1 /*
2  * Copyright (C) 2008 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 android.location.cts.fine;
18 
19 import static android.Manifest.permission.LOCATION_BYPASS;
20 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
21 import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
22 import static android.app.AppOpsManager.OPSTR_FINE_LOCATION_SOURCE;
23 import static android.app.AppOpsManager.OPSTR_MONITOR_HIGH_POWER_LOCATION;
24 import static android.app.AppOpsManager.OPSTR_MONITOR_LOCATION;
25 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
26 import static android.location.LocationManager.EXTRA_PROVIDER_ENABLED;
27 import static android.location.LocationManager.EXTRA_PROVIDER_NAME;
28 import static android.location.LocationManager.FUSED_PROVIDER;
29 import static android.location.LocationManager.GPS_PROVIDER;
30 import static android.location.LocationManager.NETWORK_PROVIDER;
31 import static android.location.LocationManager.PASSIVE_PROVIDER;
32 import static android.location.LocationManager.PROVIDERS_CHANGED_ACTION;
33 import static android.location.LocationRequest.PASSIVE_INTERVAL;
34 import static android.location.LocationRequest.QUALITY_HIGH_ACCURACY;
35 import static android.location.provider.ProviderProperties.ACCURACY_FINE;
36 import static android.location.provider.ProviderProperties.POWER_USAGE_HIGH;
37 
38 import static androidx.test.ext.truth.content.IntentSubject.assertThat;
39 import static androidx.test.ext.truth.location.LocationSubject.assertThat;
40 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
41 
42 import static com.android.compatibility.common.util.LocationUtils.createLocation;
43 
44 import static com.google.common.truth.Truth.assertThat;
45 
46 import static org.junit.Assert.fail;
47 import static org.junit.Assume.assumeTrue;
48 
49 import android.Manifest;
50 import android.app.ActivityManager;
51 import android.app.AppOpsManager;
52 import android.app.PendingIntent;
53 import android.app.UiAutomation;
54 import android.content.Context;
55 import android.content.Intent;
56 import android.location.Criteria;
57 import android.location.GnssMeasurementsEvent;
58 import android.location.GnssNavigationMessage;
59 import android.location.GnssStatus;
60 import android.location.LastLocationRequest;
61 import android.location.Location;
62 import android.location.LocationListener;
63 import android.location.LocationManager;
64 import android.location.LocationProvider;
65 import android.location.LocationRequest;
66 import android.location.OnNmeaMessageListener;
67 import android.location.cts.common.BroadcastCapture;
68 import android.location.cts.common.GetCurrentLocationCapture;
69 import android.location.cts.common.LocationListenerCapture;
70 import android.location.cts.common.LocationPendingIntentCapture;
71 import android.location.cts.common.OpActiveChangedCapture;
72 import android.location.cts.common.ProviderRequestChangedListenerCapture;
73 import android.location.cts.common.gnss.GnssAntennaInfoCapture;
74 import android.location.cts.common.gnss.GnssMeasurementsCapture;
75 import android.location.cts.common.gnss.GnssNavigationMessageCapture;
76 import android.location.provider.ProviderProperties;
77 import android.os.Build;
78 import android.os.HandlerThread;
79 import android.os.Looper;
80 import android.os.Process;
81 import android.os.SystemClock;
82 import android.os.SystemProperties;
83 import android.platform.test.annotations.AppModeFull;
84 import android.platform.test.annotations.AppModeNonSdkSandbox;
85 import android.provider.DeviceConfig;
86 import android.util.Log;
87 
88 import androidx.test.core.app.ApplicationProvider;
89 import androidx.test.ext.junit.runners.AndroidJUnit4;
90 import androidx.test.platform.app.InstrumentationRegistry;
91 
92 import com.android.compatibility.common.util.DeviceConfigStateHelper;
93 import com.android.compatibility.common.util.LocationUtils;
94 import com.android.compatibility.common.util.UserHelper;
95 
96 import org.junit.After;
97 import org.junit.Before;
98 import org.junit.Test;
99 import org.junit.runner.RunWith;
100 
101 import java.util.HashSet;
102 import java.util.List;
103 import java.util.Objects;
104 import java.util.Random;
105 import java.util.concurrent.Executors;
106 
107 @RunWith(AndroidJUnit4.class)
108 public class LocationManagerFineTest {
109 
110     private static final String TAG = "LocationManagerFineTest";
111 
112     private static final long TIMEOUT_MS = 5000;
113     private static final long FAILURE_TIMEOUT_MS = 200;
114 
115     private static final String TEST_PROVIDER = "test_provider";
116 
117     private static final String VALID_LOCATION_ATTRIBUTION_TAG = "valid_location_attribution_tag";
118     private static final String ANOTHER_VALID_LOCATION_ATTRIBUTION_TAG =
119             "another_valid_location_attribution_tag";
120 
121     private static final String IGNORE_SETTINGS_ALLOWLIST = "ignore_settings_allowlist";
122     private static final String ADAS_SETTINGS_ALLOWLIST = "adas_settings_allowlist";
123 
124     private final UserHelper mUserHelper = new UserHelper();
125     private Random mRandom;
126     private Context mContext;
127     private LocationManager mManager;
128 
129     @Before
setUp()130     public void setUp() throws Exception {
131         LocationUtils.registerMockLocationProvider(getInstrumentation(),
132                 true);
133 
134         long seed = System.currentTimeMillis();
135         Log.i(TAG, "location random seed: " + seed);
136 
137         mRandom = new Random(seed);
138         mContext = ApplicationProvider.getApplicationContext();
139         mManager = Objects.requireNonNull(mContext.getSystemService(LocationManager.class));
140 
141         for (String provider : mManager.getAllProviders()) {
142             mManager.removeTestProvider(provider);
143         }
144 
145         mManager.addTestProvider(TEST_PROVIDER,
146                 new ProviderProperties.Builder()
147                         .setHasNetworkRequirement(true)
148                         .setHasCellRequirement(true)
149                         .setPowerUsage(POWER_USAGE_HIGH)
150                         .setAccuracy(ACCURACY_FINE).build());
151         mManager.setTestProviderEnabled(TEST_PROVIDER, true);
152     }
153 
154     @After
tearDown()155     public void tearDown() throws Exception {
156         if (mManager != null) {
157             for (String provider : mManager.getAllProviders()) {
158                 mManager.removeTestProvider(provider);
159             }
160             mManager.removeTestProvider(FUSED_PROVIDER);
161         }
162 
163         LocationUtils.registerMockLocationProvider(getInstrumentation(),
164                 false);
165     }
166 
167     @Test
testIsLocationEnabled()168     public void testIsLocationEnabled() {
169         assertThat(mManager.isLocationEnabled()).isTrue();
170     }
171 
172     @Test
testIsProviderEnabled()173     public void testIsProviderEnabled() {
174         assertThat(mManager.isProviderEnabled(TEST_PROVIDER)).isTrue();
175 
176         mManager.setTestProviderEnabled(TEST_PROVIDER, false);
177         assertThat(mManager.isProviderEnabled(TEST_PROVIDER)).isFalse();
178 
179         mManager.setTestProviderEnabled(TEST_PROVIDER, true);
180         assertThat(mManager.isProviderEnabled(TEST_PROVIDER)).isTrue();
181 
182         for (String provider : mManager.getAllProviders()) {
183             mManager.isProviderEnabled(provider);
184         }
185 
186         try {
187             mManager.isProviderEnabled(null);
188             fail("Should throw IllegalArgumentException if provider is null!");
189         } catch (IllegalArgumentException e) {
190             // expected
191         }
192     }
193 
194     @Test
195     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetLastKnownLocation()196     public void testGetLastKnownLocation() {
197         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
198         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
199 
200         mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
201         assertThat(mManager.getLastKnownLocation(TEST_PROVIDER)).isEqualTo(loc1);
202 
203         mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
204         assertThat(mManager.getLastKnownLocation(TEST_PROVIDER)).isEqualTo(loc2);
205 
206         mManager.setTestProviderEnabled(TEST_PROVIDER, false);
207         assertThat(mManager.getLastKnownLocation(TEST_PROVIDER)).isNull();
208 
209         try {
210             mManager.getLastKnownLocation(null);
211             fail("Should throw IllegalArgumentException if provider is null!");
212         } catch (IllegalArgumentException e) {
213             // expected
214         }
215     }
216 
217     @Test
218     @AppModeFull(reason = "Instant apps can't hold INTERACT_ACROSS_USERS permission")
testGetLastKnownLocation_AdasLocationSettingsOn()219     public void testGetLastKnownLocation_AdasLocationSettingsOn() throws Exception {
220         assumeTrue(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
221 
222         try (DeviceConfigStateHelper locationDeviceConfigStateHelper =
223                      new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_LOCATION)) {
224 
225             locationDeviceConfigStateHelper.set(ADAS_SETTINGS_ALLOWLIST, mContext.getPackageName());
226 
227             mManager.addTestProvider(GPS_PROVIDER, new ProviderProperties.Builder().build());
228 
229             Location loc = createLocation(GPS_PROVIDER, mRandom);
230             mManager.setTestProviderLocation(GPS_PROVIDER, loc);
231 
232             mManager.setTestProviderEnabled(GPS_PROVIDER, true);
233 
234             getInstrumentation()
235                     .getUiAutomation()
236                     .adoptShellPermissionIdentity(LOCATION_BYPASS, WRITE_SECURE_SETTINGS);
237 
238             try {
239                 mManager.setLocationEnabledForUser(false, mContext.getUser());
240                 mManager.setAdasGnssLocationEnabled(true);
241 
242                 if (ActivityManager.getCurrentUser() == Process.myUserHandle().myUserId()) {
243                     assertThat(
244                             mManager.getLastKnownLocation(
245                                     GPS_PROVIDER,
246                                     new LastLocationRequest.Builder()
247                                             .setAdasGnssBypass(true)
248                                             .build()))
249                             .isEqualTo(loc);
250                 } else if (mUserHelper.isVisibleBackgroundUser()) {
251                     assertThat(
252                             mManager.getLastKnownLocation(
253                                     GPS_PROVIDER,
254                                     new LastLocationRequest.Builder()
255                                             .setAdasGnssBypass(true)
256                                             .build()))
257                             .isNull();
258                 }
259             } finally {
260                 mManager.setLocationEnabledForUser(true, Process.myUserHandle());
261                 getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
262             }
263         }
264     }
265 
266     @Test
testGetLastKnownLocation_AdasLocationSettingsOff()267     public void testGetLastKnownLocation_AdasLocationSettingsOff() throws Exception {
268         assumeTrue(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
269 
270         try (DeviceConfigStateHelper locationDeviceConfigStateHelper =
271                      new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_LOCATION)) {
272 
273             locationDeviceConfigStateHelper.set(ADAS_SETTINGS_ALLOWLIST, mContext.getPackageName());
274 
275             mManager.addTestProvider(GPS_PROVIDER, new ProviderProperties.Builder().build());
276 
277             Location loc = createLocation(GPS_PROVIDER, mRandom);
278             mManager.setTestProviderLocation(GPS_PROVIDER, loc);
279 
280             mManager.setTestProviderEnabled(GPS_PROVIDER, true);
281 
282             getInstrumentation()
283                     .getUiAutomation()
284                     .adoptShellPermissionIdentity(LOCATION_BYPASS, WRITE_SECURE_SETTINGS);
285 
286             try {
287                 // Returns null when ADAS toggle is off
288                 mManager.setAdasGnssLocationEnabled(false);
289                 mManager.setLocationEnabledForUser(false, mContext.getUser());
290 
291                 assertThat(
292                         mManager.getLastKnownLocation(
293                                 GPS_PROVIDER,
294                                 new LastLocationRequest.Builder()
295                                         .setAdasGnssBypass(true)
296                                         .build()))
297                         .isNull();
298             } finally {
299                 mManager.setLocationEnabledForUser(true, Process.myUserHandle());
300                 mManager.setAdasGnssLocationEnabled(true);
301                 getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
302             }
303         }
304     }
305 
306     @Test
307     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetLastKnownLocation_RemoveProvider()308     public void testGetLastKnownLocation_RemoveProvider() {
309         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
310 
311         mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
312         mManager.removeTestProvider(TEST_PROVIDER);
313         assertThat(mManager.getLastKnownLocation(TEST_PROVIDER)).isNull();
314     }
315 
316     @Test
317     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetLastKnownLocation_NoteOp()318     public void testGetLastKnownLocation_NoteOp() {
319         // Ensure no note ops for null location
320         long timeBeforeLocationAccess = System.currentTimeMillis();
321         mManager.getLastKnownLocation(TEST_PROVIDER);
322         assertFineOpNotNoted(timeBeforeLocationAccess, null);
323 
324         mManager.setTestProviderLocation(TEST_PROVIDER, createLocation(TEST_PROVIDER, mRandom));
325         timeBeforeLocationAccess = System.currentTimeMillis();
326         mManager.getLastKnownLocation(TEST_PROVIDER);
327         assertFineOpNoted(timeBeforeLocationAccess, null);
328 
329         // Ensure no note ops when provider disabled
330         mManager.setTestProviderEnabled(TEST_PROVIDER, false);
331         timeBeforeLocationAccess = System.currentTimeMillis();
332         mManager.getLastKnownLocation(TEST_PROVIDER);
333         assertFineOpNotNoted(timeBeforeLocationAccess, null);
334     }
335 
336     @Test
337     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetCurrentLocation()338     public void testGetCurrentLocation() throws Exception {
339         Location loc = createLocation(TEST_PROVIDER, mRandom);
340 
341         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
342             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
343                     Executors.newSingleThreadExecutor(), capture);
344             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
345             assertThat(capture.getLocation(TIMEOUT_MS)).isEqualTo(loc);
346         }
347 
348         try {
349             mManager.getCurrentLocation((String) null, null, Executors.newSingleThreadExecutor(),
350                     (location) -> {});
351             fail("Should throw IllegalArgumentException if provider is null!");
352         } catch (IllegalArgumentException e) {
353             // expected
354         }
355     }
356 
357     @Test
358     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetCurrentLocation_Timeout()359     public void testGetCurrentLocation_Timeout() throws Exception {
360         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
361             mManager.getCurrentLocation(
362                     TEST_PROVIDER,
363                     new LocationRequest.Builder(0).setDurationMillis(500).build(),
364                     capture.getCancellationSignal(),
365                     Executors.newSingleThreadExecutor(),
366                     capture);
367             assertThat(capture.getLocation(1000)).isNull();
368         }
369 
370         try {
371             mManager.getCurrentLocation((String) null, null, Executors.newSingleThreadExecutor(),
372                     (location) -> {});
373             fail("Should throw IllegalArgumentException if provider is null!");
374         } catch (IllegalArgumentException e) {
375             // expected
376         }
377     }
378 
379     @Test
380     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetCurrentLocation_FreshOldLocation()381     public void testGetCurrentLocation_FreshOldLocation() throws Exception {
382         Location loc = createLocation(TEST_PROVIDER, mRandom);
383 
384         mManager.setTestProviderLocation(TEST_PROVIDER, loc);
385         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
386             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
387                     Executors.newSingleThreadExecutor(), capture);
388             assertThat(capture.getLocation(TIMEOUT_MS)).isEqualTo(loc);
389         }
390     }
391 
392     @Test
393     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetCurrentLocation_DirectExecutor()394     public void testGetCurrentLocation_DirectExecutor() throws Exception {
395         Location loc = createLocation(TEST_PROVIDER, mRandom);
396 
397         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
398             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
399                     Runnable::run, capture);
400             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
401             assertThat(capture.getLocation(TIMEOUT_MS)).isEqualTo(loc);
402         }
403     }
404 
405     @Test
406     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetCurrentLocation_Cancellation()407     public void testGetCurrentLocation_Cancellation() throws Exception {
408         Location loc = createLocation(TEST_PROVIDER, mRandom);
409 
410         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
411             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
412                     Executors.newSingleThreadExecutor(), capture);
413             capture.getCancellationSignal().cancel();
414             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
415             assertThat(capture.hasLocation(FAILURE_TIMEOUT_MS)).isFalse();
416         }
417     }
418 
419     @Test
420     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetCurrentLocation_ProviderDisabled()421     public void testGetCurrentLocation_ProviderDisabled() throws Exception {
422         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
423             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
424             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
425                     Executors.newSingleThreadExecutor(), capture);
426             assertThat(capture.getLocation(FAILURE_TIMEOUT_MS)).isNull();
427         }
428 
429         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
430             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
431                     Executors.newSingleThreadExecutor(), capture);
432             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
433             assertThat(capture.getLocation(FAILURE_TIMEOUT_MS)).isNull();
434         }
435     }
436 
437     @Test
438     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetCurrentLocation_NoteOps()439     public void testGetCurrentLocation_NoteOps() throws Exception {
440         long timeBeforeLocationAccess = System.currentTimeMillis();
441         Location loc = createLocation(TEST_PROVIDER, mRandom);
442 
443         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
444             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
445                     Executors.newSingleThreadExecutor(), capture);
446             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
447             assertThat(capture.getLocation(TIMEOUT_MS)).isEqualTo(loc);
448             assertFineOpNoted(timeBeforeLocationAccess, null);
449         }
450 
451         // Ensure no note ops when provider disabled
452         mManager.setTestProviderEnabled(TEST_PROVIDER, false);
453         timeBeforeLocationAccess = System.currentTimeMillis();
454         try (GetCurrentLocationCapture capture2 = new GetCurrentLocationCapture()) {
455             mManager.getCurrentLocation(TEST_PROVIDER, capture2.getCancellationSignal(),
456                     Executors.newSingleThreadExecutor(), capture2);
457             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
458             assertFineOpNotNoted(timeBeforeLocationAccess, null);
459         }
460     }
461 
462     @Test
463     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates()464     public void testRequestLocationUpdates() throws Exception {
465         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
466         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
467 
468         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
469             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
470                     Executors.newSingleThreadExecutor(), capture);
471 
472             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
473             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
474             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
475             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc2);
476             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
477             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.FALSE);
478             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
479             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.TRUE);
480 
481             mManager.removeUpdates(capture);
482 
483             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
484             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
485             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
486             assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
487             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
488             assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
489         }
490 
491         try {
492             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, null, Looper.getMainLooper());
493             fail("Should throw IllegalArgumentException if listener is null!");
494         } catch (IllegalArgumentException e) {
495             // expected
496         }
497 
498         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
499             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, null, capture);
500             fail("Should throw IllegalArgumentException if executor is null!");
501         } catch (IllegalArgumentException e) {
502             // expected
503         }
504 
505         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
506             mManager.requestLocationUpdates(null, 0, 0, capture, Looper.getMainLooper());
507             fail("Should throw IllegalArgumentException if provider is null!");
508         } catch (IllegalArgumentException e) {
509             // expected
510         }
511 
512         try {
513             mManager.removeUpdates((LocationListener) null);
514             fail("Should throw IllegalArgumentException if listener is null!");
515         } catch (IllegalArgumentException e) {
516             // expected
517         }
518     }
519 
520     @Test
521     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_Passive()522     public void testRequestLocationUpdates_Passive() throws Exception {
523         Location loc = createLocation(TEST_PROVIDER, mRandom);
524 
525         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
526             mManager.requestLocationUpdates(
527                     TEST_PROVIDER,
528                     new LocationRequest.Builder(PASSIVE_INTERVAL)
529                             .setMinUpdateIntervalMillis(0)
530                             .build(),
531                     Runnable::run,
532                     capture);
533             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
534             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc);
535         }
536     }
537 
538     @Test
539     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_PendingIntent()540     public void testRequestLocationUpdates_PendingIntent() throws Exception {
541         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
542         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
543 
544         try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
545             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture.getPendingIntent());
546 
547             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
548             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
549             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
550             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc2);
551             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
552             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.FALSE);
553             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
554             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.TRUE);
555 
556             mManager.removeUpdates(capture.getPendingIntent());
557 
558             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
559             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
560             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
561             assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
562             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
563             assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
564         }
565 
566         try {
567             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, (PendingIntent) null);
568             fail("Should throw IllegalArgumentException if pending intent is null!");
569         } catch (IllegalArgumentException e) {
570             // expected
571         }
572 
573         PendingIntent immutablePI = PendingIntent.getBroadcast(mContext, 0,
574                 new Intent("IMMUTABLE_TEST_ACTION")
575                         .setPackage(mContext.getPackageName())
576                         .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
577                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
578         try {
579             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, immutablePI);
580             fail("Should throw IllegalArgumentException if pending intent is immutable!");
581         } catch (IllegalArgumentException e) {
582             // expected
583         } finally {
584             immutablePI.cancel();
585         }
586 
587         try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
588             mManager.requestLocationUpdates(null, 0, 0, capture.getPendingIntent());
589             fail("Should throw IllegalArgumentException if provider is null!");
590         } catch (IllegalArgumentException e) {
591             // expected
592         }
593 
594         try {
595             mManager.removeUpdates((PendingIntent) null);
596             fail("Should throw IllegalArgumentException if pending intent is null!");
597         } catch (IllegalArgumentException e) {
598             // expected
599         }
600     }
601 
602     @Test
603     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_DirectExecutor()604     public void testRequestLocationUpdates_DirectExecutor() throws Exception {
605         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
606         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
607 
608         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
609             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Runnable::run, capture);
610 
611             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
612             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
613             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
614             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc2);
615             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
616             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.FALSE);
617             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
618             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.TRUE);
619         }
620     }
621 
622     @Test
623     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_Looper()624     public void testRequestLocationUpdates_Looper() throws Exception {
625         HandlerThread thread = new HandlerThread("locationTestThread");
626         thread.start();
627         Looper looper = thread.getLooper();
628         try {
629 
630             Location loc1 = createLocation(TEST_PROVIDER, mRandom);
631             Location loc2 = createLocation(TEST_PROVIDER, mRandom);
632 
633             try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
634                 mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture, looper);
635 
636                 mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
637                 assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
638                 mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
639                 assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc2);
640                 mManager.setTestProviderEnabled(TEST_PROVIDER, false);
641                 assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.FALSE);
642                 mManager.setTestProviderEnabled(TEST_PROVIDER, true);
643                 assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.TRUE);
644             }
645 
646         } finally {
647             looper.quit();
648         }
649     }
650 
651     @SuppressWarnings("deprecation")
652     @Test
653     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_Criteria()654     public void testRequestLocationUpdates_Criteria() throws Exception {
655         // criteria API will always use the fused provider...
656         mManager.addTestProvider(FUSED_PROVIDER,
657                 false,
658                 false,
659                 false,
660                 false,
661                 true,
662                 true,
663                 true,
664                 Criteria.POWER_LOW,
665                 Criteria.ACCURACY_FINE);
666         mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
667 
668         Criteria criteria = new Criteria();
669         criteria.setAccuracy(Criteria.ACCURACY_FINE);
670         criteria.setPowerRequirement(Criteria.POWER_LOW);
671 
672         Location loc1 = createLocation(FUSED_PROVIDER, mRandom);
673         Location loc2 = createLocation(FUSED_PROVIDER, mRandom);
674 
675         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
676             mManager.requestLocationUpdates(0, 0, criteria, Executors.newSingleThreadExecutor(), capture);
677 
678             mManager.setTestProviderLocation(FUSED_PROVIDER, loc1);
679             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
680             mManager.setTestProviderLocation(FUSED_PROVIDER, loc2);
681             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc2);
682             mManager.setTestProviderEnabled(FUSED_PROVIDER, false);
683             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.FALSE);
684             mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
685             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(Boolean.TRUE);
686 
687             mManager.removeUpdates(capture);
688 
689             mManager.setTestProviderLocation(FUSED_PROVIDER, loc1);
690             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
691             mManager.setTestProviderEnabled(FUSED_PROVIDER, false);
692             assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
693             mManager.setTestProviderEnabled(FUSED_PROVIDER, true);
694             assertThat(capture.getNextProviderChange(FAILURE_TIMEOUT_MS)).isNull();
695         }
696 
697 
698         try {
699             mManager.requestLocationUpdates(0, 0, criteria, null, Looper.getMainLooper());
700             fail("Should throw IllegalArgumentException if listener is null!");
701         } catch (IllegalArgumentException e) {
702             // expected
703         }
704 
705         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
706             mManager.requestLocationUpdates(0, 0, criteria, null, capture);
707             fail("Should throw IllegalArgumentException if executor is null!");
708         } catch (IllegalArgumentException e) {
709             // expected
710         }
711 
712         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
713             mManager.requestLocationUpdates(0, 0, null, Executors.newSingleThreadExecutor(), capture);
714             fail("Should throw IllegalArgumentException if criteria is null!");
715         } catch (IllegalArgumentException e) {
716             // expected
717         }
718     }
719 
720     @Test
721     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_ReplaceRequest()722     public void testRequestLocationUpdates_ReplaceRequest() throws Exception {
723         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
724         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
725 
726         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
727             mManager.requestLocationUpdates(TEST_PROVIDER, 1000, 1000, (runnable) -> {}, capture);
728             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Executors.newSingleThreadExecutor(), capture);
729 
730             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
731             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
732             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
733             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc2);
734         }
735     }
736 
737     @Test
738     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_NumUpdates()739     public void testRequestLocationUpdates_NumUpdates() throws Exception {
740         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
741         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
742 
743         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
744             mManager.requestLocationUpdates(
745                     TEST_PROVIDER,
746                     new LocationRequest.Builder(0).setMaxUpdates(1).build(),
747                     Executors.newSingleThreadExecutor(),
748                     capture);
749 
750             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
751             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
752             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
753             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
754         }
755     }
756 
757     @Test
758     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_MinUpdateInterval()759     public void testRequestLocationUpdates_MinUpdateInterval() throws Exception {
760         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
761         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
762 
763         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
764             mManager.requestLocationUpdates(
765                     TEST_PROVIDER,
766                     new LocationRequest.Builder(5000).build(),
767                     Executors.newSingleThreadExecutor(),
768                     capture);
769 
770             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
771             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
772             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
773             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
774         }
775     }
776 
777     @Test
778     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_MinUpdateDistance()779     public void testRequestLocationUpdates_MinUpdateDistance() throws Exception {
780         Location loc1 = createLocation(TEST_PROVIDER, 0, 0, 10);
781         Location loc2 = createLocation(TEST_PROVIDER, 0, 1, 10);
782 
783         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
784             mManager.requestLocationUpdates(
785                     TEST_PROVIDER,
786                     new LocationRequest.Builder(0).setMinUpdateDistanceMeters(200000).build(),
787                     Executors.newSingleThreadExecutor(),
788                     capture);
789 
790             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
791             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
792             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
793             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
794         }
795     }
796 
797     @Test
798     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_LocationSettingsIgnored()799     public void testRequestLocationUpdates_LocationSettingsIgnored() throws Exception {
800         try (LocationListenerCapture capture = new LocationListenerCapture(mContext);
801              DeviceConfigStateHelper locationDeviceConfigStateHelper =
802                      new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_LOCATION)) {
803 
804             locationDeviceConfigStateHelper.set(IGNORE_SETTINGS_ALLOWLIST,
805                     mContext.getPackageName());
806 
807             getInstrumentation().getUiAutomation()
808                     .adoptShellPermissionIdentity(LOCATION_BYPASS);
809             try {
810                 mManager.requestLocationUpdates(
811                         TEST_PROVIDER,
812                         new LocationRequest.Builder(0)
813                                 .setLocationSettingsIgnored(true)
814                                 .build(),
815                         Executors.newSingleThreadExecutor(),
816                         capture);
817             } finally {
818                 getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
819             }
820 
821             // turn off provider
822             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
823 
824             // test that all restrictions are bypassed
825             Location loc = createLocation(TEST_PROVIDER, mRandom);
826             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
827             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isEqualTo(loc);
828             loc = createLocation(TEST_PROVIDER, mRandom);
829             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
830             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isEqualTo(loc);
831         }
832     }
833 
834     @Test
835     @AppModeFull(reason = "Instant apps can't hold INTERACT_ACROSS_USERS permission")
testRequestLocationUpdates_AdasGnssBypass()836     public void testRequestLocationUpdates_AdasGnssBypass() throws Exception {
837         assumeTrue(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
838 
839         try (LocationListenerCapture capture = new LocationListenerCapture(mContext);
840              DeviceConfigStateHelper locationDeviceConfigStateHelper =
841                      new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_LOCATION)) {
842 
843             locationDeviceConfigStateHelper.set(ADAS_SETTINGS_ALLOWLIST, mContext.getPackageName());
844 
845             mManager.addTestProvider(GPS_PROVIDER, new ProviderProperties.Builder().build());
846 
847             getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(LOCATION_BYPASS);
848             try {
849                 mManager.requestLocationUpdates(
850                         GPS_PROVIDER,
851                         new LocationRequest.Builder(0).setAdasGnssBypass(true).build(),
852                         Executors.newSingleThreadExecutor(),
853                         capture);
854             } finally {
855                 getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
856             }
857 
858             // turn off provider
859             mManager.setTestProviderEnabled(GPS_PROVIDER, false);
860 
861             if (ActivityManager.getCurrentUser() == Process.myUserHandle().myUserId()) {
862                 // test that all restrictions are bypassed
863                 Location loc = createLocation(GPS_PROVIDER, mRandom);
864                 mManager.setTestProviderLocation(GPS_PROVIDER, loc);
865                 assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isEqualTo(loc);
866                 loc = createLocation(GPS_PROVIDER, mRandom);
867                 mManager.setTestProviderLocation(GPS_PROVIDER, loc);
868                 assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isEqualTo(loc);
869             } else if (mUserHelper.isVisibleBackgroundUser()) {
870                 // test restrictions aren't bypassed.
871                 Location loc = createLocation(GPS_PROVIDER, mRandom);
872                 mManager.setTestProviderLocation(GPS_PROVIDER, loc);
873                 assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
874                 loc = createLocation(GPS_PROVIDER, mRandom);
875                 mManager.setTestProviderLocation(GPS_PROVIDER, loc);
876                 assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
877             }
878         }
879     }
880 
881     @Test
882     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_NoteOps()883     public void testRequestLocationUpdates_NoteOps() throws Exception {
884         long timeBeforeLocationAccess = System.currentTimeMillis();
885         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
886 
887         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
888             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
889                     Executors.newSingleThreadExecutor(), capture);
890 
891             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
892             assertThat(capture.getNextLocation(TIMEOUT_MS)).isEqualTo(loc1);
893             assertFineOpNoted(timeBeforeLocationAccess,
894                     null);
895         }
896 
897         // Ensure no note ops when provider disabled
898         mManager.setTestProviderEnabled(TEST_PROVIDER, false);
899         timeBeforeLocationAccess = System.currentTimeMillis();
900         try (LocationListenerCapture capture2 = new LocationListenerCapture(mContext)) {
901             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
902                     Executors.newSingleThreadExecutor(), capture2);
903             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
904             assertFineOpNotNoted(timeBeforeLocationAccess, null);
905         }
906     }
907 
908     @Test
909     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestLocationUpdates_NoteOps_simultaneousRequests()910     public void testRequestLocationUpdates_NoteOps_simultaneousRequests() {
911         Context attributionContextFast =
912                 mContext.createAttributionContext(VALID_LOCATION_ATTRIBUTION_TAG);
913         Context attributionContextSlow =
914                 mContext.createAttributionContext(ANOTHER_VALID_LOCATION_ATTRIBUTION_TAG);
915         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
916         loc1.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos() - 100000000L);
917         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
918         loc2.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos() - 100000000L);
919 
920         try (LocationListenerCapture fastCapture =
921                      new LocationListenerCapture(attributionContextFast);
922                 LocationListenerCapture slowCapture =
923                      new LocationListenerCapture(attributionContextSlow)) {
924             Objects.requireNonNull(attributionContextFast.getSystemService(LocationManager.class))
925                     .requestLocationUpdates(
926                             TEST_PROVIDER,
927                             new LocationRequest.Builder(0).build(),
928                             Runnable::run,
929                             fastCapture);
930             Objects.requireNonNull(attributionContextSlow.getSystemService(LocationManager.class))
931                     .requestLocationUpdates(
932                             TEST_PROVIDER,
933                             new LocationRequest.Builder(100).build(),
934                             Runnable::run,
935                             slowCapture);
936 
937             // Set initial location.
938             long timeBeforeLocationAccess = System.currentTimeMillis();
939             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
940             assertFineOpNoted(timeBeforeLocationAccess, VALID_LOCATION_ATTRIBUTION_TAG);
941 
942             // Verify noteOp for the fast request.
943             timeBeforeLocationAccess = System.currentTimeMillis();
944             mManager.setTestProviderLocation(TEST_PROVIDER, loc2);
945             assertFineOpNoted(timeBeforeLocationAccess, VALID_LOCATION_ATTRIBUTION_TAG);
946             assertFineOpNotNoted(timeBeforeLocationAccess, ANOTHER_VALID_LOCATION_ATTRIBUTION_TAG);
947 
948             // Verify noteOp for the slow request.
949             timeBeforeLocationAccess = System.currentTimeMillis();
950             Location loc3 = createLocation(TEST_PROVIDER, mRandom);
951             mManager.setTestProviderLocation(TEST_PROVIDER, loc3);
952             assertFineOpNoted(timeBeforeLocationAccess, ANOTHER_VALID_LOCATION_ATTRIBUTION_TAG);
953         }
954     }
955 
956     @Test
957     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testMonitoring()958     public void testMonitoring() throws Exception {
959         AppOpsManager appOps = Objects.requireNonNull(
960                 mContext.getSystemService(AppOpsManager.class));
961 
962         try (OpActiveChangedCapture opCapture = new OpActiveChangedCapture(appOps,
963                 OPSTR_MONITOR_LOCATION);
964              OpActiveChangedCapture opHighPowerCapture = new OpActiveChangedCapture(appOps,
965                      OPSTR_MONITOR_HIGH_POWER_LOCATION);
966              LocationListenerCapture capture1 = new LocationListenerCapture(mContext);
967              LocationListenerCapture capture2 = new LocationListenerCapture(mContext);
968              LocationListenerCapture capture3 = new LocationListenerCapture(mContext)) {
969             appOps.startWatchingActive(new String[]{OPSTR_MONITOR_LOCATION}, Runnable::run,
970                     opCapture);
971             appOps.startWatchingActive(new String[]{OPSTR_MONITOR_HIGH_POWER_LOCATION},
972                     Runnable::run, opHighPowerCapture);
973 
974             mManager.requestLocationUpdates(TEST_PROVIDER,
975                     new LocationRequest.Builder(Long.MAX_VALUE - 1).build(),
976                     Executors.newSingleThreadExecutor(), capture1);
977             assertThat(opCapture.getNextActive(TIMEOUT_MS)).isTrue();
978             assertThat(opHighPowerCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
979 
980             mManager.requestLocationUpdates(TEST_PROVIDER, new LocationRequest.Builder(
981                             0).setQuality(
982                             QUALITY_HIGH_ACCURACY).build(),
983                     Executors.newSingleThreadExecutor(), capture2);
984             assertThat(opCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
985             assertThat(opHighPowerCapture.getNextActive(TIMEOUT_MS)).isTrue();
986 
987             mManager.requestLocationUpdates(TEST_PROVIDER, new LocationRequest.Builder(
988                             0).setQuality(
989                             QUALITY_HIGH_ACCURACY).build(),
990                     Executors.newSingleThreadExecutor(), capture3);
991             assertThat(opCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
992             assertThat(opHighPowerCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
993 
994             mManager.removeUpdates(capture2);
995             assertThat(opCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
996             assertThat(opHighPowerCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
997 
998             mManager.removeUpdates(capture3);
999             assertThat(opCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
1000             assertThat(opHighPowerCapture.getNextActive(TIMEOUT_MS)).isFalse();
1001 
1002             mManager.removeUpdates(capture1);
1003             assertThat(opCapture.getNextActive(TIMEOUT_MS)).isFalse();
1004             assertThat(opHighPowerCapture.getNextActive(FAILURE_TIMEOUT_MS)).isNull();
1005         }
1006     }
1007 
1008     @Test
1009     @AppModeFull(reason = "Instant apps can't hold INTERACT_ACROSS_USERS permission")
testAddProviderRequestListener()1010     public void testAddProviderRequestListener() throws Exception {
1011         InstrumentationRegistry.getInstrumentation().getUiAutomation()
1012                 .adoptShellPermissionIdentity(Manifest.permission.LOCATION_HARDWARE);
1013 
1014         try (ProviderRequestChangedListenerCapture requestlistener =
1015                      new ProviderRequestChangedListenerCapture(mContext);
1016              LocationListenerCapture locationListener = new LocationListenerCapture(mContext)) {
1017             mManager.addProviderRequestChangedListener(Executors.newSingleThreadExecutor(),
1018                     requestlistener);
1019             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
1020                     Executors.newSingleThreadExecutor(), locationListener);
1021 
1022             assertThat(requestlistener.getNextProviderRequest(TIMEOUT_MS)).isNotNull();
1023         } finally {
1024             InstrumentationRegistry.getInstrumentation().getUiAutomation()
1025                     .dropShellPermissionIdentity();
1026         }
1027     }
1028 
1029     @Test
1030     @AppModeFull(reason = "Instant apps can't hold ACCESS_LOCATION_EXTRA_COMMANDS permission")
testRequestGpsUpdates_B9758659()1031     public void testRequestGpsUpdates_B9758659() throws Exception {
1032         assumeTrue(mManager.hasProvider(GPS_PROVIDER));
1033 
1034         // test for b/9758659, where the gps provider may reuse network provider positions creating
1035         // an unnatural feedback loop
1036         assertThat(mManager.isProviderEnabled(GPS_PROVIDER)).isTrue();
1037 
1038         Location networkLocation = createLocation(NETWORK_PROVIDER, mRandom);
1039 
1040         mManager.addTestProvider(NETWORK_PROVIDER, new ProviderProperties.Builder().build());
1041 
1042         mManager.setTestProviderEnabled(NETWORK_PROVIDER, true);
1043         mManager.setTestProviderLocation(NETWORK_PROVIDER, networkLocation);
1044 
1045         // reset gps provider to give it a cold start scenario
1046         mManager.sendExtraCommand(GPS_PROVIDER, "delete_aiding_data", null);
1047 
1048         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1049             mManager.requestLocationUpdates(
1050                     GPS_PROVIDER,
1051                     new LocationRequest.Builder(0).build(),
1052                     Executors.newSingleThreadExecutor(),
1053                     capture);
1054 
1055             Location location = capture.getNextLocation(TIMEOUT_MS);
1056             if (location != null) {
1057                 assertThat(location.distanceTo(networkLocation)).isGreaterThan(1000.0f);
1058             }
1059         }
1060     }
1061 
1062     @Test
1063     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestFlush()1064     public void testRequestFlush() throws Exception {
1065         try (LocationListenerCapture capture1 = new LocationListenerCapture(mContext);
1066              LocationListenerCapture capture2 = new LocationListenerCapture(mContext)) {
1067             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
1068                     Executors.newSingleThreadExecutor(), capture1);
1069             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
1070                     Executors.newSingleThreadExecutor(), capture2);
1071 
1072             mManager.requestFlush(TEST_PROVIDER, capture1, 1);
1073             mManager.requestFlush(TEST_PROVIDER, capture2, 1);
1074             assertThat(capture1.getNextFlush(TIMEOUT_MS)).isEqualTo(1);
1075             assertThat(capture2.getNextFlush(TIMEOUT_MS)).isEqualTo(1);
1076             assertThat(capture1.getNextFlush(FAILURE_TIMEOUT_MS)).isNull();
1077             assertThat(capture2.getNextFlush(FAILURE_TIMEOUT_MS)).isNull();
1078         }
1079 
1080         try {
1081             mManager.requestFlush(TEST_PROVIDER, (LocationListener) null, 0);
1082             fail("Should throw IllegalArgumentException if listener is null!");
1083         } catch (IllegalArgumentException e) {
1084             // expected
1085         }
1086 
1087         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1088             mManager.requestFlush(TEST_PROVIDER, capture, 0);
1089             fail("Should throw IllegalArgumentException if listener is not registered!");
1090         } catch (IllegalArgumentException e) {
1091             // expected
1092         }
1093 
1094         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1095             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Executors.newSingleThreadExecutor(), capture);
1096             mManager.requestFlush(GPS_PROVIDER, capture, 0);
1097             fail("Should throw IllegalArgumentException if listener is not registered!");
1098         } catch (IllegalArgumentException e) {
1099             // expected
1100         }
1101 
1102         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1103             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, Executors.newSingleThreadExecutor(), capture);
1104             mManager.requestFlush(null, capture, 0);
1105             fail("Should throw IllegalArgumentException if provider is null!");
1106         } catch (IllegalArgumentException e) {
1107             // expected
1108         }
1109     }
1110 
1111     @Test
testRequestFlush_PendingIntent()1112     public void testRequestFlush_PendingIntent() throws Exception {
1113         try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
1114             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture.getPendingIntent());
1115 
1116             mManager.requestFlush(TEST_PROVIDER, capture.getPendingIntent(), 1);
1117             assertThat(capture.getNextFlush(TIMEOUT_MS)).isEqualTo(1);
1118         }
1119 
1120         try {
1121             mManager.requestFlush(TEST_PROVIDER, (PendingIntent) null, 0);
1122             fail("Should throw IllegalArgumentException if pending intent is null!");
1123         } catch (IllegalArgumentException e) {
1124             // expected
1125         }
1126 
1127         try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
1128             mManager.requestFlush(TEST_PROVIDER, capture.getPendingIntent(), 0);
1129             fail("Should throw IllegalArgumentException if pending intent is not registered!");
1130         } catch (IllegalArgumentException e) {
1131             // expected
1132         }
1133 
1134         try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
1135             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture.getPendingIntent());
1136             mManager.requestFlush(GPS_PROVIDER, capture.getPendingIntent(), 0);
1137             fail("Should throw IllegalArgumentException if pending intent is not registered!");
1138         } catch (IllegalArgumentException e) {
1139             // expected
1140         }
1141 
1142         try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
1143             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture.getPendingIntent());
1144             mManager.requestFlush(null, capture.getPendingIntent(), 0);
1145             fail("Should throw IllegalArgumentException if provider is null!");
1146         } catch (IllegalArgumentException e) {
1147             // expected
1148         }
1149     }
1150 
1151     @Test
1152     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestFlush_Ordering()1153     public void testRequestFlush_Ordering() throws Exception {
1154         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1155             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
1156                     Executors.newSingleThreadExecutor(), capture);
1157 
1158             for (int i = 0; i < 100; i++) {
1159                 mManager.requestFlush(TEST_PROVIDER, capture, i);
1160             }
1161             for (int i = 0; i < 100; i++) {
1162                 assertThat(capture.getNextFlush(TIMEOUT_MS)).isEqualTo(i);
1163             }
1164         }
1165     }
1166 
1167     @Test
1168     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRequestFlush_Gnss()1169     public void testRequestFlush_Gnss() throws Exception {
1170         assumeTrue(SystemProperties.getInt("ro.product.first_api_level", 0)
1171                 >= Build.VERSION_CODES.S);
1172         assumeTrue(mManager.hasProvider(GPS_PROVIDER));
1173 
1174         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1175             mManager.requestLocationUpdates(GPS_PROVIDER, 0, 0,
1176                     Executors.newSingleThreadExecutor(), capture);
1177 
1178             mManager.requestFlush(GPS_PROVIDER, capture, 1);
1179             assertThat(capture.getNextFlush(TIMEOUT_MS)).isEqualTo(1);
1180         }
1181     }
1182 
1183     @Test
1184     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testListenProviderEnable_Listener()1185     public void testListenProviderEnable_Listener() throws Exception {
1186         try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1187             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
1188                     Executors.newSingleThreadExecutor(), capture);
1189 
1190             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1191             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(false);
1192             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
1193             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(true);
1194 
1195             mManager.removeUpdates(capture);
1196 
1197             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1198             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
1199         }
1200     }
1201 
1202     @Test
testListenProviderEnable_PendingIntent()1203     public void testListenProviderEnable_PendingIntent() throws Exception {
1204         try (LocationPendingIntentCapture capture = new LocationPendingIntentCapture(mContext)) {
1205             mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0, capture.getPendingIntent());
1206 
1207             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1208             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(false);
1209             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
1210             assertThat(capture.getNextProviderChange(TIMEOUT_MS)).isEqualTo(true);
1211 
1212             mManager.removeUpdates(capture.getPendingIntent());
1213 
1214             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1215             assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
1216         }
1217     }
1218 
1219     @Test
1220     @AppModeFull(reason = "Instant apps can only receive whitelisted broadcasts")
testListenProviderEnable_Broadcast()1221     public void testListenProviderEnable_Broadcast() throws Exception {
1222         try (BroadcastCapture capture = new BroadcastCapture(mContext, PROVIDERS_CHANGED_ACTION)) {
1223             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1224             Intent broadcast = capture.getNextIntent(TIMEOUT_MS);
1225             assertThat(broadcast).isNotNull();
1226             assertThat(broadcast).hasAction(PROVIDERS_CHANGED_ACTION);
1227             assertThat(broadcast).extras().string(EXTRA_PROVIDER_NAME).isEqualTo(TEST_PROVIDER);
1228             assertThat(broadcast).extras().bool(EXTRA_PROVIDER_ENABLED).isFalse();
1229 
1230             mManager.setTestProviderEnabled(TEST_PROVIDER, true);
1231             broadcast = capture.getNextIntent(TIMEOUT_MS);
1232             assertThat(broadcast).isNotNull();
1233             assertThat(broadcast).hasAction(PROVIDERS_CHANGED_ACTION);
1234             assertThat(broadcast).extras().string(EXTRA_PROVIDER_NAME).isEqualTo(TEST_PROVIDER);
1235             assertThat(broadcast).extras().bool(EXTRA_PROVIDER_ENABLED).isTrue();
1236         }
1237     }
1238 
1239     @Test
testGetAllProviders()1240     public void testGetAllProviders() {
1241         List<String> providers = mManager.getAllProviders();
1242         if (mManager.hasProvider(GPS_PROVIDER)) {
1243             assertThat(providers.contains(LocationManager.GPS_PROVIDER)).isTrue();
1244         }
1245         assertThat(providers.contains(PASSIVE_PROVIDER)).isTrue();
1246         assertThat(providers.contains(TEST_PROVIDER)).isTrue();
1247         assertThat(providers.size()).isEqualTo(new HashSet<>(providers).size());
1248 
1249         mManager.removeTestProvider(TEST_PROVIDER);
1250 
1251         providers = mManager.getAllProviders();
1252         assertThat(providers.contains(PASSIVE_PROVIDER)).isTrue();
1253         assertThat(providers.contains(TEST_PROVIDER)).isFalse();
1254     }
1255 
1256     @Test
1257     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetProviders()1258     public void testGetProviders() {
1259         List<String> providers = mManager.getProviders(false);
1260         assertThat(providers.contains(TEST_PROVIDER)).isTrue();
1261 
1262         providers = mManager.getProviders(true);
1263         assertThat(providers.contains(TEST_PROVIDER)).isTrue();
1264 
1265         mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1266 
1267         providers = mManager.getProviders(false);
1268         assertThat(providers.contains(TEST_PROVIDER)).isTrue();
1269 
1270         providers = mManager.getProviders(true);
1271         assertThat(providers.contains(TEST_PROVIDER)).isFalse();
1272     }
1273 
1274     @SuppressWarnings("deprecation")
1275     @Test
1276     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetProviders_Criteria()1277     public void testGetProviders_Criteria() {
1278         Criteria criteria = new Criteria();
1279 
1280         List<String> providers = mManager.getProviders(criteria, false);
1281         assertThat(providers.contains(TEST_PROVIDER)).isTrue();
1282 
1283         providers = mManager.getProviders(criteria, true);
1284         assertThat(providers.contains(TEST_PROVIDER)).isTrue();
1285 
1286         criteria.setPowerRequirement(Criteria.POWER_LOW);
1287 
1288         providers = mManager.getProviders(criteria, false);
1289         assertThat(providers.contains(TEST_PROVIDER)).isFalse();
1290 
1291         providers = mManager.getProviders(criteria, true);
1292         assertThat(providers.contains(TEST_PROVIDER)).isFalse();
1293     }
1294 
1295     @SuppressWarnings("deprecation")
1296     @Test
1297     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testGetBestProvider()1298     public void testGetBestProvider() {
1299         List<String> allProviders = mManager.getAllProviders();
1300         Criteria criteria = new Criteria();
1301 
1302         String bestProvider = mManager.getBestProvider(criteria, false);
1303         if (allProviders.contains(FUSED_PROVIDER)) {
1304             assertThat(bestProvider).isEqualTo(FUSED_PROVIDER);
1305         } else if (allProviders.contains(GPS_PROVIDER)) {
1306             assertThat(bestProvider).isEqualTo(GPS_PROVIDER);
1307         } else if (allProviders.contains(NETWORK_PROVIDER)) {
1308             assertThat(bestProvider).isEqualTo(NETWORK_PROVIDER);
1309         } else {
1310             assertThat(bestProvider).isEqualTo(TEST_PROVIDER);
1311         }
1312 
1313         // the "perfect" provider - this test case only works if there is no real provider on the
1314         // device with the same "perfect" properties
1315         mManager.addTestProvider(TEST_PROVIDER,
1316                 false,
1317                 false,
1318                 false,
1319                 false,
1320                 true,
1321                 true,
1322                 true,
1323                 Criteria.POWER_LOW,
1324                 Criteria.ACCURACY_FINE);
1325         mManager.addTestProvider(FUSED_PROVIDER,
1326                 true,
1327                 false,
1328                 true,
1329                 false,
1330                 false,
1331                 false,
1332                 false,
1333                 Criteria.POWER_HIGH,
1334                 Criteria.ACCURACY_COARSE);
1335 
1336         criteria.setAccuracy(Criteria.ACCURACY_FINE);
1337         criteria.setPowerRequirement(Criteria.POWER_LOW);
1338         assertThat(mManager.getBestProvider(criteria, false)).isEqualTo(TEST_PROVIDER);
1339 
1340         mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1341         assertThat(mManager.getBestProvider(criteria, true)).isNotEqualTo(TEST_PROVIDER);
1342     }
1343 
1344     @SuppressWarnings("deprecation")
1345     @Test
testGetProvider()1346     public void testGetProvider() {
1347         LocationProvider provider = mManager.getProvider(TEST_PROVIDER);
1348         assertThat(provider).isNotNull();
1349         assertThat(provider.getName()).isEqualTo(TEST_PROVIDER);
1350 
1351         provider = mManager.getProvider(LocationManager.GPS_PROVIDER);
1352         if (mManager.hasProvider(GPS_PROVIDER)) {
1353             assertThat(provider).isNotNull();
1354             assertThat(provider.getName()).isEqualTo(LocationManager.GPS_PROVIDER);
1355         } else {
1356             assertThat(provider).isNull();
1357         }
1358 
1359         assertThat(mManager.getProvider("fake")).isNull();
1360 
1361         try {
1362             mManager.getProvider(null);
1363             fail("Should throw IllegalArgumentException when provider is null!");
1364         } catch (IllegalArgumentException e) {
1365             // expected
1366         }
1367     }
1368 
1369     @Test
testHasProvider()1370     public void testHasProvider() {
1371         for (String provider : mManager.getAllProviders()) {
1372             assertThat(mManager.hasProvider(provider)).isTrue();
1373         }
1374 
1375         assertThat(mManager.hasProvider("fake")).isFalse();
1376     }
1377 
1378     @Test
testGetProviderProperties()1379     public void testGetProviderProperties() {
1380         for (String provider : mManager.getAllProviders()) {
1381             mManager.getProviderProperties(provider);
1382         }
1383 
1384         try {
1385             mManager.getProviderProperties("fake");
1386             fail("Should throw IllegalArgumentException for non-existent provider");
1387         } catch (IllegalArgumentException e) {
1388             // expected
1389         }
1390     }
1391 
1392     @Test
1393     @AppModeFull(reason = "Instant apps can't hold ACCESS_LOCATION_EXTRA_COMMANDS permission")
testSendExtraCommand()1394     public void testSendExtraCommand() {
1395         for (String provider : mManager.getAllProviders()) {
1396             boolean res = mManager.sendExtraCommand(provider, "dontCrash", null);
1397             assertThat(res).isTrue();
1398 
1399             try {
1400                 mManager.sendExtraCommand(provider, null, null);
1401                 fail("Should throw IllegalArgumentException if command is null!");
1402             } catch (IllegalArgumentException e) {
1403                 // expected
1404             }
1405         }
1406 
1407         try {
1408             mManager.sendExtraCommand(null, "crash", null);
1409             fail("Should throw IllegalArgumentException if provider is null!");
1410         } catch (IllegalArgumentException e) {
1411             // expected
1412         }
1413     }
1414 
1415     @Test
testAddTestProvider()1416     public void testAddTestProvider() {
1417         // overwriting providers should not crash
1418         for (String provider : mManager.getAllProviders()) {
1419             if (PASSIVE_PROVIDER.equals(provider)) {
1420                 continue;
1421             }
1422 
1423             mManager.addTestProvider(provider, new ProviderProperties.Builder().build());
1424             mManager.setTestProviderLocation(provider, createLocation(provider, mRandom));
1425         }
1426 
1427         try {
1428             mManager.addTestProvider("passive", new ProviderProperties.Builder().build());
1429             fail("Should throw IllegalArgumentException if provider is passive!");
1430         } catch (IllegalArgumentException e) {
1431             // expected
1432         }
1433 
1434         try {
1435             mManager.addTestProvider(null, new ProviderProperties.Builder().build());
1436             fail("Should throw IllegalArgumentException if provider is null!");
1437         } catch (IllegalArgumentException e) {
1438             // expected
1439         }
1440     }
1441 
1442     @Test
testSetTestProviderEnabled()1443     public void testSetTestProviderEnabled() {
1444         for (String provider : mManager.getAllProviders()) {
1445             if (TEST_PROVIDER.equals(provider)) {
1446                 mManager.setTestProviderEnabled(provider, false);
1447                 assertThat(mManager.isProviderEnabled(provider)).isFalse();
1448                 mManager.setTestProviderEnabled(provider, true);
1449                 assertThat(mManager.isProviderEnabled(provider)).isTrue();
1450             } else {
1451                 try {
1452                     mManager.setTestProviderEnabled(provider, false);
1453                     fail("Should throw IllegalArgumentException since " + provider
1454                             + " is not a test provider!");
1455                 } catch (IllegalArgumentException e) {
1456                     // expected
1457                 }
1458             }
1459         }
1460 
1461         mManager.removeTestProvider(TEST_PROVIDER);
1462         try {
1463             mManager.setTestProviderEnabled(TEST_PROVIDER, false);
1464             fail("Should throw IllegalArgumentException since " + TEST_PROVIDER
1465                     + " is not a test provider!");
1466         } catch (IllegalArgumentException e) {
1467             // expected
1468         }
1469 
1470         try {
1471             mManager.setTestProviderEnabled(null, false);
1472             fail("Should throw IllegalArgumentException since provider is null!");
1473         } catch (IllegalArgumentException e) {
1474             // expected
1475         }
1476     }
1477 
1478     @Test
1479     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testSetTestProviderLocation()1480     public void testSetTestProviderLocation() throws Exception {
1481         Location loc1 = createLocation(TEST_PROVIDER, mRandom);
1482         Location loc2 = createLocation(TEST_PROVIDER, mRandom);
1483 
1484         for (String provider : mManager.getAllProviders()) {
1485             if (TEST_PROVIDER.equals(provider)) {
1486                 try (LocationListenerCapture capture = new LocationListenerCapture(mContext)) {
1487                     mManager.requestLocationUpdates(TEST_PROVIDER, 0, 0,
1488                             Executors.newSingleThreadExecutor(), capture);
1489                     mManager.setTestProviderLocation(provider, loc1);
1490 
1491                     Location received = capture.getNextLocation(TIMEOUT_MS);
1492                     assertThat(received).isEqualTo(loc1);
1493                     assertThat(received.isMock()).isTrue();
1494                     assertThat(mManager.getLastKnownLocation(provider)).isEqualTo(loc1);
1495 
1496                     mManager.setTestProviderEnabled(provider, false);
1497                     mManager.setTestProviderLocation(provider, loc2);
1498                     assertThat(mManager.getLastKnownLocation(provider)).isNull();
1499                     assertThat(capture.getNextLocation(FAILURE_TIMEOUT_MS)).isNull();
1500                 }
1501             } else {
1502                 try {
1503                     mManager.setTestProviderLocation(provider, loc1);
1504                     fail("Should throw IllegalArgumentException since " + provider
1505                             + " is not a test provider!");
1506                 } catch (IllegalArgumentException e) {
1507                     // expected
1508                 }
1509             }
1510         }
1511 
1512         try {
1513             mManager.setTestProviderLocation(TEST_PROVIDER, null);
1514             fail("Should throw IllegalArgumentException since location is null!");
1515         } catch (IllegalArgumentException e) {
1516             // expected
1517         }
1518 
1519         mManager.removeTestProvider(TEST_PROVIDER);
1520         try {
1521             mManager.setTestProviderLocation(TEST_PROVIDER, loc1);
1522             fail("Should throw IllegalArgumentException since " + TEST_PROVIDER
1523                     + " is not a test provider!");
1524         } catch (IllegalArgumentException e) {
1525             // expected
1526         }
1527 
1528         try {
1529             mManager.setTestProviderLocation(null, loc1);
1530             fail("Should throw IllegalArgumentException since provider is null!");
1531         } catch (IllegalArgumentException e) {
1532             // expected
1533         }
1534     }
1535 
1536     @Test
1537     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
1538     @SuppressWarnings("TryFailThrowable")
testSetTestProviderLocation_B33091107()1539     public void testSetTestProviderLocation_B33091107() throws Exception {
1540         // test for b/33091107, where a malicious app could fool a real provider into providing a
1541         // mock location that isn't marked as being mock
1542 
1543         List<String> providers = mManager.getAllProviders();
1544         if (providers.size() <= 2) {
1545             // can't perform the test without any real providers, and no need to do so since there
1546             // are no providers a malicious app could fool
1547             assertThat(providers.contains(TEST_PROVIDER)).isTrue();
1548             assertThat(providers.contains(PASSIVE_PROVIDER)).isTrue();
1549             return;
1550         }
1551 
1552         providers.remove(TEST_PROVIDER);
1553         providers.remove(PASSIVE_PROVIDER);
1554 
1555         String realProvider = providers.get(0);
1556         Location loc = createLocation(realProvider, mRandom);
1557 
1558         try (GetCurrentLocationCapture capture = new GetCurrentLocationCapture()) {
1559             mManager.getCurrentLocation(TEST_PROVIDER, capture.getCancellationSignal(),
1560                     Executors.newSingleThreadExecutor(), capture);
1561             mManager.setTestProviderLocation(TEST_PROVIDER, loc);
1562 
1563             Location received = capture.getLocation(TIMEOUT_MS);
1564             assertThat(received).isEqualTo(loc);
1565             assertThat(received.isMock()).isTrue();
1566 
1567             Location realProvideLocation = mManager.getLastKnownLocation(realProvider);
1568             if (realProvideLocation != null) {
1569                 boolean passed = false;
1570                 try {
1571                     assertThat(realProvideLocation).isEqualTo(loc);
1572                 } catch (AssertionError e) {
1573                     passed = true;
1574                 }
1575                 if (!passed) {
1576                     fail("real provider saw " + TEST_PROVIDER + " location!");
1577                 }
1578             }
1579         }
1580     }
1581 
1582     @Test
testRemoveTestProvider()1583     public void testRemoveTestProvider() {
1584         // removing providers should not crash
1585         for (String provider : mManager.getAllProviders()) {
1586             mManager.removeTestProvider(provider);
1587         }
1588     }
1589 
1590     @Test
testGetGnssCapabilities()1591     public void testGetGnssCapabilities() {
1592         assumeTrue(mManager.hasProvider(GPS_PROVIDER));
1593         assertThat(mManager.getGnssCapabilities()).isNotNull();
1594     }
1595 
1596     @Test
testGetGnssYearOfHardware()1597     public void testGetGnssYearOfHardware() {
1598         assumeTrue(mManager.hasProvider(GPS_PROVIDER));
1599         mManager.getGnssYearOfHardware();
1600     }
1601 
1602     @Test
testGetGnssHardwareModelName()1603     public void testGetGnssHardwareModelName() {
1604         assumeTrue(mManager.hasProvider(GPS_PROVIDER));
1605 
1606         // model name should be longer than 4 characters
1607         String gnssHardwareModelName = mManager.getGnssHardwareModelName();
1608 
1609         // Hardware model name was added in HAL 1.1. HAL 1.0 and earlier do not have this set.
1610         if (gnssHardwareModelName == null) {
1611             Log.w(TAG, "gnssHardwareModelName is null. Skipping test.");
1612             return;
1613         }
1614         assertThat(gnssHardwareModelName.length()).isGreaterThan(3);
1615     }
1616 
1617     @Test
testGetGnssAntennaInfos()1618     public void testGetGnssAntennaInfos() {
1619         assumeTrue(mManager.hasProvider(GPS_PROVIDER));
1620         if (mManager.getGnssCapabilities().hasAntennaInfo()) {
1621             assertThat(mManager.getGnssAntennaInfos()).isNotNull();
1622         } else {
1623             assertThat(mManager.getGnssAntennaInfos()).isNull();
1624         }
1625     }
1626 
1627     @Test
1628     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRegisterGnssStatusCallback()1629     public void testRegisterGnssStatusCallback() {
1630         GnssStatus.Callback callback = new GnssStatus.Callback() {
1631         };
1632 
1633         mManager.registerGnssStatusCallback(Executors.newSingleThreadExecutor(), callback);
1634         mManager.unregisterGnssStatusCallback(callback);
1635     }
1636 
1637     @Test
1638     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testAddNmeaListener()1639     public void testAddNmeaListener() {
1640         OnNmeaMessageListener listener = (message, timestamp) -> {
1641         };
1642 
1643         mManager.addNmeaListener(Executors.newSingleThreadExecutor(), listener);
1644         mManager.removeNmeaListener(listener);
1645     }
1646 
1647     @Test
1648     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRegisterGnssMeasurementsCallback()1649     public void testRegisterGnssMeasurementsCallback() throws Exception {
1650         try (GnssMeasurementsCapture capture = new GnssMeasurementsCapture(mContext)) {
1651             mManager.registerGnssMeasurementsCallback(Runnable::run, capture);
1652 
1653             // test deprecated status messages
1654             if (mManager.hasProvider(GPS_PROVIDER)) {
1655                 Integer status = capture.getNextStatus(TIMEOUT_MS);
1656                 assertThat(status).isNotNull();
1657                 assertThat(status).isEqualTo(GnssMeasurementsEvent.Callback.STATUS_READY);
1658             }
1659         }
1660     }
1661 
1662     @Test
testRegisterGnssAntennaInfoCallback()1663     public void testRegisterGnssAntennaInfoCallback() {
1664         try (GnssAntennaInfoCapture capture = new GnssAntennaInfoCapture(mContext)) {
1665             mManager.registerAntennaInfoListener(Runnable::run, capture);
1666         }
1667     }
1668 
1669     @Test
1670     @AppModeNonSdkSandbox(reason = "SDK sandboxes do not have ACCESS_FINE_LOCATION permission")
testRegisterGnssNavigationMessageCallback()1671     public void testRegisterGnssNavigationMessageCallback() throws Exception {
1672         try (GnssNavigationMessageCapture capture = new GnssNavigationMessageCapture(mContext)) {
1673             mManager.registerGnssNavigationMessageCallback(Runnable::run, capture);
1674 
1675             // test deprecated status messages
1676             if (mManager.hasProvider(GPS_PROVIDER)) {
1677                 Integer status = capture.getNextStatus(TIMEOUT_MS);
1678                 assertThat(status).isNotNull();
1679                 assertThat(status).isEqualTo(GnssNavigationMessage.Callback.STATUS_READY);
1680             }
1681         }
1682     }
1683 
assertFineOpNoted( long timeBeforeLocationAccess, String attributionTag)1684     private void assertFineOpNoted(
1685             long timeBeforeLocationAccess,
1686             String attributionTag) {
1687         final UiAutomation automation =
1688                 InstrumentationRegistry.getInstrumentation().getUiAutomation();
1689         automation.adoptShellPermissionIdentity(android.Manifest.permission.GET_APP_OPS_STATS);
1690 
1691         try {
1692             final AppOpsManager appOpsManager = Objects.requireNonNull(
1693                     mContext.getSystemService(AppOpsManager.class));
1694             final List<AppOpsManager.PackageOps> affectedPackageOps =
1695                     appOpsManager.getPackagesForOps(new String[]{OPSTR_FINE_LOCATION,
1696                             OPSTR_FINE_LOCATION_SOURCE});
1697             for (AppOpsManager.PackageOps packageOps : affectedPackageOps) {
1698                 if (mContext.getPackageName().equals(packageOps.getPackageName())) {
1699                     // We are pulling stats only for one app op.
1700                     for (AppOpsManager.OpEntry opEntry : packageOps.getOps()) {
1701                         if (OPSTR_FINE_LOCATION_SOURCE.equals(opEntry.getOpStr())) {
1702                             fail("Unexpected access to " + OPSTR_FINE_LOCATION_SOURCE);
1703                         } else if (OPSTR_FINE_LOCATION.equals(opEntry.getOpStr())
1704                                 && opEntry.getAttributedOpEntries().containsKey(attributionTag)
1705                                 && opEntry
1706                                 .getAttributedOpEntries()
1707                                 .get(attributionTag)
1708                                 .getLastAccessTime(AppOpsManager.OP_FLAGS_ALL_TRUSTED)
1709                                 >= timeBeforeLocationAccess) {
1710                             return;
1711                         }
1712                     }
1713                 }
1714             }
1715             fail("No expected access to " + OPSTR_FINE_LOCATION);
1716         } finally {
1717             automation.dropShellPermissionIdentity();
1718         }
1719     }
1720 
assertFineOpNotNoted( long timeBeforeLocationAccess, String attributionTag)1721     private void assertFineOpNotNoted(
1722             long timeBeforeLocationAccess, String attributionTag) {
1723         final UiAutomation automation =
1724                 InstrumentationRegistry.getInstrumentation().getUiAutomation();
1725         automation.adoptShellPermissionIdentity(android.Manifest.permission.GET_APP_OPS_STATS);
1726         try {
1727             final AppOpsManager appOpsManager = Objects.requireNonNull(
1728                     mContext.getSystemService(AppOpsManager.class));
1729             final List<AppOpsManager.PackageOps> affectedPackageOps =
1730                     appOpsManager.getPackagesForOps(new String[]{OPSTR_FINE_LOCATION});
1731             for (AppOpsManager.PackageOps packageOps : affectedPackageOps) {
1732                 if (mContext.getPackageName().equals(packageOps.getPackageName())) {
1733                     // We are pulling stats only for one app op.
1734                     for (AppOpsManager.OpEntry opEntry : packageOps.getOps()) {
1735                         if (OPSTR_FINE_LOCATION.equals(opEntry.getOpStr())
1736                                 && opEntry.getAttributedOpEntries().containsKey(attributionTag)
1737                                 && opEntry
1738                                 .getAttributedOpEntries()
1739                                 .get(attributionTag)
1740                                 .getLastAccessTime(AppOpsManager.OP_FLAGS_ALL_TRUSTED)
1741                                 >= timeBeforeLocationAccess) {
1742                             fail("Unexpected access to " + OPSTR_FINE_LOCATION);
1743                         }
1744                     }
1745                 }
1746             }
1747         } finally {
1748             automation.dropShellPermissionIdentity();
1749         }
1750     }
1751 }
1752