1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.location; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.junit.Assert.assertThrows; 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.ArgumentMatchers.anyInt; 24 import static org.mockito.ArgumentMatchers.anyString; 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.MockitoAnnotations.initMocks; 28 29 import android.app.AppOpsManager; 30 import android.content.Context; 31 import android.content.pm.PackageManager; 32 import android.content.res.Resources; 33 import android.location.ILocationListener; 34 import android.location.LocationManagerInternal; 35 import android.location.LocationRequest; 36 import android.location.provider.ProviderRequest; 37 import android.os.IBinder; 38 import android.os.PowerManager; 39 import android.platform.test.annotations.Presubmit; 40 41 import androidx.test.ext.junit.runners.AndroidJUnit4; 42 import androidx.test.filters.SmallTest; 43 import androidx.test.platform.app.InstrumentationRegistry; 44 45 import com.android.server.LocalServices; 46 import com.android.server.location.injector.FakeUserInfoHelper; 47 import com.android.server.location.injector.TestInjector; 48 import com.android.server.location.provider.AbstractLocationProvider; 49 import com.android.server.location.provider.LocationProviderManager; 50 import com.android.server.pm.permission.LegacyPermissionManagerInternal; 51 52 import com.google.common.util.concurrent.MoreExecutors; 53 54 import org.junit.After; 55 import org.junit.Before; 56 import org.junit.Ignore; 57 import org.junit.Test; 58 import org.junit.runner.RunWith; 59 import org.mockito.Mock; 60 import org.mockito.Spy; 61 62 import java.util.Collections; 63 64 @Presubmit 65 @SmallTest 66 @RunWith(AndroidJUnit4.class) 67 public class LocationManagerServiceTest { 68 private static final String PROVIDER_WITH_PERMISSION = "provider_with_permission"; 69 private static final String PROVIDER_WITHOUT_PERMISSION = "provider_without_permission"; 70 private static final int CURRENT_USER = FakeUserInfoHelper.DEFAULT_USERID; 71 private static final String CALLER_PACKAGE = "caller_package"; 72 private static final String MISSING_PERMISSION = "missing_permission"; 73 private static final String ATTRIBUTION_TAG = "test_tag"; 74 75 private TestInjector mInjector; 76 private LocationManagerService mLocationManagerService; 77 78 @Spy private FakeAbstractLocationProvider mProviderWithPermission; 79 @Spy private FakeAbstractLocationProvider mProviderWithoutPermission; 80 @Mock private ILocationListener mLocationListener; 81 @Mock private IBinder mBinder; 82 @Mock private Context mContext; 83 @Mock private Resources mResources; 84 @Mock private PackageManager mPackageManager; 85 @Mock private AppOpsManager mAppOpsManager; 86 @Mock private PowerManager mPowerManager; 87 @Mock private PowerManager.WakeLock mWakeLock; 88 @Mock private LegacyPermissionManagerInternal mPermissionManagerInternal; 89 90 @Before setUp()91 public void setUp() { 92 initMocks(this); 93 94 doReturn(mContext).when(mContext).createAttributionContext(any()); 95 doReturn("android").when(mContext).getPackageName(); 96 doReturn(mResources).when(mContext).getResources(); 97 doReturn(mPackageManager).when(mContext).getPackageManager(); 98 doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class); 99 doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString()); 100 doReturn(mAppOpsManager).when(mContext).getSystemService(AppOpsManager.class); 101 String[] packages = {CALLER_PACKAGE}; 102 doReturn(InstrumentationRegistry.getInstrumentation().getContext().getContentResolver()) 103 .when(mContext) 104 .getContentResolver(); 105 doReturn(packages).when(mPackageManager).getPackagesForUid(anyInt()); 106 doReturn(mBinder).when(mLocationListener).asBinder(); 107 doReturn(PackageManager.PERMISSION_DENIED) 108 .when(mContext) 109 .checkCallingOrSelfPermission(MISSING_PERMISSION); 110 111 mInjector = new TestInjector(mContext); 112 mInjector.getUserInfoHelper().setUserVisible(CURRENT_USER, true); 113 114 LocalServices.addService(LegacyPermissionManagerInternal.class, mPermissionManagerInternal); 115 116 mLocationManagerService = new LocationManagerService(mContext, mInjector); 117 118 LocationProviderManager managerWithPermission = 119 new LocationProviderManager( 120 mContext, mInjector, PROVIDER_WITH_PERMISSION, /* passiveManager= */ null); 121 mLocationManagerService.addLocationProviderManager( 122 managerWithPermission, mProviderWithPermission); 123 LocationProviderManager managerWithoutPermission = 124 new LocationProviderManager( 125 mContext, 126 mInjector, 127 PROVIDER_WITHOUT_PERMISSION, 128 /* passiveManager= */ null, 129 Collections.singletonList(MISSING_PERMISSION)); 130 mLocationManagerService.addLocationProviderManager( 131 managerWithoutPermission, mProviderWithoutPermission); 132 } 133 134 @After tearDown()135 public void tearDown() throws Exception { 136 LocalServices.removeServiceForTest(LegacyPermissionManagerInternal.class); 137 LocalServices.removeServiceForTest(LocationManagerInternal.class); 138 } 139 140 @Test 141 @Ignore("b/274432939") // Test is flaky for as of yet unknown reasons testRequestLocationUpdates()142 public void testRequestLocationUpdates() { 143 LocationRequest request = new LocationRequest.Builder(0).build(); 144 mLocationManagerService.registerLocationListener( 145 PROVIDER_WITH_PERMISSION, 146 request, 147 mLocationListener, 148 CALLER_PACKAGE, 149 ATTRIBUTION_TAG, 150 "any_listener_id"); 151 verify(mProviderWithPermission).onSetRequestPublic(any()); 152 } 153 154 @Test testRequestLocationUpdates_noPermission()155 public void testRequestLocationUpdates_noPermission() { 156 LocationRequest request = new LocationRequest.Builder(0).build(); 157 assertThrows( 158 IllegalArgumentException.class, 159 () -> 160 mLocationManagerService.registerLocationListener( 161 PROVIDER_WITHOUT_PERMISSION, 162 request, 163 mLocationListener, 164 CALLER_PACKAGE, 165 ATTRIBUTION_TAG, 166 "any_listener_id")); 167 } 168 169 @Test testHasProvider()170 public void testHasProvider() { 171 assertThat(mLocationManagerService.hasProvider(PROVIDER_WITH_PERMISSION)).isTrue(); 172 } 173 174 @Test testHasProvider_noPermission()175 public void testHasProvider_noPermission() { 176 assertThat(mLocationManagerService.hasProvider(PROVIDER_WITHOUT_PERMISSION)).isFalse(); 177 } 178 179 @Test testGetAllProviders()180 public void testGetAllProviders() { 181 assertThat(mLocationManagerService.getAllProviders()).contains(PROVIDER_WITH_PERMISSION); 182 assertThat(mLocationManagerService.getAllProviders()) 183 .doesNotContain(PROVIDER_WITHOUT_PERMISSION); 184 } 185 186 abstract static class FakeAbstractLocationProvider extends AbstractLocationProvider { FakeAbstractLocationProvider()187 FakeAbstractLocationProvider() { 188 super( 189 MoreExecutors.directExecutor(), 190 /* identity= */ null, 191 /* properties= */ null, 192 /* extraAttributionTags= */ Collections.emptySet()); 193 setAllowed(true); 194 } 195 196 @Override onSetRequest(ProviderRequest request)197 protected void onSetRequest(ProviderRequest request) { 198 // Call a public version of this method so mockito can verify. 199 onSetRequestPublic(request); 200 } 201 onSetRequestPublic(ProviderRequest request)202 public abstract void onSetRequestPublic(ProviderRequest request); 203 } 204 } 205