1 /*
2  * Copyright (C) 2020 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.provider;
18 
19 import static android.app.AppOpsManager.OP_FINE_LOCATION;
20 import static android.app.AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION;
21 import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
22 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
23 import static android.location.LocationManager.GPS_PROVIDER;
24 import static android.location.LocationRequest.PASSIVE_INTERVAL;
25 import static android.location.provider.ProviderProperties.POWER_USAGE_HIGH;
26 import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
27 
28 import static androidx.test.ext.truth.location.LocationSubject.assertThat;
29 
30 import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
31 import static com.android.server.location.LocationPermissions.PERMISSION_COARSE;
32 import static com.android.server.location.LocationPermissions.PERMISSION_FINE;
33 import static com.android.server.location.LocationUtils.createLocation;
34 import static com.android.server.location.LocationUtils.createLocationResult;
35 import static com.android.server.location.listeners.RemoteListenerRegistration.IN_PROCESS_EXECUTOR;
36 
37 import static com.google.common.truth.Truth.assertThat;
38 
39 import static org.mockito.ArgumentMatchers.any;
40 import static org.mockito.ArgumentMatchers.anyBoolean;
41 import static org.mockito.ArgumentMatchers.anyInt;
42 import static org.mockito.ArgumentMatchers.anyLong;
43 import static org.mockito.ArgumentMatchers.anyString;
44 import static org.mockito.ArgumentMatchers.eq;
45 import static org.mockito.ArgumentMatchers.isNull;
46 import static org.mockito.ArgumentMatchers.nullable;
47 import static org.mockito.Mockito.after;
48 import static org.mockito.Mockito.doReturn;
49 import static org.mockito.Mockito.inOrder;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.never;
52 import static org.mockito.Mockito.spy;
53 import static org.mockito.Mockito.timeout;
54 import static org.mockito.Mockito.times;
55 import static org.mockito.Mockito.verify;
56 import static org.mockito.Mockito.verifyNoMoreInteractions;
57 import static org.mockito.MockitoAnnotations.initMocks;
58 import static org.testng.Assert.assertThrows;
59 
60 import android.content.Context;
61 import android.content.pm.PackageManager;
62 import android.content.res.Resources;
63 import android.location.ILocationCallback;
64 import android.location.ILocationListener;
65 import android.location.LastLocationRequest;
66 import android.location.Location;
67 import android.location.LocationManagerInternal;
68 import android.location.LocationManagerInternal.ProviderEnabledListener;
69 import android.location.LocationRequest;
70 import android.location.LocationResult;
71 import android.location.provider.IProviderRequestListener;
72 import android.location.provider.ProviderProperties;
73 import android.location.provider.ProviderRequest;
74 import android.location.util.identity.CallerIdentity;
75 import android.os.Bundle;
76 import android.os.ICancellationSignal;
77 import android.os.IRemoteCallback;
78 import android.os.PackageTagsList;
79 import android.os.PowerManager;
80 import android.os.Process;
81 import android.os.RemoteException;
82 import android.os.WorkSource;
83 import android.platform.test.annotations.Presubmit;
84 import android.util.Log;
85 
86 import androidx.test.filters.SmallTest;
87 import androidx.test.runner.AndroidJUnit4;
88 
89 import com.android.internal.R;
90 import com.android.server.FgThread;
91 import com.android.server.LocalServices;
92 import com.android.server.location.injector.FakeUserInfoHelper;
93 import com.android.server.location.injector.TestInjector;
94 
95 import org.junit.After;
96 import org.junit.Before;
97 import org.junit.Test;
98 import org.junit.runner.RunWith;
99 import org.mockito.ArgumentCaptor;
100 import org.mockito.InOrder;
101 import org.mockito.Mock;
102 
103 import java.io.FileDescriptor;
104 import java.io.PrintWriter;
105 import java.util.ArrayList;
106 import java.util.Collections;
107 import java.util.List;
108 import java.util.Random;
109 import java.util.concurrent.CountDownLatch;
110 import java.util.concurrent.TimeUnit;
111 
112 @Presubmit
113 @SmallTest
114 @RunWith(AndroidJUnit4.class)
115 public class LocationProviderManagerTest {
116 
117     private static final String TAG = "LocationProviderManagerTest";
118 
119     private static final long TIMEOUT_MS = 1000;
120 
121     private static final int CURRENT_USER = FakeUserInfoHelper.DEFAULT_USERID;
122     private static final int OTHER_USER = CURRENT_USER + 10;
123 
124     private static final String NAME = "test";
125     private static final ProviderProperties PROPERTIES = new ProviderProperties.Builder()
126             .setHasAltitudeSupport(true)
127             .setHasSpeedSupport(true)
128             .setHasBearingSupport(true)
129             .setPowerUsage(POWER_USAGE_HIGH)
130             .setAccuracy(ProviderProperties.ACCURACY_FINE)
131             .build();
132     private static final CallerIdentity PROVIDER_IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
133             "mypackage", "attribution");
134     private static final CallerIdentity IDENTITY = CallerIdentity.forTest(CURRENT_USER, 1,
135             "mypackage", "attribution", "listener");
136     private static final WorkSource WORK_SOURCE = new WorkSource(IDENTITY.getUid());
137 
138     private Random mRandom;
139 
140     @Mock
141     private LocationProviderManager.StateChangedListener mStateChangedListener;
142     @Mock
143     private LocationManagerInternal mInternal;
144     @Mock
145     private Context mContext;
146     @Mock
147     private Resources mResources;
148     @Mock
149     private PackageManager mPackageManager;
150     @Mock
151     private PowerManager mPowerManager;
152     @Mock
153     private PowerManager.WakeLock mWakeLock;
154 
155     private TestInjector mInjector;
156     private PassiveLocationProviderManager mPassive;
157     private TestProvider mProvider;
158 
159     private LocationProviderManager mManager;
160 
161     @Before
setUp()162     public void setUp() {
163         initMocks(this);
164 
165         long seed = System.currentTimeMillis();
166         Log.i(TAG, "location random seed: " + seed);
167 
168         mRandom = new Random(seed);
169 
170         LocalServices.addService(LocationManagerInternal.class, mInternal);
171 
172         doReturn("android").when(mContext).getPackageName();
173         doReturn(mResources).when(mContext).getResources();
174         doReturn(mPackageManager).when(mContext).getPackageManager();
175         doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
176         doReturn(mWakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
177 
178         mInjector = new TestInjector(mContext);
179         mInjector.getUserInfoHelper().startUser(OTHER_USER);
180 
181         mPassive = new PassiveLocationProviderManager(mContext, mInjector);
182         mPassive.startManager(null);
183         mPassive.setRealProvider(new PassiveLocationProvider(mContext));
184 
185         createManager(NAME);
186     }
187 
createManager(String name)188     private void createManager(String name) {
189         mStateChangedListener = mock(LocationProviderManager.StateChangedListener.class);
190 
191         mProvider = new TestProvider(PROPERTIES, PROVIDER_IDENTITY);
192         mProvider.setProviderAllowed(true);
193 
194         mManager = new LocationProviderManager(mContext, mInjector, name, mPassive);
195         mManager.startManager(mStateChangedListener);
196         mManager.setRealProvider(mProvider);
197     }
198 
199     @After
tearDown()200     public void tearDown() throws Exception {
201         LocalServices.removeServiceForTest(LocationManagerInternal.class);
202 
203         // some test failures may leave the fg thread stuck, interrupt until we get out of it
204         CountDownLatch latch = new CountDownLatch(1);
205         FgThread.getExecutor().execute(latch::countDown);
206         int count = 0;
207         while (++count < 10 && !latch.await(10, TimeUnit.MILLISECONDS)) {
208             FgThread.get().getLooper().getThread().interrupt();
209         }
210     }
211 
212     @Test
testProperties()213     public void testProperties() {
214         assertThat(mManager.getName()).isEqualTo(NAME);
215         assertThat(mManager.getProperties()).isEqualTo(PROPERTIES);
216         assertThat(mManager.getIdentity()).isEqualTo(IDENTITY);
217         assertThat(mManager.hasProvider()).isTrue();
218 
219         ProviderProperties newProperties = new ProviderProperties.Builder()
220                 .setHasNetworkRequirement(true)
221                 .setHasSatelliteRequirement(true)
222                 .setHasCellRequirement(true)
223                 .setHasMonetaryCost(true)
224                 .setPowerUsage(POWER_USAGE_HIGH)
225                 .setAccuracy(ProviderProperties.ACCURACY_COARSE)
226                 .build();
227         mProvider.setProperties(newProperties);
228         assertThat(mManager.getProperties()).isEqualTo(newProperties);
229 
230         CallerIdentity newIdentity = CallerIdentity.forTest(OTHER_USER, 1, "otherpackage",
231                 "otherattribution");
232         mProvider.setIdentity(newIdentity);
233         assertThat(mManager.getIdentity()).isEqualTo(newIdentity);
234 
235         mManager.setRealProvider(null);
236         assertThat(mManager.hasProvider()).isFalse();
237     }
238 
239     @Test
testStateChangedListener()240     public void testStateChangedListener() {
241         mProvider.setExtraAttributionTags(Collections.singleton("extra"));
242 
243         ArgumentCaptor<AbstractLocationProvider.State> captorOld = ArgumentCaptor.forClass(
244                 AbstractLocationProvider.State.class);
245         ArgumentCaptor<AbstractLocationProvider.State> captorNew = ArgumentCaptor.forClass(
246                 AbstractLocationProvider.State.class);
247         verify(mStateChangedListener, timeout(TIMEOUT_MS).times(2)).onStateChanged(eq(NAME),
248                 captorOld.capture(), captorNew.capture());
249 
250         assertThat(captorOld.getAllValues().get(1).extraAttributionTags).isEmpty();
251         assertThat(captorNew.getAllValues().get(1).extraAttributionTags).containsExactly("extra");
252     }
253 
254     @Test
testRemoveProvider()255     public void testRemoveProvider() {
256         mManager.setRealProvider(null);
257         assertThat(mManager.hasProvider()).isFalse();
258     }
259 
260     @Test
testIsEnabled()261     public void testIsEnabled() {
262         assertThat(mManager.isEnabled(CURRENT_USER)).isTrue();
263         assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
264 
265         mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
266         assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
267         assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
268 
269         mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
270         mProvider.setAllowed(false);
271         assertThat(mManager.isEnabled(CURRENT_USER)).isFalse();
272         assertThat(mManager.isEnabled(OTHER_USER)).isFalse();
273 
274         mProvider.setAllowed(true);
275         assertThat(mManager.isEnabled(CURRENT_USER)).isTrue();
276         assertThat(mManager.isEnabled(OTHER_USER)).isTrue();
277     }
278 
279     @Test
testIsEnabledListener()280     public void testIsEnabledListener() {
281         ProviderEnabledListener listener = mock(ProviderEnabledListener.class);
282         mManager.addEnabledListener(listener);
283         verify(listener, never()).onProviderEnabledChanged(anyString(), anyInt(), anyBoolean());
284 
285         mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
286         verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, CURRENT_USER,
287                 false);
288 
289         mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
290         verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, CURRENT_USER,
291                 true);
292 
293         mProvider.setAllowed(false);
294         verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, CURRENT_USER,
295                 false);
296         verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, OTHER_USER,
297                 false);
298 
299         mProvider.setAllowed(true);
300         verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, CURRENT_USER,
301                 true);
302         verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, OTHER_USER,
303                 true);
304 
305         mManager.removeEnabledListener(listener);
306         mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
307         verifyNoMoreInteractions(listener);
308     }
309 
310     @Test
testGetLastLocation_Fine()311     public void testGetLastLocation_Fine() {
312         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
313                 PERMISSION_FINE)).isNull();
314 
315         Location loc = createLocation(NAME, mRandom);
316         mProvider.setProviderLocation(loc);
317         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
318                 PERMISSION_FINE)).isEqualTo(loc);
319     }
320 
321     @Test
testGetLastLocation_Coarse()322     public void testGetLastLocation_Coarse() {
323         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
324                 PERMISSION_FINE)).isNull();
325 
326         Location loc = createLocation(NAME, mRandom);
327         mProvider.setProviderLocation(loc);
328         Location coarse = mManager.getLastLocation(new LastLocationRequest.Builder().build(),
329                 IDENTITY, PERMISSION_COARSE);
330         assertThat(coarse).isNotEqualTo(loc);
331         assertThat(coarse).isNearby(loc, 5000);
332     }
333 
334     @Test
testGetLastLocation_Bypass()335     public void testGetLastLocation_Bypass() {
336         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
337                 PERMISSION_FINE)).isNull();
338         assertThat(mManager.getLastLocation(
339                 new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
340                 IDENTITY, PERMISSION_FINE)).isNull();
341 
342         Location loc = createLocation(NAME, mRandom);
343         mProvider.setProviderLocation(loc);
344         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
345                 PERMISSION_FINE)).isEqualTo(loc);
346         assertThat(mManager.getLastLocation(
347                 new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
348                 IDENTITY, PERMISSION_FINE)).isEqualTo(
349                 loc);
350 
351         mProvider.setProviderAllowed(false);
352         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
353                 PERMISSION_FINE)).isNull();
354         assertThat(mManager.getLastLocation(
355                 new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
356                 IDENTITY, PERMISSION_FINE)).isEqualTo(
357                 loc);
358 
359         loc = createLocation(NAME, mRandom);
360         mProvider.setProviderLocation(loc);
361         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
362                 PERMISSION_FINE)).isNull();
363         assertThat(mManager.getLastLocation(
364                 new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
365                 IDENTITY, PERMISSION_FINE)).isEqualTo(
366                 loc);
367 
368         mProvider.setProviderAllowed(true);
369         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
370                 PERMISSION_FINE)).isNull();
371         assertThat(mManager.getLastLocation(
372                 new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
373                 IDENTITY, PERMISSION_FINE)).isEqualTo(
374                 loc);
375 
376         loc = createLocation(NAME, mRandom);
377         mProvider.setProviderLocation(loc);
378         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
379                 PERMISSION_FINE)).isEqualTo(loc);
380         assertThat(mManager.getLastLocation(
381                 new LastLocationRequest.Builder().setLocationSettingsIgnored(true).build(),
382                 IDENTITY, PERMISSION_FINE)).isEqualTo(
383                 loc);
384     }
385 
386     @Test
testGetLastLocation_ClearOnMockRemoval()387     public void testGetLastLocation_ClearOnMockRemoval() {
388         MockLocationProvider mockProvider = new MockLocationProvider(PROPERTIES, PROVIDER_IDENTITY,
389                 Collections.emptySet());
390         mockProvider.setAllowed(true);
391         mManager.setMockProvider(mockProvider);
392 
393         Location loc = createLocation(NAME, mRandom);
394         mockProvider.setProviderLocation(loc);
395         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
396                 PERMISSION_FINE)).isEqualTo(loc);
397 
398         mManager.setMockProvider(null);
399         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
400                 PERMISSION_FINE)).isNull();
401     }
402 
403     @Test
testInjectLastLocation()404     public void testInjectLastLocation() {
405         Location loc1 = createLocation(NAME, mRandom);
406         mManager.injectLastLocation(loc1, CURRENT_USER);
407 
408         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
409                 PERMISSION_FINE)).isEqualTo(loc1);
410 
411         Location loc2 = createLocation(NAME, mRandom);
412         mManager.injectLastLocation(loc2, CURRENT_USER);
413 
414         assertThat(mManager.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
415                 PERMISSION_FINE)).isEqualTo(loc1);
416     }
417 
418     @Test
testPassive_Listener()419     public void testPassive_Listener() throws Exception {
420         ILocationListener listener = createMockLocationListener();
421         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
422         mPassive.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
423 
424         LocationResult loc = createLocationResult(NAME, mRandom);
425         mProvider.setProviderLocation(loc);
426         verify(listener).onLocationChanged(eq(loc.asList()), nullable(IRemoteCallback.class));
427     }
428 
429     @Test
testPassive_LastLocation()430     public void testPassive_LastLocation() {
431         Location loc = createLocation(NAME, mRandom);
432         mProvider.setProviderLocation(loc);
433 
434         assertThat(mPassive.getLastLocation(new LastLocationRequest.Builder().build(), IDENTITY,
435                 PERMISSION_FINE)).isEqualTo(loc);
436     }
437 
438     @Test
testRegisterListener()439     public void testRegisterListener() throws Exception {
440         ILocationListener listener = createMockLocationListener();
441         mManager.registerLocationRequest(
442                 new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
443                 IDENTITY,
444                 PERMISSION_FINE,
445                 listener);
446 
447         LocationResult loc = createLocationResult(NAME, mRandom);
448         mProvider.setProviderLocation(loc);
449         verify(listener).onLocationChanged(eq(loc.asList()), nullable(IRemoteCallback.class));
450 
451         mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
452         verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, false);
453         loc = createLocationResult(NAME, mRandom);
454         mProvider.setProviderLocation(loc);
455         verify(listener, times(1)).onLocationChanged(any(List.class),
456                 nullable(IRemoteCallback.class));
457 
458         mInjector.getSettingsHelper().setLocationEnabled(true, CURRENT_USER);
459         verify(listener, timeout(TIMEOUT_MS).times(1)).onProviderEnabledChanged(NAME, true);
460 
461         mProvider.setAllowed(false);
462         verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, false);
463         loc = createLocationResult(NAME, mRandom);
464         mProvider.setProviderLocation(loc);
465         verify(listener, times(1)).onLocationChanged(any(List.class),
466                 nullable(IRemoteCallback.class));
467 
468         mProvider.setAllowed(true);
469         verify(listener, timeout(TIMEOUT_MS).times(2)).onProviderEnabledChanged(NAME, true);
470 
471         loc = createLocationResult(NAME, mRandom);
472         mProvider.setProviderLocation(loc);
473         verify(listener).onLocationChanged(eq(loc.asList()), nullable(IRemoteCallback.class));
474     }
475 
476     @Test
testRegisterListener_SameProcess()477     public void testRegisterListener_SameProcess() throws Exception {
478         CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
479                 "attribution", "listener");
480 
481         ILocationListener listener = createMockLocationListener();
482         mManager.registerLocationRequest(
483                 new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
484                 identity,
485                 PERMISSION_FINE,
486                 listener);
487 
488         LocationResult loc = createLocationResult(NAME, mRandom);
489         mProvider.setProviderLocation(loc);
490         verify(listener, timeout(TIMEOUT_MS).times(1)).onLocationChanged(eq(loc.asList()),
491                 nullable(IRemoteCallback.class));
492     }
493 
494     @Test
testRegisterListener_Unregister()495     public void testRegisterListener_Unregister() throws Exception {
496         ILocationListener listener = createMockLocationListener();
497         mManager.registerLocationRequest(
498                 new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
499                 IDENTITY,
500                 PERMISSION_FINE,
501                 listener);
502         mManager.unregisterLocationRequest(listener);
503 
504         mProvider.setProviderLocation(createLocation(NAME, mRandom));
505         verify(listener, never()).onLocationChanged(any(List.class),
506                 nullable(IRemoteCallback.class));
507 
508         mInjector.getSettingsHelper().setLocationEnabled(false, CURRENT_USER);
509         verify(listener, after(TIMEOUT_MS).never()).onProviderEnabledChanged(NAME, false);
510     }
511 
512     @Test
testRegisterListener_Unregister_SameProcess()513     public void testRegisterListener_Unregister_SameProcess() throws Exception {
514         CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
515                 "attribution", "listener");
516 
517         ILocationListener listener = createMockLocationListener();
518         mManager.registerLocationRequest(
519                 new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
520                 identity,
521                 PERMISSION_FINE,
522                 listener);
523 
524         CountDownLatch blocker = new CountDownLatch(1);
525         IN_PROCESS_EXECUTOR.execute(() -> {
526             try {
527                 blocker.await();
528             } catch (InterruptedException e) {
529                 // do nothing
530             }
531         });
532 
533         mProvider.setProviderLocation(createLocation(NAME, mRandom));
534         mManager.unregisterLocationRequest(listener);
535         blocker.countDown();
536         verify(listener, after(TIMEOUT_MS).never()).onLocationChanged(any(List.class),
537                 nullable(IRemoteCallback.class));
538     }
539 
540     @Test
testRegisterListener_NumUpdates()541     public void testRegisterListener_NumUpdates() throws Exception {
542         ILocationListener listener = createMockLocationListener();
543         LocationRequest request = new LocationRequest.Builder(0)
544                 .setMaxUpdates(5)
545                 .setWorkSource(WORK_SOURCE)
546                 .build();
547         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
548 
549         mProvider.setProviderLocation(createLocation(NAME, mRandom));
550         mProvider.setProviderLocation(createLocation(NAME, mRandom));
551         mProvider.setProviderLocation(createLocation(NAME, mRandom));
552         mProvider.setProviderLocation(createLocation(NAME, mRandom));
553         mProvider.setProviderLocation(createLocation(NAME, mRandom));
554         mProvider.setProviderLocation(createLocation(NAME, mRandom));
555 
556         verify(listener, times(5)).onLocationChanged(any(List.class),
557                 nullable(IRemoteCallback.class));
558     }
559 
560     @Test
testRegisterListener_ExpiringAlarm()561     public void testRegisterListener_ExpiringAlarm() throws Exception {
562         ILocationListener listener = createMockLocationListener();
563         LocationRequest request = new LocationRequest.Builder(0)
564                 .setDurationMillis(5000)
565                 .setWorkSource(WORK_SOURCE)
566                 .build();
567         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
568 
569         mInjector.getAlarmHelper().incrementAlarmTime(5000);
570         mProvider.setProviderLocation(createLocation(NAME, mRandom));
571         verify(listener, never()).onLocationChanged(any(List.class),
572                 nullable(IRemoteCallback.class));
573     }
574 
575     @Test
testRegisterListener_ExpiringNoAlarm()576     public void testRegisterListener_ExpiringNoAlarm() throws Exception {
577         ILocationListener listener = createMockLocationListener();
578         LocationRequest request = new LocationRequest.Builder(0)
579                 .setDurationMillis(25)
580                 .setWorkSource(WORK_SOURCE)
581                 .build();
582         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
583 
584         Thread.sleep(25);
585 
586         mProvider.setProviderLocation(createLocation(NAME, mRandom));
587         verify(listener, never()).onLocationChanged(any(List.class),
588                 nullable(IRemoteCallback.class));
589     }
590 
591     @Test
testRegisterListener_FastestInterval()592     public void testRegisterListener_FastestInterval() throws Exception {
593         ILocationListener listener = createMockLocationListener();
594         LocationRequest request = new LocationRequest.Builder(5000)
595                 .setMinUpdateIntervalMillis(5000)
596                 .setWorkSource(WORK_SOURCE)
597                 .build();
598         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
599 
600         mProvider.setProviderLocation(createLocation(NAME, mRandom));
601         mProvider.setProviderLocation(createLocation(NAME, mRandom));
602 
603         verify(listener, times(1)).onLocationChanged(
604                 any(List.class), nullable(IRemoteCallback.class));
605     }
606 
607     @Test
testRegisterListener_SmallestDisplacement()608     public void testRegisterListener_SmallestDisplacement() throws Exception {
609         ILocationListener listener = createMockLocationListener();
610         LocationRequest request = new LocationRequest.Builder(5000)
611                 .setMinUpdateDistanceMeters(1f)
612                 .setWorkSource(WORK_SOURCE)
613                 .build();
614         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
615 
616         Location loc = createLocation(NAME, mRandom);
617         mProvider.setProviderLocation(loc);
618         mProvider.setProviderLocation(loc);
619 
620         verify(listener, times(1)).onLocationChanged(
621                 any(List.class), nullable(IRemoteCallback.class));
622     }
623 
624     @Test
testRegisterListener_NoteOpFailure()625     public void testRegisterListener_NoteOpFailure() throws Exception {
626         ILocationListener listener = createMockLocationListener();
627         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
628         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
629 
630         mInjector.getAppOpsHelper().setAppOpAllowed(OP_FINE_LOCATION, IDENTITY.getPackageName(),
631                 false);
632 
633         mProvider.setProviderLocation(createLocation(NAME, mRandom));
634 
635         verify(listener, never()).onLocationChanged(any(List.class),
636                 nullable(IRemoteCallback.class));
637     }
638 
639     @Test
testRegisterListener_Wakelock()640     public void testRegisterListener_Wakelock() throws Exception {
641         CallerIdentity identity = CallerIdentity.forTest(CURRENT_USER, Process.myPid(), "mypackage",
642                 "attribution", "listener");
643 
644         ILocationListener listener = createMockLocationListener();
645         mManager.registerLocationRequest(
646                 new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
647                 identity,
648                 PERMISSION_FINE,
649                 listener);
650 
651         CountDownLatch blocker = new CountDownLatch(1);
652         IN_PROCESS_EXECUTOR.execute(() -> {
653             try {
654                 blocker.await();
655             } catch (InterruptedException e) {
656                 // do nothing
657             }
658         });
659 
660         mProvider.setProviderLocation(createLocation(NAME, mRandom));
661         verify(mWakeLock).acquire(anyLong());
662         verify(mWakeLock, never()).release();
663 
664         blocker.countDown();
665         verify(listener, timeout(TIMEOUT_MS)).onLocationChanged(any(List.class),
666                 nullable(IRemoteCallback.class));
667         verify(mWakeLock).acquire(anyLong());
668         verify(mWakeLock, timeout(TIMEOUT_MS)).release();
669     }
670 
671     @Test
testRegisterListener_Coarse()672     public void testRegisterListener_Coarse() throws Exception {
673         ILocationListener listener = createMockLocationListener();
674         mManager.registerLocationRequest(
675                 new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
676                 IDENTITY,
677                 PERMISSION_COARSE,
678                 listener);
679 
680         mProvider.setProviderLocation(createLocation(NAME, mRandom));
681         mProvider.setProviderLocation(createLocation(NAME, mRandom));
682         verify(listener, times(1))
683                 .onLocationChanged(any(List.class), nullable(IRemoteCallback.class));
684     }
685 
686     @Test
testRegisterListener_Coarse_Passive()687     public void testRegisterListener_Coarse_Passive() throws Exception {
688         ILocationListener listener = createMockLocationListener();
689         mManager.registerLocationRequest(
690                 new LocationRequest.Builder(PASSIVE_INTERVAL)
691                         .setMinUpdateIntervalMillis(0)
692                         .setWorkSource(WORK_SOURCE).build(),
693                 IDENTITY,
694                 PERMISSION_COARSE,
695                 listener);
696 
697         mProvider.setProviderLocation(createLocation(NAME, mRandom));
698         mProvider.setProviderLocation(createLocation(NAME, mRandom));
699         verify(listener, times(1))
700                 .onLocationChanged(any(List.class), nullable(IRemoteCallback.class));
701     }
702 
703     @Test
testProviderRequestListener()704     public void testProviderRequestListener() throws Exception {
705         IProviderRequestListener requestListener = mock(IProviderRequestListener.class);
706         mManager.addProviderRequestListener(requestListener);
707 
708         ILocationListener locationListener = createMockLocationListener();
709         LocationRequest request = new LocationRequest.Builder(1).setWorkSource(
710                 WORK_SOURCE).build();
711         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, locationListener);
712 
713         verify(requestListener, timeout(TIMEOUT_MS).times(1)).onProviderRequestChanged(anyString(),
714                 any(ProviderRequest.class));
715 
716         mManager.unregisterLocationRequest(locationListener);
717         mManager.removeProviderRequestListener(requestListener);
718     }
719 
720     @Test
testGetCurrentLocation()721     public void testGetCurrentLocation() throws Exception {
722         ILocationCallback listener = createMockGetCurrentLocationListener();
723         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
724         mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
725 
726         Location loc = createLocation(NAME, mRandom);
727         mProvider.setProviderLocation(loc);
728         mProvider.setProviderLocation(createLocation(NAME, mRandom));
729         verify(listener, times(1)).onLocation(loc);
730     }
731 
732     @Test
testGetCurrentLocation_Cancel()733     public void testGetCurrentLocation_Cancel() throws Exception {
734         ILocationCallback listener = createMockGetCurrentLocationListener();
735         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
736         ICancellationSignal cancellationSignal = mManager.getCurrentLocation(request,
737                 IDENTITY, PERMISSION_FINE, listener);
738 
739         cancellationSignal.cancel();
740         mProvider.setProviderLocation(createLocation(NAME, mRandom));
741         verify(listener, never()).onLocation(nullable(Location.class));
742     }
743 
744     @Test
testGetCurrentLocation_ProviderDisabled()745     public void testGetCurrentLocation_ProviderDisabled() throws Exception {
746         ILocationCallback listener = createMockGetCurrentLocationListener();
747         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
748         mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
749 
750         mProvider.setProviderAllowed(false);
751         mProvider.setProviderAllowed(true);
752         mProvider.setProviderLocation(createLocation(NAME, mRandom));
753         verify(listener, times(1)).onLocation(isNull());
754     }
755 
756     @Test
testGetCurrentLocation_ProviderAlreadyDisabled()757     public void testGetCurrentLocation_ProviderAlreadyDisabled() throws Exception {
758         mProvider.setProviderAllowed(false);
759 
760         ILocationCallback listener = createMockGetCurrentLocationListener();
761         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
762         mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
763 
764         mProvider.setProviderAllowed(true);
765         mProvider.setProviderLocation(createLocation(NAME, mRandom));
766         verify(listener, times(1)).onLocation(isNull());
767     }
768 
769     @Test
testGetCurrentLocation_LastLocation()770     public void testGetCurrentLocation_LastLocation() throws Exception {
771         Location loc = createLocation(NAME, mRandom);
772         mProvider.setProviderLocation(loc);
773 
774         ILocationCallback listener = createMockGetCurrentLocationListener();
775         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
776         mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
777         verify(listener, times(1)).onLocation(eq(loc));
778     }
779 
780     @Test
testGetCurrentLocation_Timeout()781     public void testGetCurrentLocation_Timeout() throws Exception {
782         ILocationCallback listener = createMockGetCurrentLocationListener();
783         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
784         mManager.getCurrentLocation(request, IDENTITY, PERMISSION_FINE, listener);
785 
786         mInjector.getAlarmHelper().incrementAlarmTime(60000);
787         verify(listener, times(1)).onLocation(isNull());
788     }
789 
790     @Test
testFlush()791     public void testFlush() throws Exception {
792         ILocationListener listener = createMockLocationListener();
793         mManager.registerLocationRequest(
794                 new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
795                 IDENTITY,
796                 PERMISSION_FINE,
797                 listener);
798 
799         mManager.flush(listener, 99);
800 
801         LocationResult loc = createLocationResult(NAME, mRandom);
802         mProvider.setProviderLocation(loc);
803         mProvider.completeFlushes();
804 
805         InOrder inOrder = inOrder(listener);
806         inOrder.verify(listener).onLocationChanged(eq(loc.asList()), any(IRemoteCallback.class));
807         inOrder.verify(listener).onFlushComplete(99);
808     }
809 
810     @Test
testFlush_UnknownKey()811     public void testFlush_UnknownKey() {
812         assertThrows(IllegalArgumentException.class,
813                 () -> mManager.flush(createMockLocationListener(), 0));
814     }
815 
816     @Test
testLocationMonitoring()817     public void testLocationMonitoring() {
818         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
819                 IDENTITY.getPackageName())).isFalse();
820         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
821                 IDENTITY.getPackageName())).isFalse();
822 
823         ILocationListener listener = createMockLocationListener();
824         LocationRequest request = new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build();
825         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
826 
827         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
828                 IDENTITY.getPackageName())).isTrue();
829         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
830                 IDENTITY.getPackageName())).isTrue();
831 
832         mInjector.getAppForegroundHelper().setAppForeground(IDENTITY.getUid(), false);
833 
834         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
835                 IDENTITY.getPackageName())).isTrue();
836         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
837                 IDENTITY.getPackageName())).isFalse();
838 
839         mManager.unregisterLocationRequest(listener);
840 
841         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
842                 IDENTITY.getPackageName())).isFalse();
843         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
844                 IDENTITY.getPackageName())).isFalse();
845     }
846 
847     @Test
testLocationMonitoring_multipleIdentities()848     public void testLocationMonitoring_multipleIdentities() {
849         CallerIdentity identity1 = CallerIdentity.forTest(CURRENT_USER, 1,
850                 "mypackage", "attribution", "listener1");
851         CallerIdentity identity2 = CallerIdentity.forTest(CURRENT_USER, 1,
852                 "mypackage", "attribution", "listener2");
853 
854         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
855                 IDENTITY.getPackageName())).isFalse();
856         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
857                 IDENTITY.getPackageName())).isFalse();
858 
859         ILocationListener listener1 = createMockLocationListener();
860         LocationRequest request1 = new LocationRequest.Builder(0).setWorkSource(
861                 WORK_SOURCE).build();
862         mManager.registerLocationRequest(request1, identity1, PERMISSION_FINE, listener1);
863 
864         ILocationListener listener2 = createMockLocationListener();
865         LocationRequest request2 = new LocationRequest.Builder(0).setWorkSource(
866                 WORK_SOURCE).build();
867         mManager.registerLocationRequest(request2, identity2, PERMISSION_FINE, listener2);
868 
869         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
870                 "mypackage")).isTrue();
871         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
872                 "mypackage")).isTrue();
873 
874         mManager.unregisterLocationRequest(listener2);
875 
876         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
877                 "mypackage")).isTrue();
878         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
879                 "mypackage")).isTrue();
880 
881         mManager.unregisterLocationRequest(listener1);
882 
883         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
884                 "mypackage")).isFalse();
885         assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
886                 "mypackage")).isFalse();
887     }
888 
889     @Test
testProviderRequest()890     public void testProviderRequest() {
891         assertThat(mProvider.getRequest().isActive()).isFalse();
892 
893         ILocationListener listener1 = createMockLocationListener();
894         LocationRequest request1 = new LocationRequest.Builder(5).setWorkSource(
895                 WORK_SOURCE).build();
896         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
897 
898         assertThat(mProvider.getRequest().isActive()).isTrue();
899         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
900         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
901         assertThat(mProvider.getRequest().isLowPower()).isFalse();
902         assertThat(mProvider.getRequest().getWorkSource()).isNotNull();
903 
904         ILocationListener listener2 = createMockLocationListener();
905         LocationRequest request2 = new LocationRequest.Builder(1)
906                 .setLowPower(true)
907                 .setWorkSource(WORK_SOURCE)
908                 .build();
909         mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
910 
911         assertThat(mProvider.getRequest().isActive()).isTrue();
912         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
913         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
914         assertThat(mProvider.getRequest().isLowPower()).isFalse();
915         assertThat(mProvider.getRequest().getWorkSource()).isNotNull();
916 
917         mManager.unregisterLocationRequest(listener1);
918 
919         assertThat(mProvider.getRequest().isActive()).isTrue();
920         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
921         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
922         assertThat(mProvider.getRequest().isLowPower()).isTrue();
923         assertThat(mProvider.getRequest().getWorkSource()).isNotNull();
924 
925         mManager.unregisterLocationRequest(listener2);
926 
927         assertThat(mProvider.getRequest().isActive()).isFalse();
928     }
929 
930     @Test
testProviderRequest_DelayedRequest()931     public void testProviderRequest_DelayedRequest() throws Exception {
932         mProvider.setProviderLocation(createLocation(NAME, mRandom));
933 
934         ILocationListener listener1 = createMockLocationListener();
935         LocationRequest request1 = new LocationRequest.Builder(60000)
936                 .setWorkSource(WORK_SOURCE)
937                 .build();
938         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
939 
940         verify(listener1).onLocationChanged(any(List.class),
941                 nullable(IRemoteCallback.class));
942 
943         assertThat(mProvider.getRequest().isActive()).isFalse();
944 
945         mInjector.getAlarmHelper().incrementAlarmTime(60000);
946         assertThat(mProvider.getRequest().isActive()).isTrue();
947         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(60000);
948     }
949 
950     @Test
testProviderRequest_DelayedRequest_Remove()951     public void testProviderRequest_DelayedRequest_Remove() {
952         mProvider.setProviderLocation(createLocation(NAME, mRandom));
953 
954         ILocationListener listener1 = createMockLocationListener();
955         LocationRequest request1 = new LocationRequest.Builder(60000)
956                 .setWorkSource(WORK_SOURCE)
957                 .build();
958         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
959         mManager.unregisterLocationRequest(listener1);
960 
961         mInjector.getAlarmHelper().incrementAlarmTime(60000);
962         assertThat(mProvider.getRequest().isActive()).isFalse();
963     }
964 
965     @Test
testProviderRequest_SpamRequesting()966     public void testProviderRequest_SpamRequesting() {
967         mProvider.setProviderLocation(createLocation(NAME, mRandom));
968 
969         ILocationListener listener1 = createMockLocationListener();
970         LocationRequest request1 = new LocationRequest.Builder(60000)
971                 .setWorkSource(WORK_SOURCE)
972                 .build();
973 
974         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
975         assertThat(mProvider.getRequest().isActive()).isFalse();
976         mManager.unregisterLocationRequest(listener1);
977         assertThat(mProvider.getRequest().isActive()).isFalse();
978         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
979         assertThat(mProvider.getRequest().isActive()).isFalse();
980         mManager.unregisterLocationRequest(listener1);
981         assertThat(mProvider.getRequest().isActive()).isFalse();
982     }
983 
984     @Test
testProviderRequest_BackgroundThrottle()985     public void testProviderRequest_BackgroundThrottle() {
986         ILocationListener listener1 = createMockLocationListener();
987         LocationRequest request1 = new LocationRequest.Builder(5)
988                 .setWorkSource(WORK_SOURCE)
989                 .build();
990         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
991 
992         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
993 
994         mInjector.getAppForegroundHelper().setAppForeground(IDENTITY.getUid(), false);
995         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(
996                 mInjector.getSettingsHelper().getBackgroundThrottleIntervalMs());
997     }
998 
999     @Test
testProviderRequest_IgnoreLocationSettings()1000     public void testProviderRequest_IgnoreLocationSettings() {
1001         mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
1002                 new PackageTagsList.Builder().add(
1003                         IDENTITY.getPackageName()).build());
1004 
1005         ILocationListener listener1 = createMockLocationListener();
1006         LocationRequest request1 = new LocationRequest.Builder(5)
1007                 .setWorkSource(WORK_SOURCE)
1008                 .build();
1009         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
1010 
1011         assertThat(mProvider.getRequest().isActive()).isTrue();
1012         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
1013         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
1014 
1015         ILocationListener listener2 = createMockLocationListener();
1016         LocationRequest request2 = new LocationRequest.Builder(1)
1017                 .setLocationSettingsIgnored(true)
1018                 .setWorkSource(WORK_SOURCE)
1019                 .build();
1020         mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
1021 
1022         assertThat(mProvider.getRequest().isActive()).isTrue();
1023         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
1024         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isTrue();
1025     }
1026 
1027     @Test
testProviderRequest_IgnoreLocationSettings_ProviderDisabled()1028     public void testProviderRequest_IgnoreLocationSettings_ProviderDisabled() {
1029         mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
1030                 new PackageTagsList.Builder().add(
1031                         IDENTITY.getPackageName()).build());
1032 
1033         ILocationListener listener1 = createMockLocationListener();
1034         LocationRequest request1 = new LocationRequest.Builder(1)
1035                 .setWorkSource(WORK_SOURCE)
1036                 .build();
1037         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
1038 
1039         ILocationListener listener2 = createMockLocationListener();
1040         LocationRequest request2 = new LocationRequest.Builder(5)
1041                 .setLocationSettingsIgnored(true)
1042                 .setWorkSource(WORK_SOURCE)
1043                 .build();
1044         mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
1045 
1046         mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId());
1047 
1048         assertThat(mProvider.getRequest().isActive()).isTrue();
1049         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
1050         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isTrue();
1051     }
1052 
1053     @Test
testProviderRequest_IgnoreLocationSettings_NoAllowlist()1054     public void testProviderRequest_IgnoreLocationSettings_NoAllowlist() {
1055         mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
1056                 new PackageTagsList.Builder().add(
1057                         IDENTITY.getPackageName()).build());
1058 
1059         ILocationListener listener = createMockLocationListener();
1060         LocationRequest request = new LocationRequest.Builder(1)
1061                 .setLocationSettingsIgnored(true)
1062                 .setWorkSource(WORK_SOURCE)
1063                 .build();
1064         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
1065 
1066         mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
1067                 new PackageTagsList.Builder().build());
1068 
1069         assertThat(mProvider.getRequest().isActive()).isTrue();
1070         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
1071         assertThat(mProvider.getRequest().isLocationSettingsIgnored()).isFalse();
1072     }
1073 
1074     @Test
testProviderRequest_BackgroundThrottle_IgnoreLocationSettings()1075     public void testProviderRequest_BackgroundThrottle_IgnoreLocationSettings() {
1076         mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
1077                 new PackageTagsList.Builder().add(
1078                         IDENTITY.getPackageName()).build());
1079 
1080         ILocationListener listener1 = createMockLocationListener();
1081         LocationRequest request1 = new LocationRequest.Builder(5)
1082                 .setLocationSettingsIgnored(true)
1083                 .setWorkSource(WORK_SOURCE)
1084                 .build();
1085         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
1086 
1087         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
1088 
1089         mInjector.getAppForegroundHelper().setAppForeground(IDENTITY.getUid(), false);
1090         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
1091     }
1092 
1093     @Test
testProviderRequest_AdasGnssBypass()1094     public void testProviderRequest_AdasGnssBypass() {
1095         doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_AUTOMOTIVE);
1096         doReturn(true).when(mResources).getBoolean(R.bool.config_defaultAdasGnssLocationEnabled);
1097 
1098         createManager(GPS_PROVIDER);
1099 
1100         ILocationListener listener1 = createMockLocationListener();
1101         LocationRequest request1 = new LocationRequest.Builder(5)
1102                 .setWorkSource(WORK_SOURCE)
1103                 .build();
1104         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
1105 
1106         assertThat(mProvider.getRequest().isActive()).isTrue();
1107         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
1108         assertThat(mProvider.getRequest().isAdasGnssBypass()).isFalse();
1109 
1110         ILocationListener listener2 = createMockLocationListener();
1111         LocationRequest request2 = new LocationRequest.Builder(1)
1112                 .setAdasGnssBypass(true)
1113                 .setWorkSource(WORK_SOURCE)
1114                 .build();
1115         mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
1116 
1117         assertThat(mProvider.getRequest().isActive()).isTrue();
1118         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(1);
1119         assertThat(mProvider.getRequest().isAdasGnssBypass()).isTrue();
1120     }
1121 
1122     @Test
testProviderRequest_AdasGnssBypass_ProviderDisabled()1123     public void testProviderRequest_AdasGnssBypass_ProviderDisabled() {
1124         doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_AUTOMOTIVE);
1125         doReturn(true).when(mResources).getBoolean(R.bool.config_defaultAdasGnssLocationEnabled);
1126 
1127         createManager(GPS_PROVIDER);
1128 
1129         ILocationListener listener1 = createMockLocationListener();
1130         LocationRequest request1 = new LocationRequest.Builder(1)
1131                 .setWorkSource(WORK_SOURCE)
1132                 .build();
1133         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
1134 
1135         ILocationListener listener2 = createMockLocationListener();
1136         LocationRequest request2 = new LocationRequest.Builder(5)
1137                 .setAdasGnssBypass(true)
1138                 .setWorkSource(WORK_SOURCE)
1139                 .build();
1140         mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
1141 
1142         mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId());
1143 
1144         assertThat(mProvider.getRequest().isActive()).isTrue();
1145         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
1146         assertThat(mProvider.getRequest().isAdasGnssBypass()).isTrue();
1147     }
1148 
1149     @Test
testProviderRequest_AdasGnssBypass_ProviderDisabled_AdasDisabled()1150     public void testProviderRequest_AdasGnssBypass_ProviderDisabled_AdasDisabled() {
1151         mInjector.getSettingsHelper().setIgnoreSettingsAllowlist(
1152                 new PackageTagsList.Builder().add(
1153                         IDENTITY.getPackageName()).build());
1154         doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_AUTOMOTIVE);
1155         doReturn(true).when(mResources).getBoolean(R.bool.config_defaultAdasGnssLocationEnabled);
1156 
1157         createManager(GPS_PROVIDER);
1158 
1159         ILocationListener listener1 = createMockLocationListener();
1160         LocationRequest request1 = new LocationRequest.Builder(5)
1161                 .setLocationSettingsIgnored(true)
1162                 .setWorkSource(WORK_SOURCE)
1163                 .build();
1164         mManager.registerLocationRequest(request1, IDENTITY, PERMISSION_FINE, listener1);
1165 
1166         ILocationListener listener2 = createMockLocationListener();
1167         LocationRequest request2 = new LocationRequest.Builder(1)
1168                 .setAdasGnssBypass(true)
1169                 .setWorkSource(WORK_SOURCE)
1170                 .build();
1171         mManager.registerLocationRequest(request2, IDENTITY, PERMISSION_FINE, listener2);
1172 
1173         mInjector.getLocationSettings().updateUserSettings(IDENTITY.getUserId(),
1174                 settings -> settings.withAdasGnssLocationEnabled(false));
1175         mInjector.getSettingsHelper().setLocationEnabled(false, IDENTITY.getUserId());
1176 
1177         assertThat(mProvider.getRequest().isActive()).isTrue();
1178         assertThat(mProvider.getRequest().getIntervalMillis()).isEqualTo(5);
1179         assertThat(mProvider.getRequest().isAdasGnssBypass()).isFalse();
1180     }
1181 
1182     @Test
testProviderRequest_BatterySaver_ScreenOnOff()1183     public void testProviderRequest_BatterySaver_ScreenOnOff() {
1184         mInjector.getLocationPowerSaveModeHelper().setLocationPowerSaveMode(
1185                 LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF);
1186 
1187         ILocationListener listener = createMockLocationListener();
1188         LocationRequest request = new LocationRequest.Builder(5).setWorkSource(WORK_SOURCE).build();
1189         mManager.registerLocationRequest(request, IDENTITY, PERMISSION_FINE, listener);
1190 
1191         assertThat(mProvider.getRequest().isActive()).isTrue();
1192 
1193         mInjector.getScreenInteractiveHelper().setScreenInteractive(false);
1194         assertThat(mProvider.getRequest().isActive()).isFalse();
1195     }
1196 
createMockLocationListener()1197     private ILocationListener createMockLocationListener() {
1198         return spy(new ILocationListener.Stub() {
1199             @Override
1200             public void onLocationChanged(List<Location> locations,
1201                     IRemoteCallback onCompleteCallback) {
1202                 if (onCompleteCallback != null) {
1203                     try {
1204                         onCompleteCallback.sendResult(null);
1205                     } catch (RemoteException e) {
1206                         e.rethrowFromSystemServer();
1207                     }
1208                 }
1209             }
1210 
1211             @Override
1212             public void onFlushComplete(int requestCode) {
1213             }
1214 
1215             @Override
1216             public void onProviderEnabledChanged(String provider, boolean enabled) {
1217             }
1218         });
1219     }
1220 
1221     private ILocationCallback createMockGetCurrentLocationListener() {
1222         return spy(new ILocationCallback.Stub() {
1223             @Override
1224             public void onLocation(Location location) {
1225             }
1226         });
1227     }
1228 
1229     private static class TestProvider extends AbstractLocationProvider {
1230 
1231         private ProviderRequest mProviderRequest = ProviderRequest.EMPTY_REQUEST;
1232 
1233         private final ArrayList<Runnable> mFlushCallbacks = new ArrayList<>();
1234 
1235         TestProvider(ProviderProperties properties, CallerIdentity identity) {
1236             super(DIRECT_EXECUTOR, identity, properties, Collections.emptySet());
1237         }
1238 
1239         public void setProviderAllowed(boolean allowed) {
1240             setAllowed(allowed);
1241         }
1242 
1243         public void setProviderLocation(Location l) {
1244             reportLocation(LocationResult.create(new Location(l)));
1245         }
1246 
1247         public void setProviderLocation(LocationResult l) {
1248             reportLocation(l);
1249         }
1250 
1251         public void completeFlushes() {
1252             for (Runnable r : mFlushCallbacks) {
1253                 r.run();
1254             }
1255             mFlushCallbacks.clear();
1256         }
1257 
1258         public ProviderRequest getRequest() {
1259             return mProviderRequest;
1260         }
1261 
1262         @Override
1263         public void onSetRequest(ProviderRequest request) {
1264             mProviderRequest = request;
1265         }
1266 
1267         @Override
1268         protected void onFlush(Runnable callback) {
1269             mFlushCallbacks.add(callback);
1270         }
1271 
1272         @Override
1273         protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {
1274         }
1275 
1276         @Override
1277         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1278         }
1279     }
1280 }
1281