• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
18 
19 import static android.Manifest.permission.ACCESS_FINE_LOCATION;
20 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
21 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
22 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
23 import static android.location.LocationManager.FUSED_PROVIDER;
24 import static android.location.LocationManager.GPS_PROVIDER;
25 import static android.location.LocationManager.NETWORK_PROVIDER;
26 import static android.location.LocationManager.PASSIVE_PROVIDER;
27 import static android.os.PowerManager.locationPowerSaveModeToString;
28 
29 import static com.android.server.location.CallerIdentity.PERMISSION_COARSE;
30 import static com.android.server.location.CallerIdentity.PERMISSION_FINE;
31 import static com.android.server.location.UserInfoHelper.UserListener.CURRENT_USER_CHANGED;
32 import static com.android.server.location.UserInfoHelper.UserListener.USER_STARTED;
33 import static com.android.server.location.UserInfoHelper.UserListener.USER_STOPPED;
34 
35 import static java.util.concurrent.TimeUnit.NANOSECONDS;
36 
37 import android.Manifest;
38 import android.annotation.NonNull;
39 import android.annotation.Nullable;
40 import android.annotation.UserIdInt;
41 import android.app.ActivityManager;
42 import android.app.AppOpsManager;
43 import android.app.PendingIntent;
44 import android.content.BroadcastReceiver;
45 import android.content.Context;
46 import android.content.Intent;
47 import android.content.IntentFilter;
48 import android.location.Address;
49 import android.location.Criteria;
50 import android.location.GeocoderParams;
51 import android.location.Geofence;
52 import android.location.GnssCapabilities;
53 import android.location.GnssMeasurementCorrections;
54 import android.location.GnssRequest;
55 import android.location.IBatchedLocationCallback;
56 import android.location.IGnssAntennaInfoListener;
57 import android.location.IGnssMeasurementsListener;
58 import android.location.IGnssNavigationMessageListener;
59 import android.location.IGnssStatusListener;
60 import android.location.IGpsGeofenceHardware;
61 import android.location.ILocationListener;
62 import android.location.ILocationManager;
63 import android.location.Location;
64 import android.location.LocationManager;
65 import android.location.LocationManagerInternal;
66 import android.location.LocationProvider;
67 import android.location.LocationRequest;
68 import android.location.LocationTime;
69 import android.os.Binder;
70 import android.os.Build;
71 import android.os.Bundle;
72 import android.os.CancellationSignal;
73 import android.os.Handler;
74 import android.os.IBinder;
75 import android.os.ICancellationSignal;
76 import android.os.ParcelFileDescriptor;
77 import android.os.PowerManager;
78 import android.os.PowerManager.ServiceType;
79 import android.os.PowerManagerInternal;
80 import android.os.Process;
81 import android.os.RemoteException;
82 import android.os.SystemClock;
83 import android.os.UserHandle;
84 import android.os.WorkSource;
85 import android.os.WorkSource.WorkChain;
86 import android.stats.location.LocationStatsEnums;
87 import android.text.TextUtils;
88 import android.util.EventLog;
89 import android.util.Log;
90 import android.util.SparseArray;
91 import android.util.TimeUtils;
92 
93 import com.android.internal.annotations.GuardedBy;
94 import com.android.internal.content.PackageMonitor;
95 import com.android.internal.location.ProviderProperties;
96 import com.android.internal.location.ProviderRequest;
97 import com.android.internal.util.DumpUtils;
98 import com.android.internal.util.IndentingPrintWriter;
99 import com.android.internal.util.Preconditions;
100 import com.android.server.FgThread;
101 import com.android.server.LocalServices;
102 import com.android.server.PendingIntentUtils;
103 import com.android.server.SystemService;
104 import com.android.server.location.AbstractLocationProvider.State;
105 import com.android.server.location.CallerIdentity.PermissionLevel;
106 import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
107 import com.android.server.location.LocationRequestStatistics.PackageStatistics;
108 import com.android.server.location.UserInfoHelper.UserListener.UserChange;
109 import com.android.server.location.gnss.GnssManagerService;
110 import com.android.server.pm.permission.PermissionManagerServiceInternal;
111 
112 import java.io.ByteArrayOutputStream;
113 import java.io.FileDescriptor;
114 import java.io.PrintStream;
115 import java.io.PrintWriter;
116 import java.util.ArrayList;
117 import java.util.Collections;
118 import java.util.HashMap;
119 import java.util.HashSet;
120 import java.util.List;
121 import java.util.Map;
122 import java.util.Map.Entry;
123 import java.util.Objects;
124 import java.util.Set;
125 import java.util.TreeMap;
126 import java.util.concurrent.CopyOnWriteArrayList;
127 
128 /**
129  * The service class that manages LocationProviders and issues location
130  * updates and alerts.
131  */
132 public class LocationManagerService extends ILocationManager.Stub {
133 
134     /**
135      * Controls lifecycle of LocationManagerService.
136      */
137     public static class Lifecycle extends SystemService {
138 
139         private final UserInfoHelper mUserInfoHelper;
140         private final LocationManagerService mService;
141 
Lifecycle(Context context)142         public Lifecycle(Context context) {
143             super(context);
144             mUserInfoHelper = new SystemUserInfoHelper(context);
145             mService = new LocationManagerService(context, mUserInfoHelper);
146         }
147 
148         @Override
onStart()149         public void onStart() {
150             // enable client caches by doing the first invalidate
151             LocationManager.invalidateLocalLocationEnabledCaches();
152 
153             publishBinderService(Context.LOCATION_SERVICE, mService);
154             // disable caching for whatever process contains LocationManagerService
155             ((LocationManager) mService.mContext.getSystemService(LocationManager.class))
156                     .disableLocalLocationEnabledCaches();
157         }
158 
159         @Override
onBootPhase(int phase)160         public void onBootPhase(int phase) {
161             if (phase == PHASE_SYSTEM_SERVICES_READY) {
162                 // the location service must be functioning after this boot phase
163                 mService.onSystemReady();
164             } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
165                 // some providers rely on third party code, so we wait to initialize
166                 // providers until third party code is allowed to run
167                 mService.onSystemThirdPartyAppsCanStart();
168             }
169         }
170 
171         @Override
onUserStarting(TargetUser user)172         public void onUserStarting(TargetUser user) {
173             mUserInfoHelper.dispatchOnUserStarted(user.getUserIdentifier());
174         }
175 
176         @Override
onUserSwitching(TargetUser from, TargetUser to)177         public void onUserSwitching(TargetUser from, TargetUser to) {
178             mUserInfoHelper.dispatchOnCurrentUserChanged(from.getUserIdentifier(),
179                     to.getUserIdentifier());
180         }
181 
182         @Override
onUserStopped(TargetUser user)183         public void onUserStopped(TargetUser user) {
184             mUserInfoHelper.dispatchOnUserStopped(user.getUserIdentifier());
185         }
186 
187         private static class SystemUserInfoHelper extends UserInfoHelper {
188 
SystemUserInfoHelper(Context context)189             SystemUserInfoHelper(Context context) {
190                 super(context);
191             }
192         }
193     }
194 
195     public static final String TAG = "LocationManagerService";
196     public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
197 
198     private static final String WAKELOCK_KEY = "*location*";
199 
200     private static final String NETWORK_LOCATION_SERVICE_ACTION =
201             "com.android.location.service.v3.NetworkLocationProvider";
202     private static final String FUSED_LOCATION_SERVICE_ACTION =
203             "com.android.location.service.FusedLocationProvider";
204 
205     // The maximum interval a location request can have and still be considered "high power".
206     private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
207 
208     // The fastest interval that applications can receive coarse locations
209     private static final long FASTEST_COARSE_INTERVAL_MS = 10 * 60 * 1000;
210 
211     // maximum age of a location before it is no longer considered "current"
212     private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000;
213 
214     // Location Providers may sometimes deliver location updates
215     // slightly faster that requested - provide grace period so
216     // we don't unnecessarily filter events that are otherwise on
217     // time
218     private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
219 
220     private static final String ATTRIBUTION_TAG = "LocationService";
221 
222     private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
223 
224     private final Object mLock = new Object();
225     private final Context mContext;
226     private final Handler mHandler;
227     private final LocalService mLocalService;
228     private final AppOpsHelper mAppOpsHelper;
229     private final UserInfoHelper mUserInfoHelper;
230     private final SettingsHelper mSettingsHelper;
231     private final AppForegroundHelper mAppForegroundHelper;
232     private final LocationUsageLogger mLocationUsageLogger;
233 
234     @Nullable private volatile GnssManagerService mGnssManagerService = null;
235 
236     private final PassiveLocationProviderManager mPassiveManager;
237 
238     private PowerManager mPowerManager;
239 
240     private GeofenceManager mGeofenceManager;
241     private GeocoderProxy mGeocodeProvider;
242 
243     @GuardedBy("mLock")
244     private String mExtraLocationControllerPackage;
245     @GuardedBy("mLock")
246     private boolean mExtraLocationControllerPackageEnabled;
247 
248     // @GuardedBy("mLock")
249     // hold lock for write or to prevent write, no lock for read
250     private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers =
251             new CopyOnWriteArrayList<>();
252 
253     @GuardedBy("mLock")
254     private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
255     private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
256             new HashMap<>();
257 
258     private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
259 
260     @GuardedBy("mLock")
261     @PowerManager.LocationPowerSaveMode
262     private int mBatterySaverMode;
263 
LocationManagerService(Context context, UserInfoHelper userInfoHelper)264     private LocationManagerService(Context context, UserInfoHelper userInfoHelper) {
265         mContext = context.createAttributionContext(ATTRIBUTION_TAG);
266         mHandler = FgThread.getHandler();
267         mLocalService = new LocalService();
268 
269         LocalServices.addService(LocationManagerInternal.class, mLocalService);
270 
271         mAppOpsHelper = new AppOpsHelper(mContext);
272         mUserInfoHelper = userInfoHelper;
273         mSettingsHelper = new SettingsHelper(mContext, mHandler);
274         mAppForegroundHelper = new AppForegroundHelper(mContext);
275         mLocationUsageLogger = new LocationUsageLogger();
276 
277         // set up passive provider - we do this early because it has no dependencies on system
278         // services or external code that isn't ready yet, and because this allows the variable to
279         // be final. other more complex providers are initialized later, when system services are
280         // ready
281         mPassiveManager = new PassiveLocationProviderManager();
282         mProviderManagers.add(mPassiveManager);
283         mPassiveManager.setRealProvider(new PassiveProvider(mContext));
284 
285         // Let the package manager query which are the default location
286         // providers as they get certain permissions granted by default.
287         PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService(
288                 PermissionManagerServiceInternal.class);
289         permissionManagerInternal.setLocationPackagesProvider(
290                 userId -> mContext.getResources().getStringArray(
291                         com.android.internal.R.array.config_locationProviderPackageNames));
292         permissionManagerInternal.setLocationExtraPackagesProvider(
293                 userId -> mContext.getResources().getStringArray(
294                         com.android.internal.R.array.config_locationExtraPackageNames));
295 
296         // most startup is deferred until systemReady()
297     }
298 
onSystemReady()299     private void onSystemReady() {
300         mAppOpsHelper.onSystemReady();
301         mUserInfoHelper.onSystemReady();
302         mSettingsHelper.onSystemReady();
303         mAppForegroundHelper.onSystemReady();
304 
305         synchronized (mLock) {
306             mPowerManager = mContext.getSystemService(PowerManager.class);
307             mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper);
308 
309             // add listeners
310             mContext.getPackageManager().addOnPermissionsChangeListener(
311                     uid -> {
312                         // listener invoked on ui thread, move to our thread to reduce risk of
313                         // blocking ui thread
314                         mHandler.post(() -> {
315                             synchronized (mLock) {
316                                 onPermissionsChangedLocked();
317                             }
318                         });
319                     });
320 
321             LocalServices.getService(PowerManagerInternal.class).registerLowPowerModeObserver(
322                     ServiceType.LOCATION,
323                     state -> {
324                         // listener invoked on ui thread, move to our thread to reduce risk of
325                         // blocking ui thread
326                         mHandler.post(() -> {
327                             synchronized (mLock) {
328                                 onBatterySaverModeChangedLocked(state.locationMode);
329                             }
330                         });
331                     });
332             mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
333 
334             mAppOpsHelper.addListener(this::onAppOpChanged);
335 
336             mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged);
337             mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener(
338                     this::onBackgroundThrottleIntervalChanged);
339             mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener(
340                     this::onBackgroundThrottleWhitelistChanged);
341             mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener(
342                     this::onIgnoreSettingsWhitelistChanged);
343 
344             PackageMonitor packageMonitor = new PackageMonitor() {
345                 @Override
346                 public void onPackageDisappeared(String packageName, int reason) {
347                     synchronized (mLock) {
348                         LocationManagerService.this.onPackageDisappeared(packageName);
349                     }
350                 }
351             };
352             packageMonitor.register(mContext, null, true, mHandler);
353 
354             mUserInfoHelper.addListener(this::onUserChanged);
355 
356             mAppForegroundHelper.addListener(this::onAppForegroundChanged);
357 
358             IntentFilter screenIntentFilter = new IntentFilter();
359             screenIntentFilter.addAction(Intent.ACTION_SCREEN_OFF);
360             screenIntentFilter.addAction(Intent.ACTION_SCREEN_ON);
361             mContext.registerReceiverAsUser(new BroadcastReceiver() {
362                 @Override
363                 public void onReceive(Context context, Intent intent) {
364                     if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())
365                             || Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
366                         onScreenStateChanged();
367                     }
368                 }
369             }, UserHandle.ALL, screenIntentFilter, null, mHandler);
370 
371             // initialize the current users. we would get the user started notifications for these
372             // users eventually anyways, but this takes care of it as early as possible.
373             for (int userId: mUserInfoHelper.getCurrentUserIds()) {
374                 onUserChanged(userId, USER_STARTED);
375             }
376         }
377     }
378 
onSystemThirdPartyAppsCanStart()379     private void onSystemThirdPartyAppsCanStart() {
380         synchronized (mLock) {
381             // prepare providers
382             initializeProvidersLocked();
383         }
384 
385         // initialize gnss last because it has no awareness of boot phases and blindly assumes that
386         // all other location providers are loaded at initialization
387         initializeGnss();
388     }
389 
onAppOpChanged(String packageName)390     private void onAppOpChanged(String packageName) {
391         synchronized (mLock) {
392             for (Receiver receiver : mReceivers.values()) {
393                 if (receiver.mCallerIdentity.packageName.equals(packageName)) {
394                     receiver.updateMonitoring(true);
395                 }
396             }
397 
398             HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
399             for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
400                 String provider = entry.getKey();
401                 for (UpdateRecord record : entry.getValue()) {
402                     if (record.mReceiver.mCallerIdentity.packageName.equals(packageName)) {
403                         affectedProviders.add(provider);
404                     }
405                 }
406             }
407             for (String provider : affectedProviders) {
408                 applyRequirementsLocked(provider);
409             }
410         }
411     }
412 
413     @GuardedBy("mLock")
onPermissionsChangedLocked()414     private void onPermissionsChangedLocked() {
415         for (LocationProviderManager manager : mProviderManagers) {
416             applyRequirementsLocked(manager);
417         }
418     }
419 
420     @GuardedBy("mLock")
onBatterySaverModeChangedLocked(int newLocationMode)421     private void onBatterySaverModeChangedLocked(int newLocationMode) {
422         if (mBatterySaverMode == newLocationMode) {
423             return;
424         }
425 
426         if (D) {
427             Log.d(TAG,
428                     "Battery Saver location mode changed from "
429                             + locationPowerSaveModeToString(mBatterySaverMode) + " to "
430                             + locationPowerSaveModeToString(newLocationMode));
431         }
432 
433         mBatterySaverMode = newLocationMode;
434 
435         for (LocationProviderManager manager : mProviderManagers) {
436             applyRequirementsLocked(manager);
437         }
438     }
439 
onScreenStateChanged()440     private void onScreenStateChanged() {
441         synchronized (mLock) {
442             if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) {
443                 for (LocationProviderManager manager : mProviderManagers) {
444                     applyRequirementsLocked(manager);
445                 }
446             }
447         }
448     }
449 
onLocationModeChanged(int userId)450     private void onLocationModeChanged(int userId) {
451         boolean enabled = mSettingsHelper.isLocationEnabled(userId);
452         LocationManager.invalidateLocalLocationEnabledCaches();
453 
454         if (D) {
455             Log.d(TAG, "[u" + userId + "] location enabled = " + enabled);
456         }
457 
458         Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION)
459                 .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled)
460                 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
461                 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
462         mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
463 
464         synchronized (mLock) {
465             for (LocationProviderManager manager : mProviderManagers) {
466                 manager.onEnabledChangedLocked(userId);
467             }
468         }
469     }
470 
onPackageDisappeared(String packageName)471     private void onPackageDisappeared(String packageName) {
472         synchronized (mLock) {
473             ArrayList<Receiver> deadReceivers = null;
474 
475             for (Receiver receiver : mReceivers.values()) {
476                 if (receiver.mCallerIdentity.packageName.equals(packageName)) {
477                     if (deadReceivers == null) {
478                         deadReceivers = new ArrayList<>();
479                     }
480                     deadReceivers.add(receiver);
481                 }
482             }
483 
484             // perform removal outside of mReceivers loop
485             if (deadReceivers != null) {
486                 for (Receiver receiver : deadReceivers) {
487                     removeUpdatesLocked(receiver);
488                 }
489             }
490         }
491     }
492 
onAppForegroundChanged(int uid, boolean foreground)493     private void onAppForegroundChanged(int uid, boolean foreground) {
494         synchronized (mLock) {
495             HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
496             for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
497                 String provider = entry.getKey();
498                 for (UpdateRecord record : entry.getValue()) {
499                     if (record.mReceiver.mCallerIdentity.uid == uid
500                             && record.mIsForegroundUid != foreground) {
501                         record.updateForeground(foreground);
502 
503                         if (!isThrottlingExempt(record.mReceiver.mCallerIdentity)) {
504                             affectedProviders.add(provider);
505                         }
506                     }
507                 }
508             }
509             for (String provider : affectedProviders) {
510                 applyRequirementsLocked(provider);
511             }
512         }
513     }
514 
onBackgroundThrottleIntervalChanged()515     private void onBackgroundThrottleIntervalChanged() {
516         synchronized (mLock) {
517             for (LocationProviderManager manager : mProviderManagers) {
518                 applyRequirementsLocked(manager);
519             }
520         }
521     }
522 
onBackgroundThrottleWhitelistChanged()523     private void onBackgroundThrottleWhitelistChanged() {
524         synchronized (mLock) {
525             for (LocationProviderManager manager : mProviderManagers) {
526                 applyRequirementsLocked(manager);
527             }
528         }
529     }
530 
onIgnoreSettingsWhitelistChanged()531     private void onIgnoreSettingsWhitelistChanged() {
532         synchronized (mLock) {
533             for (LocationProviderManager manager : mProviderManagers) {
534                 applyRequirementsLocked(manager);
535             }
536         }
537     }
538 
539     @GuardedBy("mLock")
initializeProvidersLocked()540     private void initializeProvidersLocked() {
541         LocationProviderProxy networkProvider = LocationProviderProxy.createAndRegister(
542                 mContext,
543                 NETWORK_LOCATION_SERVICE_ACTION,
544                 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
545                 com.android.internal.R.string.config_networkLocationProviderPackageName);
546         if (networkProvider != null) {
547             LocationProviderManager networkManager = new LocationProviderManager(NETWORK_PROVIDER);
548             mProviderManagers.add(networkManager);
549             networkManager.setRealProvider(networkProvider);
550         } else {
551             Log.w(TAG, "no network location provider found");
552         }
553 
554         // ensure that a fused provider exists which will work in direct boot
555         Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser(
556                 new Intent(FUSED_LOCATION_SERVICE_ACTION),
557                 MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(),
558                 "Unable to find a direct boot aware fused location provider");
559 
560         // bind to fused provider
561         LocationProviderProxy fusedProvider = LocationProviderProxy.createAndRegister(
562                 mContext,
563                 FUSED_LOCATION_SERVICE_ACTION,
564                 com.android.internal.R.bool.config_enableFusedLocationOverlay,
565                 com.android.internal.R.string.config_fusedLocationProviderPackageName);
566         if (fusedProvider != null) {
567             LocationProviderManager fusedManager = new LocationProviderManager(FUSED_PROVIDER);
568             mProviderManagers.add(fusedManager);
569             fusedManager.setRealProvider(fusedProvider);
570         } else {
571             Log.e(TAG, "no fused location provider found");
572         }
573 
574         // bind to geocoder provider
575         mGeocodeProvider = GeocoderProxy.createAndRegister(mContext);
576         if (mGeocodeProvider == null) {
577             Log.e(TAG, "no geocoder provider found");
578         }
579 
580         // bind to hardware activity recognition
581         HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy =
582                 HardwareActivityRecognitionProxy.createAndRegister(mContext);
583         if (hardwareActivityRecognitionProxy == null) {
584             Log.e(TAG, "unable to bind ActivityRecognitionProxy");
585         }
586 
587         String[] testProviderStrings = mContext.getResources().getStringArray(
588                 com.android.internal.R.array.config_testLocationProviders);
589         for (String testProviderString : testProviderStrings) {
590             String[] fragments = testProviderString.split(",");
591             String name = fragments[0].trim();
592             ProviderProperties properties = new ProviderProperties(
593                     Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
594                     Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
595                     Boolean.parseBoolean(fragments[3]) /* requiresCell */,
596                     Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
597                     Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
598                     Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
599                     Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
600                     Integer.parseInt(fragments[8]) /* powerRequirement */,
601                     Integer.parseInt(fragments[9]) /* accuracy */);
602             LocationProviderManager manager = getLocationProviderManager(name);
603             if (manager == null) {
604                 manager = new LocationProviderManager(name);
605                 mProviderManagers.add(manager);
606             }
607             manager.setMockProvider(new MockProvider(properties));
608         }
609     }
610 
initializeGnss()611     private void initializeGnss() {
612         // Do not hold mLock when calling GnssManagerService#isGnssSupported() which calls into HAL.
613         if (GnssManagerService.isGnssSupported()) {
614             mGnssManagerService = new GnssManagerService(mContext, mAppOpsHelper, mSettingsHelper,
615                     mAppForegroundHelper, mLocationUsageLogger);
616             mGnssManagerService.onSystemReady();
617 
618             LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER);
619             synchronized (mLock) {
620                 mProviderManagers.add(gnssManager);
621             }
622             gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider());
623 
624             // bind to geofence proxy
625             IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy();
626             if (gpsGeofenceHardware != null) {
627                 GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware);
628                 if (provider == null) {
629                     Log.e(TAG, "unable to bind to GeofenceProxy");
630                 }
631             }
632         }
633     }
634 
onUserChanged(@serIdInt int userId, @UserChange int change)635     private void onUserChanged(@UserIdInt int userId, @UserChange int change) {
636         switch (change) {
637             case CURRENT_USER_CHANGED:
638                 synchronized (mLock) {
639                     for (LocationProviderManager manager : mProviderManagers) {
640                         manager.onEnabledChangedLocked(userId);
641                     }
642                 }
643                 break;
644             case USER_STARTED:
645                 synchronized (mLock) {
646                     for (LocationProviderManager manager : mProviderManagers) {
647                         manager.onUserStarted(userId);
648                     }
649                 }
650                 break;
651             case USER_STOPPED:
652                 synchronized (mLock) {
653                     for (LocationProviderManager manager : mProviderManagers) {
654                         manager.onUserStopped(userId);
655                     }
656                 }
657                 break;
658         }
659     }
660 
661     /**
662      * Location provider manager, manages a LocationProvider.
663      */
664     class LocationProviderManager implements MockableLocationProvider.Listener {
665 
666         private final String mName;
667 
668         private final LocationFudger mLocationFudger;
669 
670         // if the provider is enabled for a given user id - null or not present means unknown
671         @GuardedBy("mLock")
672         private final SparseArray<Boolean> mEnabled;
673 
674         // last location for a given user
675         @GuardedBy("mLock")
676         private final SparseArray<Location> mLastLocation;
677 
678         // last coarse location for a given user
679         @GuardedBy("mLock")
680         private final SparseArray<Location> mLastCoarseLocation;
681 
682         // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary
683         protected final MockableLocationProvider mProvider;
684 
LocationProviderManager(String name)685         private LocationProviderManager(String name) {
686             mName = name;
687             mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
688             mEnabled = new SparseArray<>(2);
689             mLastLocation = new SparseArray<>(2);
690             mLastCoarseLocation = new SparseArray<>(2);
691 
692             // initialize last since this lets our reference escape
693             mProvider = new MockableLocationProvider(mLock, this);
694         }
695 
getName()696         public String getName() {
697             return mName;
698         }
699 
hasProvider()700         public boolean hasProvider() {
701             return mProvider.getProvider() != null;
702         }
703 
setRealProvider(AbstractLocationProvider provider)704         public void setRealProvider(AbstractLocationProvider provider) {
705             mProvider.setRealProvider(provider);
706         }
707 
setMockProvider(@ullable MockProvider provider)708         public void setMockProvider(@Nullable MockProvider provider) {
709             synchronized (mLock) {
710                 mProvider.setMockProvider(provider);
711 
712                 // when removing a mock provider, also clear any mock last locations and reset the
713                 // location fudger. the mock provider could have been used to infer the current
714                 // location fudger offsets.
715                 if (provider == null) {
716                     for (int i = 0; i < mLastLocation.size(); i++) {
717                         Location lastLocation = mLastLocation.valueAt(i);
718                         if (lastLocation != null && lastLocation.isFromMockProvider()) {
719                             mLastLocation.setValueAt(i, null);
720                         }
721                     }
722 
723                     for (int i = 0; i < mLastCoarseLocation.size(); i++) {
724                         Location lastCoarseLocation = mLastCoarseLocation.valueAt(i);
725                         if (lastCoarseLocation != null && lastCoarseLocation.isFromMockProvider()) {
726                             mLastCoarseLocation.setValueAt(i, null);
727                         }
728                     }
729 
730                     mLocationFudger.resetOffsets();
731                 }
732             }
733         }
734 
getPackages()735         public Set<String> getPackages() {
736             return mProvider.getState().providerPackageNames;
737         }
738 
739         @Nullable
getProperties()740         public ProviderProperties getProperties() {
741             return mProvider.getState().properties;
742         }
743 
744         @Nullable
getLastLocation(int userId, @PermissionLevel int permissionlevel)745         public Location getLastLocation(int userId, @PermissionLevel int permissionlevel) {
746             synchronized (mLock) {
747                 switch (permissionlevel) {
748                     case PERMISSION_COARSE:
749                         return mLastCoarseLocation.get(userId);
750                     case PERMISSION_FINE:
751                         return mLastLocation.get(userId);
752                     default:
753                         throw new AssertionError();
754                 }
755             }
756         }
757 
injectLastLocation(Location location, int userId)758         public void injectLastLocation(Location location, int userId) {
759             synchronized (mLock) {
760                 if (mLastLocation.get(userId) == null) {
761                     setLastLocation(location, userId);
762                 }
763             }
764         }
765 
setLastLocation(Location location, int userId)766         private void setLastLocation(Location location, int userId) {
767             synchronized (mLock) {
768                 mLastLocation.put(userId, location);
769 
770                 // update last coarse interval only if enough time has passed
771                 long timeDeltaMs = Long.MAX_VALUE;
772                 Location coarseLocation = mLastCoarseLocation.get(userId);
773                 if (coarseLocation != null) {
774                     timeDeltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeNanos())
775                             - NANOSECONDS.toMillis(coarseLocation.getElapsedRealtimeNanos());
776                 }
777                 if (timeDeltaMs > FASTEST_COARSE_INTERVAL_MS) {
778                     mLastCoarseLocation.put(userId, mLocationFudger.createCoarse(location));
779                 }
780             }
781         }
782 
setMockProviderAllowed(boolean enabled)783         public void setMockProviderAllowed(boolean enabled) {
784             synchronized (mLock) {
785                 if (!mProvider.isMock()) {
786                     throw new IllegalArgumentException(mName + " provider is not a test provider");
787                 }
788 
789                 mProvider.setMockProviderAllowed(enabled);
790             }
791         }
792 
setMockProviderLocation(Location location)793         public void setMockProviderLocation(Location location) {
794             synchronized (mLock) {
795                 if (!mProvider.isMock()) {
796                     throw new IllegalArgumentException(mName + " provider is not a test provider");
797                 }
798 
799                 String locationProvider = location.getProvider();
800                 if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) {
801                     // The location has an explicit provider that is different from the mock
802                     // provider name. The caller may be trying to fool us via b/33091107.
803                     EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
804                             mName + "!=" + locationProvider);
805                 }
806 
807                 mProvider.setMockProviderLocation(location);
808             }
809         }
810 
getMockProviderRequests()811         public List<LocationRequest> getMockProviderRequests() {
812             synchronized (mLock) {
813                 if (!mProvider.isMock()) {
814                     throw new IllegalArgumentException(mName + " provider is not a test provider");
815                 }
816 
817                 return mProvider.getCurrentRequest().locationRequests;
818             }
819         }
820 
setRequest(ProviderRequest request)821         public void setRequest(ProviderRequest request) {
822             mProvider.setRequest(request);
823         }
824 
sendExtraCommand(int uid, int pid, String command, Bundle extras)825         public void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
826             mProvider.sendExtraCommand(uid, pid, command, extras);
827         }
828 
829         @GuardedBy("mLock")
830         @Override
onReportLocation(Location location)831         public void onReportLocation(Location location) {
832             // don't validate mock locations
833             if (!location.isFromMockProvider()) {
834                 if (location.getLatitude() == 0 && location.getLongitude() == 0) {
835                     Log.w(TAG, "blocking 0,0 location from " + mName + " provider");
836                     return;
837                 }
838             }
839 
840             if (!location.isComplete()) {
841                 Log.w(TAG, "blocking incomplete location from " + mName + " provider");
842                 return;
843             }
844 
845             // update last location if the provider is enabled or if servicing a bypass request
846             boolean locationSettingsIgnored = mProvider.getCurrentRequest().locationSettingsIgnored;
847             for (int userId : mUserInfoHelper.getCurrentUserIds()) {
848                 if (locationSettingsIgnored || isEnabled(userId)) {
849                     setLastLocation(location, userId);
850                 }
851             }
852 
853             handleLocationChangedLocked(this, location, mLocationFudger.createCoarse(location));
854         }
855 
856         @GuardedBy("mLock")
857         @Override
onReportLocation(List<Location> locations)858         public void onReportLocation(List<Location> locations) {
859             if (mGnssManagerService == null || !GPS_PROVIDER.equals(mName)) {
860                 return;
861             }
862 
863             mGnssManagerService.onReportLocation(locations);
864         }
865 
866         @GuardedBy("mLock")
867         @Override
onStateChanged(State oldState, State newState)868         public void onStateChanged(State oldState, State newState) {
869             if (oldState.allowed != newState.allowed) {
870                 onEnabledChangedLocked(UserHandle.USER_ALL);
871             }
872         }
873 
onUserStarted(int userId)874         public void onUserStarted(int userId) {
875             synchronized (mLock) {
876                 // clear the user's enabled state in order to force a reevalution of whether the
877                 // provider is enabled or disabled for the given user. we clear the user's state
878                 // first to ensure that a user starting never causes any change notifications. it's
879                 // possible for us to observe a user before we observe it's been started (for
880                 // example, another component gets a user started notification before us and
881                 // registers a location request immediately), which would cause us to already have
882                 // some state in place. when we eventually do get the user started notification
883                 // ourselves we don't want to send a change notification based on the prior state
884                 mEnabled.put(userId, null);
885                 onEnabledChangedLocked(userId);
886             }
887         }
888 
onUserStopped(int userId)889         public void onUserStopped(int userId) {
890             synchronized (mLock) {
891                 mEnabled.remove(userId);
892                 mLastLocation.remove(userId);
893                 mLastCoarseLocation.remove(userId);
894             }
895         }
896 
isEnabled(int userId)897         public boolean isEnabled(int userId) {
898             if (userId == UserHandle.USER_NULL) {
899                 // used during initialization - ignore since many lower level operations (checking
900                 // settings for instance) do not support the null user
901                 return false;
902             }
903 
904             synchronized (mLock) {
905                 Boolean enabled = mEnabled.get(userId);
906                 if (enabled == null) {
907                     // this generally shouldn't occur, but might be possible due to race conditions
908                     // on when we are notified of new users
909 
910                     // hack to fix b/171910679. mutating the user enabled state within this method
911                     // may cause unexpected changes to other state (for instance, this could cause
912                     // provider enable/disable notifications to be sent to clients, which could
913                     // result in a dead client being detected, which could result in the client
914                     // being removed, which means that if this function is called while clients are
915                     // being iterated over we have now unexpectedly mutated the iterated
916                     // collection). instead, we return a correct value immediately here, and
917                     // schedule the actual update for later. this has been completely rewritten and
918                     // is no longer a problem in the next version of android.
919                     enabled = mProvider.getState().allowed
920                             && mUserInfoHelper.isCurrentUserId(userId)
921                             && mSettingsHelper.isLocationEnabled(userId);
922 
923                     Log.w(TAG, mName + " provider saw user " + userId + " unexpectedly");
924                     mHandler.post(() -> {
925                         synchronized (mLock) {
926                             onEnabledChangedLocked(userId);
927                         }
928                     });
929                 }
930 
931                 return enabled;
932             }
933         }
934 
935         @GuardedBy("mLock")
onEnabledChangedLocked(int userId)936         public void onEnabledChangedLocked(int userId) {
937             if (userId == UserHandle.USER_NULL) {
938                 // used during initialization - ignore since many lower level operations (checking
939                 // settings for instance) do not support the null user
940                 return;
941             } else if (userId == UserHandle.USER_ALL) {
942                 // we know enabled changes can only happen for current users since providers are
943                 // always disabled for all non-current users
944                 for (int currentUserId : mUserInfoHelper.getCurrentUserIds()) {
945                     onEnabledChangedLocked(currentUserId);
946                 }
947                 return;
948             }
949 
950             // if any property that contributes to "enabled" here changes state, it MUST result
951             // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to
952             // guarantee that it will always eventually reach the correct state.
953             boolean enabled = mProvider.getState().allowed
954                     && mUserInfoHelper.isCurrentUserId(userId)
955                     && mSettingsHelper.isLocationEnabled(userId);
956 
957             Boolean wasEnabled = mEnabled.get(userId);
958             if (wasEnabled != null && wasEnabled == enabled) {
959                 return;
960             }
961 
962             mEnabled.put(userId, enabled);
963 
964             if (D) {
965                 Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled);
966             }
967 
968             // clear last locations if we become disabled and if not servicing a bypass request
969             if (!enabled && !mProvider.getCurrentRequest().locationSettingsIgnored) {
970                 mLastLocation.put(userId, null);
971                 mLastCoarseLocation.put(userId, null);
972             }
973 
974             // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility
975             mSettingsHelper.setLocationProviderAllowed(mName, enabled, userId);
976 
977             // do not send change notifications if we just saw this user for the first time
978             if (wasEnabled != null) {
979                 // fused and passive provider never get public updates for legacy reasons
980                 if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) {
981                     Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION)
982                             .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName)
983                             .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled)
984                             .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)
985                             .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
986                     mContext.sendBroadcastAsUser(intent, UserHandle.of(userId));
987                 }
988             }
989 
990             updateProviderEnabledLocked(this, enabled);
991         }
992 
dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args)993         public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) {
994             synchronized (mLock) {
995                 pw.print(mName + " provider");
996                 if (mProvider.isMock()) {
997                     pw.print(" [mock]");
998                 }
999                 pw.println(":");
1000 
1001                 pw.increaseIndent();
1002 
1003                 // for now we only dump for the parent user
1004                 int[] userIds = mUserInfoHelper.getCurrentUserIds();
1005                 if (userIds.length == 1) {
1006                     int userId = userIds[0];
1007                     pw.println("last location=" + mLastLocation.get(userId));
1008                     pw.println("last coarse location=" + mLastCoarseLocation.get(userId));
1009                     pw.println("enabled=" + isEnabled(userId));
1010                 } else {
1011                     for (int userId : userIds) {
1012                         pw.println("user " + userId + ":");
1013                         pw.increaseIndent();
1014                         pw.println("last location=" + mLastLocation.get(userId));
1015                         pw.println("last coarse location=" + mLastCoarseLocation.get(userId));
1016                         pw.println("enabled=" + isEnabled(userId));
1017                         pw.decreaseIndent();
1018                     }
1019                 }
1020             }
1021 
1022             mProvider.dump(fd, pw, args);
1023 
1024             pw.decreaseIndent();
1025         }
1026     }
1027 
1028     class PassiveLocationProviderManager extends LocationProviderManager {
1029 
PassiveLocationProviderManager()1030         private PassiveLocationProviderManager() {
1031             super(PASSIVE_PROVIDER);
1032         }
1033 
1034         @Override
setRealProvider(AbstractLocationProvider provider)1035         public void setRealProvider(AbstractLocationProvider provider) {
1036             Preconditions.checkArgument(provider instanceof PassiveProvider);
1037             super.setRealProvider(provider);
1038         }
1039 
1040         @Override
setMockProvider(@ullable MockProvider provider)1041         public void setMockProvider(@Nullable MockProvider provider) {
1042             if (provider != null) {
1043                 throw new IllegalArgumentException("Cannot mock the passive provider");
1044             }
1045         }
1046 
updateLocation(Location location)1047         public void updateLocation(Location location) {
1048             synchronized (mLock) {
1049                 PassiveProvider passiveProvider = (PassiveProvider) mProvider.getProvider();
1050                 Preconditions.checkState(passiveProvider != null);
1051 
1052                 long identity = Binder.clearCallingIdentity();
1053                 try {
1054                     passiveProvider.updateLocation(location);
1055                 } finally {
1056                     Binder.restoreCallingIdentity(identity);
1057                 }
1058             }
1059         }
1060     }
1061 
1062     /**
1063      * A wrapper class holding either an ILocationListener or a PendingIntent to receive
1064      * location updates.
1065      */
1066     private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements
1067             PendingIntent.OnFinished {
1068         private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000;
1069 
1070         private final ILocationListener mListener;
1071         final PendingIntent mPendingIntent;
1072         final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
1073         private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
1074         private final Object mKey;
1075 
1076         final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>();
1077 
1078         // True if app ops has started monitoring this receiver for locations.
1079         private boolean mOpMonitoring;
1080         // True if app ops has started monitoring this receiver for high power (gps) locations.
1081         private boolean mOpHighPowerMonitoring;
1082         private int mPendingBroadcasts;
1083         PowerManager.WakeLock mWakeLock;
1084 
Receiver(ILocationListener listener, PendingIntent intent, CallerIdentity identity, WorkSource workSource, boolean hideFromAppOps)1085         private Receiver(ILocationListener listener, PendingIntent intent, CallerIdentity identity,
1086                 WorkSource workSource, boolean hideFromAppOps) {
1087             super(identity);
1088             mListener = listener;
1089             mPendingIntent = intent;
1090             if (listener != null) {
1091                 mKey = listener.asBinder();
1092             } else {
1093                 mKey = intent;
1094             }
1095             if (workSource != null && workSource.isEmpty()) {
1096                 workSource = null;
1097             }
1098             mWorkSource = workSource;
1099             mHideFromAppOps = hideFromAppOps;
1100 
1101             updateMonitoring(true);
1102 
1103             // construct/configure wakelock
1104             mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
1105             if (workSource == null) {
1106                 workSource = new WorkSource(mCallerIdentity.uid, mCallerIdentity.packageName);
1107             }
1108             mWakeLock.setWorkSource(workSource);
1109 
1110             // For a non-reference counted wakelock, each acquire will reset the timeout, and we
1111             // only need to release it once.
1112             mWakeLock.setReferenceCounted(false);
1113         }
1114 
1115         @Override
equals(Object otherObj)1116         public boolean equals(Object otherObj) {
1117             return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
1118         }
1119 
1120         @Override
hashCode()1121         public int hashCode() {
1122             return mKey.hashCode();
1123         }
1124 
1125         @Override
toString()1126         public String toString() {
1127             StringBuilder s = new StringBuilder();
1128             s.append("Reciever[");
1129             s.append(Integer.toHexString(System.identityHashCode(this)));
1130             if (mListener != null) {
1131                 s.append(" listener");
1132             } else {
1133                 s.append(" intent");
1134             }
1135             for (String p : mUpdateRecords.keySet()) {
1136                 s.append(" ").append(mUpdateRecords.get(p).toString());
1137             }
1138             s.append(" monitoring location: ").append(mOpMonitoring);
1139             s.append("]");
1140             return s.toString();
1141         }
1142 
1143         /**
1144          * Update AppOp monitoring for this receiver.
1145          *
1146          * @param allow If true receiver is currently active, if false it's been removed.
1147          */
updateMonitoring(boolean allow)1148         public void updateMonitoring(boolean allow) {
1149             if (mHideFromAppOps) {
1150                 return;
1151             }
1152 
1153             boolean requestingLocation = false;
1154             boolean requestingHighPowerLocation = false;
1155             if (allow) {
1156                 // See if receiver has any enabled update records.  Also note if any update records
1157                 // are high power (has a high power provider with an interval under a threshold).
1158                 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
1159                     LocationProviderManager manager = getLocationProviderManager(
1160                             updateRecord.mProvider);
1161                     if (manager == null) {
1162                         continue;
1163                     }
1164                     if (!manager.isEnabled(UserHandle.getUserId(mCallerIdentity.uid))
1165                             && !isSettingsExempt(updateRecord)) {
1166                         continue;
1167                     }
1168 
1169                     requestingLocation = true;
1170                     ProviderProperties properties = manager.getProperties();
1171                     if (properties != null
1172                             && properties.mPowerRequirement == Criteria.POWER_HIGH
1173                             && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
1174                         requestingHighPowerLocation = true;
1175                         break;
1176                     }
1177                 }
1178             }
1179 
1180             // First update monitoring of any location request (including high power).
1181             mOpMonitoring = updateMonitoring(
1182                     requestingLocation,
1183                     mOpMonitoring,
1184                     false);
1185 
1186             // Now update monitoring of high power requests only.
1187             boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
1188             mOpHighPowerMonitoring = updateMonitoring(
1189                     requestingHighPowerLocation,
1190                     mOpHighPowerMonitoring,
1191                     true);
1192             if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
1193                 long identity = Binder.clearCallingIdentity();
1194                 try {
1195                     // Send an intent to notify that a high power request has been added/removed.
1196                     Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
1197                     mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
1198                 } finally {
1199                     Binder.restoreCallingIdentity(identity);
1200                 }
1201             }
1202         }
1203 
updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring, boolean highPower)1204         private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
1205                 boolean highPower) {
1206             if (!currentlyMonitoring) {
1207                 if (allowMonitoring) {
1208                     if (!highPower) {
1209                         return mAppOpsHelper.startLocationMonitoring(mCallerIdentity);
1210                     } else {
1211                         return mAppOpsHelper.startHighPowerLocationMonitoring(mCallerIdentity);
1212                     }
1213                 }
1214             } else {
1215                 if (!allowMonitoring || !mAppOpsHelper.checkLocationAccess(mCallerIdentity)) {
1216                     if (!highPower) {
1217                         mAppOpsHelper.stopLocationMonitoring(mCallerIdentity);
1218                     } else {
1219                         mAppOpsHelper.stopHighPowerLocationMonitoring(mCallerIdentity);
1220                     }
1221                     return false;
1222                 }
1223             }
1224 
1225             return currentlyMonitoring;
1226         }
1227 
isListener()1228         public boolean isListener() {
1229             return mListener != null;
1230         }
1231 
isPendingIntent()1232         public boolean isPendingIntent() {
1233             return mPendingIntent != null;
1234         }
1235 
getListener()1236         public ILocationListener getListener() {
1237             if (mListener != null) {
1238                 return mListener;
1239             }
1240             throw new IllegalStateException("Request for non-existent listener");
1241         }
1242 
callLocationChangedLocked(Location location)1243         public boolean callLocationChangedLocked(Location location) {
1244             if (mListener != null) {
1245                 try {
1246                     mListener.onLocationChanged(new Location(location));
1247                     // call this after broadcasting so we do not increment
1248                     // if we throw an exception.
1249                     incrementPendingBroadcastsLocked();
1250                 } catch (RemoteException e) {
1251                     return false;
1252                 }
1253             } else {
1254                 Intent locationChanged = new Intent();
1255                 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED,
1256                         new Location(location));
1257                 try {
1258                     mPendingIntent.send(mContext, 0, locationChanged, this, mHandler,
1259                             CallerIdentity.asPermission(mCallerIdentity.permissionLevel),
1260                             PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1261                     // call this after broadcasting so we do not increment
1262                     // if we throw an exception.
1263                     incrementPendingBroadcastsLocked();
1264                 } catch (PendingIntent.CanceledException e) {
1265                     return false;
1266                 }
1267             }
1268             return true;
1269         }
1270 
callProviderEnabledLocked(String provider, boolean enabled)1271         private boolean callProviderEnabledLocked(String provider, boolean enabled) {
1272             // First update AppOp monitoring.
1273             // An app may get/lose location access as providers are enabled/disabled.
1274             updateMonitoring(true);
1275 
1276             if (mListener != null) {
1277                 try {
1278                     if (enabled) {
1279                         mListener.onProviderEnabled(provider);
1280                     } else {
1281                         mListener.onProviderDisabled(provider);
1282                     }
1283                     // call this after broadcasting so we do not increment
1284                     // if we throw an exception.
1285                     incrementPendingBroadcastsLocked();
1286                 } catch (RemoteException e) {
1287                     return false;
1288                 }
1289             } else {
1290                 Intent providerIntent = new Intent();
1291                 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1292                 try {
1293                     mPendingIntent.send(mContext, 0, providerIntent, this, mHandler,
1294                             CallerIdentity.asPermission(mCallerIdentity.permissionLevel),
1295                             PendingIntentUtils.createDontSendToRestrictedAppsBundle(null));
1296                     // call this after broadcasting so we do not increment
1297                     // if we throw an exception.
1298                     incrementPendingBroadcastsLocked();
1299                 } catch (PendingIntent.CanceledException e) {
1300                     return false;
1301                 }
1302             }
1303             return true;
1304         }
1305 
callRemovedLocked()1306         public void callRemovedLocked() {
1307             if (mListener != null) {
1308                 try {
1309                     mListener.onRemoved();
1310                 } catch (RemoteException e) {
1311                     // doesn't matter
1312                 }
1313             }
1314         }
1315 
1316         @Override
binderDied()1317         public void binderDied() {
1318             synchronized (mLock) {
1319                 removeUpdatesLocked(this);
1320                 clearPendingBroadcastsLocked();
1321             }
1322         }
1323 
1324         @Override
onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)1325         public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1326                 int resultCode, String resultData, Bundle resultExtras) {
1327             synchronized (mLock) {
1328                 decrementPendingBroadcastsLocked();
1329             }
1330         }
1331 
1332         // this must be called while synchronized by caller in a synchronized block
1333         // containing the sending of the broadcaset
incrementPendingBroadcastsLocked()1334         private void incrementPendingBroadcastsLocked() {
1335             mPendingBroadcasts++;
1336             // so wakelock calls will succeed
1337             long identity = Binder.clearCallingIdentity();
1338             try {
1339                 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS);
1340             } finally {
1341                 Binder.restoreCallingIdentity(identity);
1342             }
1343         }
1344 
decrementPendingBroadcastsLocked()1345         private void decrementPendingBroadcastsLocked() {
1346             if (--mPendingBroadcasts == 0) {
1347                 // so wakelock calls will succeed
1348                 long identity = Binder.clearCallingIdentity();
1349                 try {
1350                     if (mWakeLock.isHeld()) {
1351                         mWakeLock.release();
1352                     }
1353                 } finally {
1354                     Binder.restoreCallingIdentity(identity);
1355                 }
1356             }
1357         }
1358 
clearPendingBroadcastsLocked()1359         public void clearPendingBroadcastsLocked() {
1360             if (mPendingBroadcasts > 0) {
1361                 mPendingBroadcasts = 0;
1362                 // so wakelock calls will succeed
1363                 long identity = Binder.clearCallingIdentity();
1364                 try {
1365                     if (mWakeLock.isHeld()) {
1366                         mWakeLock.release();
1367                     }
1368                 } finally {
1369                     Binder.restoreCallingIdentity(identity);
1370                 }
1371             }
1372         }
1373     }
1374 
1375     @Override
locationCallbackFinished(ILocationListener listener)1376     public void locationCallbackFinished(ILocationListener listener) {
1377         //Do not use getReceiverLocked here as that will add the ILocationListener to
1378         //the receiver list if it is not found.  If it is not found then the
1379         //LocationListener was removed when it had a pending broadcast and should
1380         //not be added back.
1381         synchronized (mLock) {
1382             Receiver receiver = mReceivers.get(listener.asBinder());
1383             if (receiver != null) {
1384                 receiver.decrementPendingBroadcastsLocked();
1385             }
1386         }
1387     }
1388 
1389     @Override
getGnssYearOfHardware()1390     public int getGnssYearOfHardware() {
1391         return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware();
1392     }
1393 
1394     @Override
1395     @Nullable
getGnssHardwareModelName()1396     public String getGnssHardwareModelName() {
1397         return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName();
1398     }
1399 
1400     @Override
getGnssBatchSize(String packageName)1401     public int getGnssBatchSize(String packageName) {
1402         return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(packageName);
1403     }
1404 
1405     @Override
addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName, String featureId)1406     public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName,
1407             String featureId) {
1408         return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback(
1409                 callback, packageName, featureId);
1410     }
1411 
1412     @Override
removeGnssBatchingCallback()1413     public void removeGnssBatchingCallback() {
1414         if (mGnssManagerService != null) mGnssManagerService.removeGnssBatchingCallback();
1415     }
1416 
1417     @Override
startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, String featureId)1418     public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName,
1419             String featureId) {
1420         return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos,
1421                 wakeOnFifoFull, packageName, featureId);
1422     }
1423 
1424     @Override
flushGnssBatch(String packageName)1425     public void flushGnssBatch(String packageName) {
1426         if (mGnssManagerService != null) mGnssManagerService.flushGnssBatch(packageName);
1427     }
1428 
1429     @Override
stopGnssBatch()1430     public boolean stopGnssBatch() {
1431         return mGnssManagerService != null && mGnssManagerService.stopGnssBatch();
1432     }
1433 
1434     @Nullable
getLocationProviderManager(String providerName)1435     private LocationProviderManager getLocationProviderManager(String providerName) {
1436         for (LocationProviderManager manager : mProviderManagers) {
1437             if (providerName.equals(manager.getName())) {
1438                 return manager;
1439             }
1440         }
1441 
1442         return null;
1443     }
1444 
1445     @Override
getAllProviders()1446     public List<String> getAllProviders() {
1447         ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1448         for (LocationProviderManager manager : mProviderManagers) {
1449             if (FUSED_PROVIDER.equals(manager.getName())) {
1450                 continue;
1451             }
1452             providers.add(manager.getName());
1453         }
1454         return providers;
1455     }
1456 
1457     @Override
getProviders(Criteria criteria, boolean enabledOnly)1458     public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
1459         if (!CallerIdentity.checkCallingOrSelfLocationPermission(mContext)) {
1460             return Collections.emptyList();
1461         }
1462 
1463         synchronized (mLock) {
1464             ArrayList<String> providers = new ArrayList<>(mProviderManagers.size());
1465             for (LocationProviderManager manager : mProviderManagers) {
1466                 String name = manager.getName();
1467                 if (FUSED_PROVIDER.equals(name)) {
1468                     continue;
1469                 }
1470                 if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) {
1471                     continue;
1472                 }
1473                 if (criteria != null && !LocationProvider.propertiesMeetCriteria(name,
1474                         manager.getProperties(), criteria)) {
1475                     continue;
1476                 }
1477                 providers.add(name);
1478             }
1479             return providers;
1480         }
1481     }
1482 
1483     @Override
getBestProvider(Criteria criteria, boolean enabledOnly)1484     public String getBestProvider(Criteria criteria, boolean enabledOnly) {
1485         List<String> providers;
1486         synchronized (mLock) {
1487             providers = getProviders(criteria, enabledOnly);
1488             if (providers.isEmpty()) {
1489                 providers = getProviders(null, enabledOnly);
1490             }
1491         }
1492 
1493         if (!providers.isEmpty()) {
1494             if (providers.contains(GPS_PROVIDER)) {
1495                 return GPS_PROVIDER;
1496             } else if (providers.contains(NETWORK_PROVIDER)) {
1497                 return NETWORK_PROVIDER;
1498             } else {
1499                 return providers.get(0);
1500             }
1501         }
1502 
1503         return null;
1504     }
1505 
1506     @GuardedBy("mLock")
updateProviderEnabledLocked(LocationProviderManager manager, boolean enabled)1507     private void updateProviderEnabledLocked(LocationProviderManager manager, boolean enabled) {
1508         ArrayList<Receiver> deadReceivers = null;
1509         ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
1510         if (records != null) {
1511             for (UpdateRecord record : records) {
1512                 if (!mUserInfoHelper.isCurrentUserId(
1513                         UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) {
1514                     continue;
1515                 }
1516 
1517                 // requests that ignore location settings will never provide notifications
1518                 if (isSettingsExempt(record)) {
1519                     continue;
1520                 }
1521 
1522                 // Sends a notification message to the receiver
1523                 if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) {
1524                     if (deadReceivers == null) {
1525                         deadReceivers = new ArrayList<>();
1526                     }
1527                     deadReceivers.add(record.mReceiver);
1528                 }
1529             }
1530         }
1531 
1532         if (deadReceivers != null) {
1533             for (int i = deadReceivers.size() - 1; i >= 0; i--) {
1534                 removeUpdatesLocked(deadReceivers.get(i));
1535             }
1536         }
1537 
1538         applyRequirementsLocked(manager);
1539     }
1540 
1541     @GuardedBy("mLock")
applyRequirementsLocked(String providerName)1542     private void applyRequirementsLocked(String providerName) {
1543         LocationProviderManager manager = getLocationProviderManager(providerName);
1544         if (manager != null) {
1545             applyRequirementsLocked(manager);
1546         }
1547     }
1548 
1549     @GuardedBy("mLock")
applyRequirementsLocked(LocationProviderManager manager)1550     private void applyRequirementsLocked(LocationProviderManager manager) {
1551         ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
1552         ProviderRequest.Builder providerRequest = new ProviderRequest.Builder();
1553 
1554         // if provider is not active, it should not respond to requests
1555 
1556         if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) {
1557             long backgroundThrottleInterval = mSettingsHelper.getBackgroundThrottleIntervalMs();
1558 
1559             ArrayList<LocationRequest> requests = new ArrayList<>(records.size());
1560 
1561             final boolean isForegroundOnlyMode =
1562                     mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
1563             final boolean shouldThrottleRequests =
1564                     mBatterySaverMode
1565                             == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
1566                             && !mPowerManager.isInteractive();
1567             // initialize the low power mode to true and set to false if any of the records requires
1568             providerRequest.setLowPowerMode(true);
1569             for (UpdateRecord record : records) {
1570                 CallerIdentity identity = record.mReceiver.mCallerIdentity;
1571                 if (!mUserInfoHelper.isCurrentUserId(identity.userId)) {
1572                     continue;
1573                 }
1574 
1575                 if (!mAppOpsHelper.checkLocationAccess(identity)) {
1576                     continue;
1577                 }
1578                 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests
1579                         || (isForegroundOnlyMode && !record.mIsForegroundUid);
1580                 if (!manager.isEnabled(identity.userId) || isBatterySaverDisablingLocation) {
1581                     if (isSettingsExempt(record)) {
1582                         providerRequest.setLocationSettingsIgnored(true);
1583                         providerRequest.setLowPowerMode(false);
1584                     } else {
1585                         continue;
1586                     }
1587                 }
1588 
1589                 LocationRequest locationRequest = record.mRealRequest;
1590                 long interval = locationRequest.getInterval();
1591 
1592 
1593                 // if we're forcing location, don't apply any throttling
1594                 if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExempt(
1595                         record.mReceiver.mCallerIdentity)) {
1596                     if (!record.mIsForegroundUid) {
1597                         interval = Math.max(interval, backgroundThrottleInterval);
1598                     }
1599                     if (interval != locationRequest.getInterval()) {
1600                         locationRequest = new LocationRequest(locationRequest);
1601                         locationRequest.setInterval(interval);
1602                     }
1603                 }
1604 
1605                 record.mRequest = locationRequest;
1606                 record.mReceiver.updateMonitoring(true);
1607                 requests.add(locationRequest);
1608                 if (!locationRequest.isLowPowerMode()) {
1609                     providerRequest.setLowPowerMode(false);
1610                 }
1611                 if (interval < providerRequest.getInterval()) {
1612                     providerRequest.setInterval(interval);
1613                 }
1614             }
1615 
1616             providerRequest.setLocationRequests(requests);
1617 
1618             if (providerRequest.getInterval() < Long.MAX_VALUE) {
1619                 // calculate who to blame for power
1620                 // This is somewhat arbitrary. We pick a threshold interval
1621                 // that is slightly higher that the minimum interval, and
1622                 // spread the blame across all applications with a request
1623                 // under that threshold.
1624                 // TODO: overflow
1625                 long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2;
1626                 for (UpdateRecord record : records) {
1627                     if (mUserInfoHelper.isCurrentUserId(
1628                             UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) {
1629                         LocationRequest locationRequest = record.mRequest;
1630 
1631                         // Don't assign battery blame for update records whose
1632                         // client has no permission to receive location data.
1633                         if (!providerRequest.getLocationRequests().contains(locationRequest)) {
1634                             continue;
1635                         }
1636 
1637                         if (locationRequest.getInterval() <= thresholdInterval) {
1638                             if (record.mReceiver.mWorkSource != null
1639                                     && isValidWorkSource(record.mReceiver.mWorkSource)) {
1640                                 providerRequest.getWorkSource().add(record.mReceiver.mWorkSource);
1641                             } else {
1642                                 // Assign blame to caller if there's no WorkSource associated with
1643                                 // the request or if it's invalid.
1644                                 providerRequest.getWorkSource().add(
1645                                         record.mReceiver.mCallerIdentity.uid,
1646                                         record.mReceiver.mCallerIdentity.packageName);
1647                             }
1648                         }
1649                     }
1650                 }
1651             }
1652         }
1653 
1654         manager.setRequest(providerRequest.build());
1655     }
1656 
1657     /**
1658      * Whether a given {@code WorkSource} associated with a Location request is valid.
1659      */
isValidWorkSource(WorkSource workSource)1660     private static boolean isValidWorkSource(WorkSource workSource) {
1661         if (workSource.size() > 0) {
1662             // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied
1663             // by tags.
1664             return workSource.getPackageName(0) != null;
1665         } else {
1666             // For now, make sure callers have supplied an attribution tag for use with
1667             // AppOpsManager. This might be relaxed in the future.
1668             final List<WorkChain> workChains = workSource.getWorkChains();
1669             return workChains != null && !workChains.isEmpty()
1670                     && workChains.get(0).getAttributionTag() != null;
1671         }
1672     }
1673 
1674     @Override
getBackgroundThrottlingWhitelist()1675     public String[] getBackgroundThrottlingWhitelist() {
1676         return mSettingsHelper.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
1677     }
1678 
1679     @Override
getIgnoreSettingsWhitelist()1680     public String[] getIgnoreSettingsWhitelist() {
1681         return mSettingsHelper.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
1682     }
1683 
isThrottlingExempt(CallerIdentity callerIdentity)1684     private boolean isThrottlingExempt(CallerIdentity callerIdentity) {
1685         if (callerIdentity.uid == Process.SYSTEM_UID) {
1686             return true;
1687         }
1688 
1689         if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains(
1690                 callerIdentity.packageName)) {
1691             return true;
1692         }
1693 
1694         return mLocalService.isProviderPackage(callerIdentity.packageName);
1695 
1696     }
1697 
isSettingsExempt(UpdateRecord record)1698     private boolean isSettingsExempt(UpdateRecord record) {
1699         if (!record.mRealRequest.isLocationSettingsIgnored()) {
1700             return false;
1701         }
1702 
1703         if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains(
1704                 record.mReceiver.mCallerIdentity.packageName)) {
1705             return true;
1706         }
1707 
1708         return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.packageName);
1709 
1710     }
1711 
1712     private class UpdateRecord {
1713         final String mProvider;
1714         private final LocationRequest mRealRequest;  // original request from client
1715         LocationRequest mRequest;  // possibly throttled version of the request
1716         private final Receiver mReceiver;
1717         private boolean mIsForegroundUid;
1718         private Location mLastFixBroadcast;
1719         private Throwable mStackTrace;  // for debugging only
1720         private long mExpirationRealtimeMs;
1721 
1722         /**
1723          * Note: must be constructed with lock held.
1724          */
UpdateRecord(String provider, LocationRequest request, Receiver receiver)1725         private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
1726             if (Build.IS_DEBUGGABLE) {
1727                 Preconditions.checkState(Thread.holdsLock(mLock));
1728             }
1729             mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
1730             mProvider = provider;
1731             mRealRequest = request;
1732             mRequest = request;
1733             mReceiver = receiver;
1734             mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.uid);
1735 
1736             if (D && receiver.mCallerIdentity.pid == Process.myPid()) {
1737                 mStackTrace = new Throwable();
1738             }
1739 
1740             ArrayList<UpdateRecord> records = mRecordsByProvider.computeIfAbsent(provider,
1741                     k -> new ArrayList<>());
1742             if (!records.contains(this)) {
1743                 records.add(this);
1744             }
1745 
1746             // Update statistics for historical location requests by package/provider
1747             mRequestStatistics.startRequesting(
1748                     mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId,
1749                     provider, request.getInterval(), mIsForegroundUid);
1750         }
1751 
1752         /**
1753          * Method to be called when record changes foreground/background
1754          */
updateForeground(boolean isForeground)1755         private void updateForeground(boolean isForeground) {
1756             mIsForegroundUid = isForeground;
1757             mRequestStatistics.updateForeground(
1758                     mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId,
1759                     mProvider, isForeground);
1760         }
1761 
1762         /**
1763          * Method to be called when a record will no longer be used.
1764          */
disposeLocked(boolean removeReceiver)1765         private void disposeLocked(boolean removeReceiver) {
1766             if (Build.IS_DEBUGGABLE) {
1767                 Preconditions.checkState(Thread.holdsLock(mLock));
1768             }
1769 
1770             CallerIdentity identity = mReceiver.mCallerIdentity;
1771             mRequestStatistics.stopRequesting(identity.packageName, identity.featureId, mProvider);
1772 
1773             mLocationUsageLogger.logLocationApiUsage(
1774                     LocationStatsEnums.USAGE_ENDED,
1775                     LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1776                     identity.packageName,
1777                     mRealRequest,
1778                     mReceiver.isListener(),
1779                     mReceiver.isPendingIntent(),
1780                     /* geofence= */ null,
1781                     mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.uid));
1782 
1783             // remove from mRecordsByProvider
1784             ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1785             if (globalRecords != null) {
1786                 globalRecords.remove(this);
1787             }
1788 
1789             if (!removeReceiver) return;  // the caller will handle the rest
1790 
1791             // remove from Receiver#mUpdateRecords
1792             HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1793             receiverRecords.remove(this.mProvider);
1794 
1795             // and also remove the Receiver if it has no more update records
1796             if (receiverRecords.size() == 0) {
1797                 removeUpdatesLocked(mReceiver);
1798             }
1799         }
1800 
1801         @Override
toString()1802         public String toString() {
1803             StringBuilder b = new StringBuilder("UpdateRecord[");
1804             b.append(mProvider).append(" ");
1805             b.append(mReceiver.mCallerIdentity).append(" ");
1806             if (!mIsForegroundUid) {
1807                 b.append("(background) ");
1808             }
1809             b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource);
1810 
1811             if (mStackTrace != null) {
1812                 ByteArrayOutputStream tmp = new ByteArrayOutputStream();
1813                 mStackTrace.printStackTrace(new PrintStream(tmp));
1814                 b.append("\n\n").append(tmp.toString()).append("\n");
1815             }
1816 
1817             b.append("]");
1818             return b.toString();
1819         }
1820     }
1821 
1822     @GuardedBy("mLock")
getReceiverLocked(ILocationListener listener, CallerIdentity identity, WorkSource workSource, boolean hideFromAppOps)1823     private Receiver getReceiverLocked(ILocationListener listener, CallerIdentity identity,
1824             WorkSource workSource, boolean hideFromAppOps) {
1825         IBinder binder = listener.asBinder();
1826         Receiver receiver = mReceivers.get(binder);
1827         if (receiver == null && identity != null) {
1828             receiver = new Receiver(listener, null, identity, workSource,
1829                     hideFromAppOps);
1830             if (!receiver.linkToListenerDeathNotificationLocked(
1831                     receiver.getListener().asBinder())) {
1832                 return null;
1833             }
1834             mReceivers.put(binder, receiver);
1835         }
1836         return receiver;
1837     }
1838 
1839     @GuardedBy("mLock")
getReceiverLocked(PendingIntent intent, CallerIdentity identity, WorkSource workSource, boolean hideFromAppOps)1840     private Receiver getReceiverLocked(PendingIntent intent, CallerIdentity identity,
1841             WorkSource workSource, boolean hideFromAppOps) {
1842         Receiver receiver = mReceivers.get(intent);
1843         if (receiver == null && identity != null) {
1844             receiver = new Receiver(null, intent, identity, workSource,
1845                     hideFromAppOps);
1846             mReceivers.put(intent, receiver);
1847         }
1848         return receiver;
1849     }
1850 
1851     /**
1852      * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1853      * and consistency requirements.
1854      *
1855      * @param request the LocationRequest from which to create a sanitized version
1856      * @return a version of request that meets the given resolution and consistency requirements
1857      * @hide
1858      */
createSanitizedRequest(LocationRequest request, CallerIdentity identity, boolean callerHasLocationHardwarePermission)1859     private LocationRequest createSanitizedRequest(LocationRequest request, CallerIdentity identity,
1860             boolean callerHasLocationHardwarePermission) {
1861         LocationRequest sanitizedRequest = new LocationRequest(request);
1862         if (!callerHasLocationHardwarePermission) {
1863             // allow setting low power mode only for callers with location hardware permission
1864             sanitizedRequest.setLowPowerMode(false);
1865         }
1866         if (identity.permissionLevel < PERMISSION_FINE) {
1867             switch (sanitizedRequest.getQuality()) {
1868                 case LocationRequest.ACCURACY_FINE:
1869                     sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
1870                     break;
1871                 case LocationRequest.POWER_HIGH:
1872                     sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
1873                     break;
1874             }
1875             // throttle
1876             if (sanitizedRequest.getInterval() < FASTEST_COARSE_INTERVAL_MS) {
1877                 sanitizedRequest.setInterval(FASTEST_COARSE_INTERVAL_MS);
1878             }
1879             if (sanitizedRequest.getFastestInterval() < FASTEST_COARSE_INTERVAL_MS) {
1880                 sanitizedRequest.setFastestInterval(FASTEST_COARSE_INTERVAL_MS);
1881             }
1882         }
1883         // make getFastestInterval() the minimum of interval and fastest interval
1884         if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
1885             sanitizedRequest.setFastestInterval(request.getInterval());
1886         }
1887         return sanitizedRequest;
1888     }
1889 
1890     @Override
requestLocationUpdates(LocationRequest request, ILocationListener listener, PendingIntent intent, String packageName, String featureId, String listenerId)1891     public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
1892             PendingIntent intent, String packageName, String featureId, String listenerId) {
1893         if (request == null) {
1894             request = DEFAULT_LOCATION_REQUEST;
1895         }
1896         if (listenerId == null && intent != null) {
1897             listenerId = AppOpsManager.toReceiverId(intent);
1898         }
1899 
1900         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId,
1901                 listenerId);
1902         identity.enforceLocationPermission();
1903 
1904         WorkSource workSource = request.getWorkSource();
1905         if (workSource != null && !workSource.isEmpty()) {
1906             mContext.enforceCallingOrSelfPermission(
1907                     Manifest.permission.UPDATE_DEVICE_STATS, null);
1908         }
1909         boolean hideFromAppOps = request.getHideFromAppOps();
1910         if (hideFromAppOps) {
1911             mContext.enforceCallingOrSelfPermission(
1912                     Manifest.permission.UPDATE_APP_OPS_STATS, null);
1913         }
1914         if (request.isLocationSettingsIgnored()) {
1915             mContext.enforceCallingOrSelfPermission(
1916                     Manifest.permission.WRITE_SECURE_SETTINGS, null);
1917         }
1918         boolean callerHasLocationHardwarePermission =
1919                 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
1920                         == PERMISSION_GRANTED;
1921         LocationRequest sanitizedRequest = createSanitizedRequest(request,
1922                 identity,
1923                 callerHasLocationHardwarePermission);
1924 
1925         if (intent == null && listener == null) {
1926             throw new IllegalArgumentException("need either listener or intent");
1927         } else if (intent != null && listener != null) {
1928             throw new IllegalArgumentException(
1929                     "cannot register both listener and intent");
1930         }
1931 
1932         mLocationUsageLogger.logLocationApiUsage(
1933                 LocationStatsEnums.USAGE_STARTED,
1934                 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
1935                 packageName, request, listener != null, intent != null,
1936                 /* geofence= */ null,
1937                 mAppForegroundHelper.getImportance(identity.uid));
1938 
1939         synchronized (mLock) {
1940             Receiver receiver;
1941             if (intent != null) {
1942                 receiver = getReceiverLocked(intent, identity, workSource, hideFromAppOps);
1943             } else {
1944                 receiver = getReceiverLocked(listener, identity, workSource, hideFromAppOps);
1945             }
1946             if (receiver != null) {
1947                 requestLocationUpdatesLocked(sanitizedRequest, receiver);
1948             }
1949         }
1950     }
1951 
1952     @GuardedBy("mLock")
requestLocationUpdatesLocked(LocationRequest request, Receiver receiver)1953     private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver) {
1954         // Figure out the provider. Either its explicitly request (legacy use cases), or
1955         // use the fused provider
1956         if (request == null) request = DEFAULT_LOCATION_REQUEST;
1957         String name = request.getProvider();
1958         if (name == null) {
1959             throw new IllegalArgumentException("provider name must not be null");
1960         }
1961 
1962         LocationProviderManager manager = getLocationProviderManager(name);
1963         if (manager == null) {
1964             throw new IllegalArgumentException("provider doesn't exist: " + name);
1965         }
1966 
1967         UpdateRecord record = new UpdateRecord(name, request, receiver);
1968 
1969         UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
1970         if (oldRecord != null) {
1971             oldRecord.disposeLocked(false);
1972         }
1973 
1974         long identity = Binder.clearCallingIdentity();
1975         try {
1976             int userId = UserHandle.getUserId(receiver.mCallerIdentity.uid);
1977             if (!manager.isEnabled(userId) && !isSettingsExempt(record)) {
1978                 // Notify the listener that updates are currently disabled - but only if the request
1979                 // does not ignore location settings
1980                 receiver.callProviderEnabledLocked(name, false);
1981             }
1982 
1983             applyRequirementsLocked(name);
1984 
1985             // Update the monitoring here just in case multiple location requests were added to the
1986             // same receiver (this request may be high power and the initial might not have been).
1987             receiver.updateMonitoring(true);
1988         } finally {
1989             Binder.restoreCallingIdentity(identity);
1990         }
1991     }
1992 
1993     @Override
removeUpdates(ILocationListener listener, PendingIntent intent)1994     public void removeUpdates(ILocationListener listener, PendingIntent intent) {
1995         if (intent == null && listener == null) {
1996             throw new IllegalArgumentException("need either listener or intent");
1997         } else if (intent != null && listener != null) {
1998             throw new IllegalArgumentException("cannot register both listener and intent");
1999         }
2000 
2001         synchronized (mLock) {
2002             Receiver receiver;
2003             if (intent != null) {
2004                 receiver = getReceiverLocked(intent, null, null, false);
2005             } else {
2006                 receiver = getReceiverLocked(listener, null, null, false);
2007             }
2008 
2009             if (receiver != null) {
2010                 removeUpdatesLocked(receiver);
2011             }
2012         }
2013     }
2014 
2015     @GuardedBy("mLock")
removeUpdatesLocked(Receiver receiver)2016     private void removeUpdatesLocked(Receiver receiver) {
2017         if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
2018 
2019         if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2020             receiver.unlinkFromListenerDeathNotificationLocked(
2021                     receiver.getListener().asBinder());
2022             receiver.clearPendingBroadcastsLocked();
2023         }
2024 
2025         receiver.updateMonitoring(false);
2026 
2027         // Record which providers were associated with this listener
2028         HashSet<String> providers = new HashSet<>();
2029         HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2030         if (oldRecords != null) {
2031             // Call dispose() on the obsolete update records.
2032             for (UpdateRecord record : oldRecords.values()) {
2033                 // Update statistics for historical location requests by package/provider
2034                 record.disposeLocked(false);
2035             }
2036             // Accumulate providers
2037             providers.addAll(oldRecords.keySet());
2038         }
2039 
2040         // update provider
2041         for (String provider : providers) {
2042             applyRequirementsLocked(provider);
2043         }
2044     }
2045 
2046     @Override
getLastLocation(LocationRequest request, String packageName, String featureId)2047     public Location getLastLocation(LocationRequest request, String packageName, String featureId) {
2048         if (request == null) {
2049             request = DEFAULT_LOCATION_REQUEST;
2050         }
2051 
2052         // unsafe is ok because app ops will verify the package name
2053         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
2054         identity.enforceLocationPermission();
2055 
2056         if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId, identity.packageName)) {
2057             return null;
2058         }
2059         if (!mUserInfoHelper.isCurrentUserId(identity.userId)) {
2060             return null;
2061         }
2062 
2063         synchronized (mLock) {
2064             LocationProviderManager manager = getLocationProviderManager(request.getProvider());
2065             if (manager == null) {
2066                 return null;
2067             }
2068             if (!manager.isEnabled(identity.userId) && !request.isLocationSettingsIgnored()) {
2069                 return null;
2070             }
2071 
2072             // appops check should always be right before delivery
2073             if (!mAppOpsHelper.noteLocationAccess(identity)) {
2074                 return null;
2075             }
2076 
2077             Location location = manager.getLastLocation(identity.userId, identity.permissionLevel);
2078 
2079             // make a defensive copy - the client could be in the same process as us
2080             return location != null ? new Location(location) : null;
2081         }
2082     }
2083 
2084     @Nullable
2085     @Override
getCurrentLocation(LocationRequest locationRequest, ILocationListener listener, String packageName, String featureId, String listenerId)2086     public ICancellationSignal getCurrentLocation(LocationRequest locationRequest,
2087             ILocationListener listener, String packageName, String featureId, String listenerId) {
2088         ICancellationSignal remoteCancellationSignal = CancellationSignal.createTransport();
2089 
2090         // side effect of validating locationRequest and packageName
2091         Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
2092         if (lastLocation != null) {
2093             long locationAgeMs = NANOSECONDS.toMillis(
2094                     SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos());
2095 
2096             if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) {
2097                 try {
2098                     listener.onLocationChanged(lastLocation);
2099                     return remoteCancellationSignal;
2100                 } catch (RemoteException e) {
2101                     Log.w(TAG, e);
2102                     return null;
2103                 }
2104             }
2105 
2106             if (!mAppForegroundHelper.isAppForeground(Binder.getCallingUid())) {
2107                 if (locationAgeMs < mSettingsHelper.getBackgroundThrottleIntervalMs()) {
2108                     // not allowed to request new locations, so we can't return anything
2109                     return null;
2110                 }
2111             }
2112         }
2113 
2114         requestLocationUpdates(locationRequest, listener, null, packageName, featureId, listenerId);
2115         CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
2116                 remoteCancellationSignal);
2117         cancellationSignal.setOnCancelListener(() -> removeUpdates(listener, null));
2118         return remoteCancellationSignal;
2119     }
2120 
2121     @Override
getGnssTimeMillis()2122     public LocationTime getGnssTimeMillis() {
2123         synchronized (mLock) {
2124             LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER);
2125             if (gpsManager == null) {
2126                 return null;
2127             }
2128 
2129             Location location = gpsManager.getLastLocation(UserHandle.getCallingUserId(),
2130                     PERMISSION_FINE);
2131             if (location == null) {
2132                 return null;
2133             }
2134 
2135             long currentNanos = SystemClock.elapsedRealtimeNanos();
2136             long deltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeAgeNanos(currentNanos));
2137             return new LocationTime(location.getTime() + deltaMs, currentNanos);
2138         }
2139     }
2140 
2141     @Override
injectLocation(Location location)2142     public void injectLocation(Location location) {
2143         mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null);
2144         mContext.enforceCallingPermission(ACCESS_FINE_LOCATION, null);
2145 
2146         Preconditions.checkArgument(location.isComplete());
2147 
2148         int userId = UserHandle.getCallingUserId();
2149         synchronized (mLock) {
2150             LocationProviderManager manager = getLocationProviderManager(location.getProvider());
2151             if (manager != null && manager.isEnabled(userId)) {
2152                 manager.injectLastLocation(Objects.requireNonNull(location), userId);
2153             }
2154         }
2155     }
2156 
2157     @Override
requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, String packageName, String featureId)2158     public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2159             String packageName, String featureId) {
2160         if (request == null) {
2161             request = DEFAULT_LOCATION_REQUEST;
2162         }
2163 
2164         CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId,
2165                 AppOpsManager.toReceiverId(intent));
2166         identity.enforceLocationPermission();
2167 
2168         Objects.requireNonNull(intent);
2169 
2170         boolean callerHasLocationHardwarePermission =
2171                 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE)
2172                         == PERMISSION_GRANTED;
2173         LocationRequest sanitizedRequest = createSanitizedRequest(request, identity,
2174                 callerHasLocationHardwarePermission);
2175 
2176         if (D) {
2177             Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2178         }
2179 
2180         if (identity.userId != UserHandle.USER_SYSTEM) {
2181             // temporary measure until geofences work for secondary users
2182             Log.w(TAG, "proximity alerts are currently available only to the primary user");
2183             return;
2184         }
2185 
2186         mLocationUsageLogger.logLocationApiUsage(
2187                 LocationStatsEnums.USAGE_STARTED,
2188                 LocationStatsEnums.API_REQUEST_GEOFENCE,
2189                 packageName,
2190                 request,
2191                 /* hasListener= */ false,
2192                 true,
2193                 geofence,
2194                 mAppForegroundHelper.getImportance(identity.uid));
2195 
2196         mGeofenceManager.addFence(sanitizedRequest, geofence, intent, identity);
2197     }
2198 
2199     @Override
removeGeofence(Geofence geofence, PendingIntent intent, String packageName)2200     public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
2201         if (intent == null) {
2202             throw new IllegalArgumentException("invalid pending intent: " + null);
2203         }
2204 
2205         if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2206 
2207         mLocationUsageLogger.logLocationApiUsage(
2208                 LocationStatsEnums.USAGE_ENDED,
2209                 LocationStatsEnums.API_REQUEST_GEOFENCE,
2210                 packageName,
2211                 /* LocationRequest= */ null,
2212                 /* hasListener= */ false,
2213                 true,
2214                 geofence,
2215                 mAppForegroundHelper.getImportance(Binder.getCallingUid()));
2216 
2217         // geo-fence manager uses the public location API, need to clear identity
2218         long identity = Binder.clearCallingIdentity();
2219         try {
2220             mGeofenceManager.removeFence(geofence, intent);
2221         } finally {
2222             Binder.restoreCallingIdentity(identity);
2223         }
2224     }
2225 
2226     @Override
registerGnssStatusCallback(IGnssStatusListener listener, String packageName, String featureId)2227     public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName,
2228             String featureId) {
2229         return mGnssManagerService != null && mGnssManagerService.registerGnssStatusCallback(
2230                 listener, packageName, featureId);
2231     }
2232 
2233     @Override
unregisterGnssStatusCallback(IGnssStatusListener listener)2234     public void unregisterGnssStatusCallback(IGnssStatusListener listener) {
2235         if (mGnssManagerService != null) mGnssManagerService.unregisterGnssStatusCallback(listener);
2236     }
2237 
2238     @Override
addGnssMeasurementsListener(@ullable GnssRequest request, IGnssMeasurementsListener listener, String packageName, String featureId)2239     public boolean addGnssMeasurementsListener(@Nullable GnssRequest request,
2240             IGnssMeasurementsListener listener, String packageName, String featureId) {
2241         return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
2242                 request, listener, packageName, featureId);
2243     }
2244 
2245     @Override
removeGnssMeasurementsListener(IGnssMeasurementsListener listener)2246     public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2247         if (mGnssManagerService != null) {
2248             mGnssManagerService.removeGnssMeasurementsListener(
2249                     listener);
2250         }
2251     }
2252 
2253     @Override
injectGnssMeasurementCorrections( GnssMeasurementCorrections measurementCorrections, String packageName)2254     public void injectGnssMeasurementCorrections(
2255             GnssMeasurementCorrections measurementCorrections, String packageName) {
2256         if (mGnssManagerService != null) {
2257             mGnssManagerService.injectGnssMeasurementCorrections(measurementCorrections,
2258                     packageName);
2259         }
2260     }
2261 
2262     @Override
getGnssCapabilities()2263     public long getGnssCapabilities() {
2264         return mGnssManagerService == null ? GnssCapabilities.INVALID_CAPABILITIES
2265                 : mGnssManagerService.getGnssCapabilities();
2266     }
2267 
2268     @Override
addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, String featureId)2269     public boolean addGnssAntennaInfoListener(IGnssAntennaInfoListener listener,
2270             String packageName, String featureId) {
2271 
2272         return mGnssManagerService != null && mGnssManagerService.addGnssAntennaInfoListener(
2273                 listener, packageName, featureId);
2274     }
2275 
2276     @Override
removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener)2277     public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
2278         if (mGnssManagerService != null) {
2279             mGnssManagerService.removeGnssAntennaInfoListener(listener);
2280         }
2281     }
2282 
2283     @Override
addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, String packageName, String featureId)2284     public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
2285             String packageName, String featureId) {
2286         return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener(
2287                 listener, packageName, featureId);
2288     }
2289 
2290     @Override
removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)2291     public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2292         if (mGnssManagerService != null) {
2293             mGnssManagerService.removeGnssNavigationMessageListener(
2294                     listener);
2295         }
2296     }
2297 
2298     @Override
sendExtraCommand(String provider, String command, Bundle extras)2299     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
2300         CallerIdentity.enforceCallingOrSelfLocationPermission(mContext);
2301         mContext.enforceCallingOrSelfPermission(
2302                 Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null);
2303 
2304         LocationProviderManager manager = getLocationProviderManager(
2305                 Objects.requireNonNull(provider));
2306         if (manager != null) {
2307             manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(),
2308                     Objects.requireNonNull(command), extras);
2309         }
2310 
2311         mLocationUsageLogger.logLocationApiUsage(
2312                 LocationStatsEnums.USAGE_STARTED,
2313                 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2314                 provider);
2315 
2316         mLocationUsageLogger.logLocationApiUsage(
2317                 LocationStatsEnums.USAGE_ENDED,
2318                 LocationStatsEnums.API_SEND_EXTRA_COMMAND,
2319                 provider);
2320 
2321         return true;
2322     }
2323 
2324     @Override
getProviderProperties(String providerName)2325     public ProviderProperties getProviderProperties(String providerName) {
2326         LocationProviderManager manager = getLocationProviderManager(providerName);
2327         if (manager == null) {
2328             return null;
2329         }
2330         return manager.getProperties();
2331     }
2332 
2333     @Override
isProviderPackage(String packageName)2334     public boolean isProviderPackage(String packageName) {
2335         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
2336         return mLocalService.isProviderPackage(packageName);
2337     }
2338 
2339     @Override
getProviderPackages(String providerName)2340     public List<String> getProviderPackages(String providerName) {
2341         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null);
2342         LocationProviderManager manager = getLocationProviderManager(providerName);
2343         return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages());
2344     }
2345 
2346     @Override
setExtraLocationControllerPackage(String packageName)2347     public void setExtraLocationControllerPackage(String packageName) {
2348         mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2349                 Manifest.permission.LOCATION_HARDWARE + " permission required");
2350         synchronized (mLock) {
2351             mExtraLocationControllerPackage = packageName;
2352         }
2353     }
2354 
2355     @Override
getExtraLocationControllerPackage()2356     public String getExtraLocationControllerPackage() {
2357         synchronized (mLock) {
2358             return mExtraLocationControllerPackage;
2359         }
2360     }
2361 
2362     @Override
setExtraLocationControllerPackageEnabled(boolean enabled)2363     public void setExtraLocationControllerPackageEnabled(boolean enabled) {
2364         mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE,
2365                 Manifest.permission.LOCATION_HARDWARE + " permission required");
2366         synchronized (mLock) {
2367             mExtraLocationControllerPackageEnabled = enabled;
2368         }
2369     }
2370 
2371     @Override
isExtraLocationControllerPackageEnabled()2372     public boolean isExtraLocationControllerPackageEnabled() {
2373         synchronized (mLock) {
2374             return mExtraLocationControllerPackageEnabled
2375                     && (mExtraLocationControllerPackage != null);
2376         }
2377     }
2378 
2379     @Override
setLocationEnabledForUser(boolean enabled, int userId)2380     public void setLocationEnabledForUser(boolean enabled, int userId) {
2381         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2382                 userId, false, false, "setLocationEnabledForUser", null);
2383 
2384         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS, null);
2385 
2386         LocationManager.invalidateLocalLocationEnabledCaches();
2387         mSettingsHelper.setLocationEnabled(enabled, userId);
2388     }
2389 
2390     @Override
isLocationEnabledForUser(int userId)2391     public boolean isLocationEnabledForUser(int userId) {
2392         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2393                 userId, false, false, "isLocationEnabledForUser", null);
2394         return mSettingsHelper.isLocationEnabled(userId);
2395     }
2396 
2397     @Override
isProviderEnabledForUser(String provider, int userId)2398     public boolean isProviderEnabledForUser(String provider, int userId) {
2399         userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
2400                 userId, false, false, "isProviderEnabledForUser", null);
2401 
2402         // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2403         // so we discourage its use
2404         if (FUSED_PROVIDER.equals(provider)) return false;
2405 
2406         return mLocalService.isProviderEnabledForUser(provider, userId);
2407     }
2408 
2409     @GuardedBy("mLock")
shouldBroadcastSafeLocked( Location loc, Location lastLoc, UpdateRecord record, long now)2410     private static boolean shouldBroadcastSafeLocked(
2411             Location loc, Location lastLoc, UpdateRecord record, long now) {
2412         // Always broadcast the first update
2413         if (lastLoc == null) {
2414             return true;
2415         }
2416 
2417         // Check whether sufficient time has passed
2418         long minTime = record.mRealRequest.getFastestInterval();
2419         long deltaMs = NANOSECONDS.toMillis(
2420                 loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos());
2421         if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
2422             return false;
2423         }
2424 
2425         // Check whether sufficient distance has been traveled
2426         double minDistance = record.mRealRequest.getSmallestDisplacement();
2427         if (minDistance > 0.0) {
2428             if (loc.distanceTo(lastLoc) <= minDistance) {
2429                 return false;
2430             }
2431         }
2432 
2433         // Check whether sufficient number of udpates is left
2434         if (record.mRealRequest.getNumUpdates() <= 0) {
2435             return false;
2436         }
2437 
2438         // Check whether the expiry date has passed
2439         return record.mExpirationRealtimeMs >= now;
2440     }
2441 
2442     @GuardedBy("mLock")
handleLocationChangedLocked(LocationProviderManager manager, Location fineLocation, Location coarseLocation)2443     private void handleLocationChangedLocked(LocationProviderManager manager, Location fineLocation,
2444             Location coarseLocation) {
2445         if (!mProviderManagers.contains(manager)) {
2446             Log.w(TAG, "received location from unknown provider: " + manager.getName());
2447             return;
2448         }
2449 
2450         // notify passive provider
2451         if (manager != mPassiveManager) {
2452             mPassiveManager.updateLocation(fineLocation);
2453         }
2454 
2455         long now = SystemClock.elapsedRealtime();
2456 
2457         ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName());
2458         if (records == null || records.size() == 0) return;
2459 
2460         ArrayList<Receiver> deadReceivers = null;
2461         ArrayList<UpdateRecord> deadUpdateRecords = null;
2462 
2463         // Broadcast location to all listeners
2464         for (UpdateRecord r : records) {
2465             Receiver receiver = r.mReceiver;
2466             CallerIdentity identity = receiver.mCallerIdentity;
2467             boolean receiverDead = false;
2468 
2469 
2470             if (!manager.isEnabled(identity.userId) && !isSettingsExempt(r)) {
2471                 continue;
2472             }
2473 
2474             if (!mUserInfoHelper.isCurrentUserId(identity.userId)
2475                     && !isProviderPackage(identity.packageName)) {
2476                 continue;
2477             }
2478 
2479             if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId,
2480                     identity.packageName)) {
2481                 continue;
2482             }
2483 
2484             Location location;
2485             switch (identity.permissionLevel) {
2486                 case PERMISSION_COARSE:
2487                     location = coarseLocation;
2488                     break;
2489                 case PERMISSION_FINE:
2490                     location = fineLocation;
2491                     break;
2492                 default:
2493                     throw new AssertionError();
2494             }
2495 
2496             if (shouldBroadcastSafeLocked(location, r.mLastFixBroadcast, r, now)) {
2497                 r.mLastFixBroadcast = location;
2498 
2499                 // appops check should always be right before delivery
2500                 if (!mAppOpsHelper.noteLocationAccess(receiver.mCallerIdentity)) {
2501                     continue;
2502                 }
2503 
2504                 if (!receiver.callLocationChangedLocked(location)) {
2505                     receiverDead = true;
2506                 }
2507                 r.mRealRequest.decrementNumUpdates();
2508             }
2509 
2510             // track expired records
2511             if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
2512                 // notify the client it can remove this listener
2513                 r.mReceiver.callRemovedLocked();
2514                 if (deadUpdateRecords == null) {
2515                     deadUpdateRecords = new ArrayList<>();
2516                 }
2517                 deadUpdateRecords.add(r);
2518             }
2519             // track dead receivers
2520             if (receiverDead) {
2521                 if (deadReceivers == null) {
2522                     deadReceivers = new ArrayList<>();
2523                 }
2524                 if (!deadReceivers.contains(receiver)) {
2525                     deadReceivers.add(receiver);
2526                 }
2527             }
2528         }
2529 
2530         // remove dead records and receivers outside the loop
2531         if (deadReceivers != null) {
2532             for (Receiver receiver : deadReceivers) {
2533                 removeUpdatesLocked(receiver);
2534             }
2535         }
2536         if (deadUpdateRecords != null) {
2537             for (UpdateRecord r : deadUpdateRecords) {
2538                 r.disposeLocked(true);
2539             }
2540             applyRequirementsLocked(manager);
2541         }
2542     }
2543 
2544     // Geocoder
2545 
2546     @Override
geocoderIsPresent()2547     public boolean geocoderIsPresent() {
2548         return mGeocodeProvider != null;
2549     }
2550 
2551     @Override
getFromLocation(double latitude, double longitude, int maxResults, GeocoderParams params, List<Address> addrs)2552     public String getFromLocation(double latitude, double longitude, int maxResults,
2553             GeocoderParams params, List<Address> addrs) {
2554         if (mGeocodeProvider != null) {
2555             return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2556                     params, addrs);
2557         }
2558         return null;
2559     }
2560 
2561     @Override
getFromLocationName(String locationName, double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude, int maxResults, GeocoderParams params, List<Address> addrs)2562     public String getFromLocationName(String locationName,
2563             double lowerLeftLatitude, double lowerLeftLongitude,
2564             double upperRightLatitude, double upperRightLongitude, int maxResults,
2565             GeocoderParams params, List<Address> addrs) {
2566 
2567         if (mGeocodeProvider != null) {
2568             return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2569                     lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2570                     maxResults, params, addrs);
2571         }
2572         return null;
2573     }
2574 
2575     // Mock Providers
2576 
2577     @Override
addTestProvider(String provider, ProviderProperties properties, String packageName, String featureId)2578     public void addTestProvider(String provider, ProviderProperties properties,
2579             String packageName, String featureId) {
2580         // unsafe is ok because app ops will verify the package name
2581         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
2582         if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
2583             return;
2584         }
2585 
2586         synchronized (mLock) {
2587             LocationProviderManager manager = getLocationProviderManager(provider);
2588             if (manager == null) {
2589                 manager = new LocationProviderManager(provider);
2590                 mProviderManagers.add(manager);
2591             }
2592 
2593             manager.setMockProvider(new MockProvider(properties));
2594         }
2595     }
2596 
2597     @Override
removeTestProvider(String provider, String packageName, String featureId)2598     public void removeTestProvider(String provider, String packageName, String featureId) {
2599         // unsafe is ok because app ops will verify the package name
2600         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
2601         if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
2602             return;
2603         }
2604 
2605         synchronized (mLock) {
2606             LocationProviderManager manager = getLocationProviderManager(provider);
2607             if (manager == null) {
2608                 return;
2609             }
2610 
2611             manager.setMockProvider(null);
2612             if (!manager.hasProvider()) {
2613                 mProviderManagers.remove(manager);
2614             }
2615         }
2616     }
2617 
2618     @Override
setTestProviderLocation(String provider, Location location, String packageName, String featureId)2619     public void setTestProviderLocation(String provider, Location location, String packageName,
2620             String featureId) {
2621         // unsafe is ok because app ops will verify the package name
2622         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
2623         if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
2624             return;
2625         }
2626 
2627         Preconditions.checkArgument(location.isComplete(),
2628                 "incomplete location object, missing timestamp or accuracy?");
2629 
2630         LocationProviderManager manager = getLocationProviderManager(provider);
2631         if (manager == null) {
2632             throw new IllegalArgumentException("provider doesn't exist: " + provider);
2633         }
2634 
2635         manager.setMockProviderLocation(location);
2636     }
2637 
2638     @Override
setTestProviderEnabled(String provider, boolean enabled, String packageName, String featureId)2639     public void setTestProviderEnabled(String provider, boolean enabled, String packageName,
2640             String featureId) {
2641         // unsafe is ok because app ops will verify the package name
2642         CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId);
2643         if (!mAppOpsHelper.noteMockLocationAccess(identity)) {
2644             return;
2645         }
2646 
2647         LocationProviderManager manager = getLocationProviderManager(provider);
2648         if (manager == null) {
2649             throw new IllegalArgumentException("provider doesn't exist: " + provider);
2650         }
2651 
2652         manager.setMockProviderAllowed(enabled);
2653     }
2654 
2655     @Override
2656     @NonNull
getTestProviderCurrentRequests(String provider)2657     public List<LocationRequest> getTestProviderCurrentRequests(String provider) {
2658         LocationProviderManager manager = getLocationProviderManager(provider);
2659         if (manager == null) {
2660             throw new IllegalArgumentException("provider doesn't exist: " + provider);
2661         }
2662 
2663         return manager.getMockProviderRequests();
2664     }
2665 
2666     @Override
handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, ParcelFileDescriptor err, String[] args)2667     public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out,
2668             ParcelFileDescriptor err, String[] args) {
2669         return new LocationShellCommand(this).exec(
2670                 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(),
2671                 args);
2672     }
2673 
2674     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)2675     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2676         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) {
2677             return;
2678         }
2679 
2680         IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
2681 
2682         synchronized (mLock) {
2683             if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) {
2684                 mGnssManagerService.dump(fd, pw, args);
2685                 return;
2686             }
2687 
2688             ipw.println("Location Manager State:");
2689             ipw.increaseIndent();
2690             ipw.print("Current System Time: "
2691                     + TimeUtils.logTimeOfDay(System.currentTimeMillis()));
2692             ipw.println(", Current Elapsed Time: "
2693                     + TimeUtils.formatDuration(SystemClock.elapsedRealtime()));
2694 
2695             ipw.println("User Info:");
2696             ipw.increaseIndent();
2697             mUserInfoHelper.dump(fd, ipw, args);
2698             ipw.decreaseIndent();
2699 
2700             ipw.println("Location Settings:");
2701             ipw.increaseIndent();
2702             mSettingsHelper.dump(fd, ipw, args);
2703             ipw.decreaseIndent();
2704 
2705             ipw.println("Battery Saver Location Mode: "
2706                     + locationPowerSaveModeToString(mBatterySaverMode));
2707 
2708             ipw.println("Location Listeners:");
2709             ipw.increaseIndent();
2710             for (Receiver receiver : mReceivers.values()) {
2711                 ipw.println(receiver);
2712             }
2713             ipw.decreaseIndent();
2714 
2715             ipw.println("Active Records by Provider:");
2716             ipw.increaseIndent();
2717             for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
2718                 ipw.println(entry.getKey() + ":");
2719                 ipw.increaseIndent();
2720                 for (UpdateRecord record : entry.getValue()) {
2721                     ipw.println(record);
2722                 }
2723                 ipw.decreaseIndent();
2724             }
2725             ipw.decreaseIndent();
2726 
2727             ipw.println("Historical Records by Provider:");
2728             ipw.increaseIndent();
2729             TreeMap<PackageProviderKey, PackageStatistics> sorted = new TreeMap<>(
2730                     mRequestStatistics.statistics);
2731             for (Map.Entry<PackageProviderKey, PackageStatistics> entry
2732                     : sorted.entrySet()) {
2733                 ipw.println(entry.getKey() + ": " + entry.getValue());
2734             }
2735             ipw.decreaseIndent();
2736 
2737             mRequestStatistics.history.dump(ipw);
2738 
2739             if (mGeofenceManager != null) {
2740                 ipw.println("Geofences:");
2741                 ipw.increaseIndent();
2742                 mGeofenceManager.dump(ipw);
2743                 ipw.decreaseIndent();
2744             }
2745 
2746             if (mExtraLocationControllerPackage != null) {
2747                 ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
2748                         + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
2749             }
2750         }
2751 
2752         ipw.println("Location Providers:");
2753         ipw.increaseIndent();
2754         for (LocationProviderManager manager : mProviderManagers) {
2755             manager.dump(fd, ipw, args);
2756         }
2757         ipw.decreaseIndent();
2758 
2759         synchronized (mLock) {
2760             if (mGnssManagerService != null) {
2761                 ipw.println("GNSS:");
2762                 ipw.increaseIndent();
2763                 mGnssManagerService.dump(fd, ipw, args);
2764                 ipw.decreaseIndent();
2765             }
2766         }
2767     }
2768 
2769     private class LocalService extends LocationManagerInternal {
2770 
2771         @Override
isProviderEnabledForUser(@onNull String provider, int userId)2772         public boolean isProviderEnabledForUser(@NonNull String provider, int userId) {
2773             synchronized (mLock) {
2774                 LocationProviderManager manager = getLocationProviderManager(provider);
2775                 if (manager == null) {
2776                     return false;
2777                 }
2778 
2779                 return manager.isEnabled(userId);
2780             }
2781         }
2782 
2783         @Override
isProviderPackage(String packageName)2784         public boolean isProviderPackage(String packageName) {
2785             for (LocationProviderManager manager : mProviderManagers) {
2786                 if (manager.getPackages().contains(packageName)) {
2787                     return true;
2788                 }
2789             }
2790             return false;
2791         }
2792 
2793         @Override
sendNiResponse(int notifId, int userResponse)2794         public void sendNiResponse(int notifId, int userResponse) {
2795             if (mGnssManagerService != null) {
2796                 mGnssManagerService.sendNiResponse(notifId, userResponse);
2797             }
2798         }
2799     }
2800 }
2801