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