1 /*
2  * Copyright (C) 2007 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;
18 
19 import android.app.ActivityManager;
20 import android.annotation.NonNull;
21 import android.content.pm.PackageManagerInternal;
22 import android.util.ArrayMap;
23 import android.util.ArraySet;
24 import com.android.internal.content.PackageMonitor;
25 import com.android.internal.location.ProviderProperties;
26 import com.android.internal.location.ProviderRequest;
27 import com.android.internal.os.BackgroundThread;
28 import com.android.internal.util.ArrayUtils;
29 import com.android.internal.util.DumpUtils;
30 import com.android.server.location.ActivityRecognitionProxy;
31 import com.android.server.location.FlpHardwareProvider;
32 import com.android.server.location.FusedProxy;
33 import com.android.server.location.GeocoderProxy;
34 import com.android.server.location.GeofenceManager;
35 import com.android.server.location.GeofenceProxy;
36 import com.android.server.location.GnssLocationProvider;
37 import com.android.server.location.GnssMeasurementsProvider;
38 import com.android.server.location.GnssNavigationMessageProvider;
39 import com.android.server.location.LocationBlacklist;
40 import com.android.server.location.LocationFudger;
41 import com.android.server.location.LocationProviderInterface;
42 import com.android.server.location.LocationProviderProxy;
43 import com.android.server.location.LocationRequestStatistics;
44 import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
45 import com.android.server.location.LocationRequestStatistics.PackageStatistics;
46 import com.android.server.location.MockProvider;
47 import com.android.server.location.PassiveProvider;
48 
49 import android.app.AppOpsManager;
50 import android.app.PendingIntent;
51 import android.content.BroadcastReceiver;
52 import android.content.ContentResolver;
53 import android.content.Context;
54 import android.content.Intent;
55 import android.content.IntentFilter;
56 import android.content.pm.ApplicationInfo;
57 import android.content.pm.PackageInfo;
58 import android.content.pm.PackageManager;
59 import android.content.pm.PackageManager.NameNotFoundException;
60 import android.content.pm.ResolveInfo;
61 import android.content.pm.Signature;
62 import android.content.res.Resources;
63 import android.database.ContentObserver;
64 import android.hardware.location.ActivityRecognitionHardware;
65 import android.location.Address;
66 import android.location.Criteria;
67 import android.location.GeocoderParams;
68 import android.location.Geofence;
69 import android.location.IBatchedLocationCallback;
70 import android.location.IGnssMeasurementsListener;
71 import android.location.IGnssStatusListener;
72 import android.location.IGnssStatusProvider;
73 import android.location.IGpsGeofenceHardware;
74 import android.location.IGnssNavigationMessageListener;
75 import android.location.ILocationListener;
76 import android.location.ILocationManager;
77 import android.location.INetInitiatedListener;
78 import android.location.Location;
79 import android.location.LocationManager;
80 import android.location.LocationProvider;
81 import android.location.LocationRequest;
82 import android.os.Binder;
83 import android.os.Bundle;
84 import android.os.Handler;
85 import android.os.IBinder;
86 import android.os.Looper;
87 import android.os.Message;
88 import android.os.PowerManager;
89 import android.os.Process;
90 import android.os.RemoteException;
91 import android.os.SystemClock;
92 import android.os.UserHandle;
93 import android.os.UserManager;
94 import android.os.WorkSource;
95 import android.provider.Settings;
96 import android.text.TextUtils;
97 import android.util.EventLog;
98 import android.util.Log;
99 import android.util.Slog;
100 
101 import java.io.FileDescriptor;
102 import java.io.PrintWriter;
103 import java.util.ArrayList;
104 import java.util.Arrays;
105 import java.util.HashMap;
106 import java.util.HashSet;
107 import java.util.List;
108 import java.util.Map;
109 import java.util.Map.Entry;
110 import java.util.NoSuchElementException;
111 import java.util.Set;
112 
113 /**
114  * The service class that manages LocationProviders and issues location
115  * updates and alerts.
116  */
117 public class LocationManagerService extends ILocationManager.Stub {
118     private static final String TAG = "LocationManagerService";
119     public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
120 
121     private static final String WAKELOCK_KEY = TAG;
122 
123     // Location resolution level: no location data whatsoever
124     private static final int RESOLUTION_LEVEL_NONE = 0;
125     // Location resolution level: coarse location data only
126     private static final int RESOLUTION_LEVEL_COARSE = 1;
127     // Location resolution level: fine location data
128     private static final int RESOLUTION_LEVEL_FINE = 2;
129 
130     private static final String ACCESS_MOCK_LOCATION =
131             android.Manifest.permission.ACCESS_MOCK_LOCATION;
132     private static final String ACCESS_LOCATION_EXTRA_COMMANDS =
133             android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS;
134     private static final String INSTALL_LOCATION_PROVIDER =
135             android.Manifest.permission.INSTALL_LOCATION_PROVIDER;
136 
137     private static final String NETWORK_LOCATION_SERVICE_ACTION =
138             "com.android.location.service.v3.NetworkLocationProvider";
139     private static final String FUSED_LOCATION_SERVICE_ACTION =
140             "com.android.location.service.FusedLocationProvider";
141 
142     private static final int MSG_LOCATION_CHANGED = 1;
143 
144     private static final long NANOS_PER_MILLI = 1000000L;
145 
146     // The maximum interval a location request can have and still be considered "high power".
147     private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000;
148 
149     private static final int FOREGROUND_IMPORTANCE_CUTOFF
150         = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
151 
152     // default background throttling interval if not overriden in settings
153     private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
154 
155     // Location Providers may sometimes deliver location updates
156     // slightly faster that requested - provide grace period so
157     // we don't unnecessarily filter events that are otherwise on
158     // time
159     private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
160 
161     private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
162 
163     private final Context mContext;
164     private final AppOpsManager mAppOps;
165 
166     // used internally for synchronization
167     private final Object mLock = new Object();
168 
169     // --- fields below are final after systemRunning() ---
170     private LocationFudger mLocationFudger;
171     private GeofenceManager mGeofenceManager;
172     private PackageManager mPackageManager;
173     private PowerManager mPowerManager;
174     private ActivityManager mActivityManager;
175     private UserManager mUserManager;
176     private GeocoderProxy mGeocodeProvider;
177     private IGnssStatusProvider mGnssStatusProvider;
178     private INetInitiatedListener mNetInitiatedListener;
179     private LocationWorkerHandler mLocationHandler;
180     private PassiveProvider mPassiveProvider;  // track passive provider for special cases
181     private LocationBlacklist mBlacklist;
182     private GnssMeasurementsProvider mGnssMeasurementsProvider;
183     private GnssNavigationMessageProvider mGnssNavigationMessageProvider;
184     private IGpsGeofenceHardware mGpsGeofenceProxy;
185 
186     // --- fields below are protected by mLock ---
187     // Set of providers that are explicitly enabled
188     // Only used by passive, fused & test.  Network & GPS are controlled separately, and not listed.
189     private final Set<String> mEnabledProviders = new HashSet<>();
190 
191     // Set of providers that are explicitly disabled
192     private final Set<String> mDisabledProviders = new HashSet<>();
193 
194     // Mock (test) providers
195     private final HashMap<String, MockProvider> mMockProviders =
196             new HashMap<>();
197 
198     // all receivers
199     private final HashMap<Object, Receiver> mReceivers = new HashMap<>();
200 
201     // currently installed providers (with mocks replacing real providers)
202     private final ArrayList<LocationProviderInterface> mProviders =
203             new ArrayList<>();
204 
205     // real providers, saved here when mocked out
206     private final HashMap<String, LocationProviderInterface> mRealProviders =
207             new HashMap<>();
208 
209     // mapping from provider name to provider
210     private final HashMap<String, LocationProviderInterface> mProvidersByName =
211             new HashMap<>();
212 
213     // mapping from provider name to all its UpdateRecords
214     private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider =
215             new HashMap<>();
216 
217     private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics();
218 
219     // mapping from provider name to last known location
220     private final HashMap<String, Location> mLastLocation = new HashMap<>();
221 
222     // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
223     // locations stored here are not fudged for coarse permissions.
224     private final HashMap<String, Location> mLastLocationCoarseInterval =
225             new HashMap<>();
226 
227     // all providers that operate over proxy, for authorizing incoming location and whitelisting
228     // throttling
229     private final ArrayList<LocationProviderProxy> mProxyProviders =
230             new ArrayList<>();
231 
232     private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
233 
234     private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners =
235             new ArrayMap<>();
236 
237     private final ArrayMap<IGnssNavigationMessageListener, Identity>
238             mGnssNavigationMessageListeners = new ArrayMap<>();
239 
240     // current active user on the device - other users are denied location data
241     private int mCurrentUserId = UserHandle.USER_SYSTEM;
242     private int[] mCurrentUserProfiles = new int[] { UserHandle.USER_SYSTEM };
243 
244     private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
245 
246     private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
247     private IBatchedLocationCallback mGnssBatchingCallback;
248     private LinkedCallback mGnssBatchingDeathCallback;
249     private boolean mGnssBatchingInProgress = false;
250 
LocationManagerService(Context context)251     public LocationManagerService(Context context) {
252         super();
253         mContext = context;
254         mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
255 
256         // Let the package manager query which are the default location
257         // providers as they get certain permissions granted by default.
258         PackageManagerInternal packageManagerInternal = LocalServices.getService(
259                 PackageManagerInternal.class);
260         packageManagerInternal.setLocationPackagesProvider(
261                 new PackageManagerInternal.PackagesProvider() {
262                     @Override
263                     public String[] getPackages(int userId) {
264                         return mContext.getResources().getStringArray(
265                                 com.android.internal.R.array.config_locationProviderPackageNames);
266                     }
267                 });
268 
269         if (D) Log.d(TAG, "Constructed");
270 
271         // most startup is deferred until systemRunning()
272     }
273 
systemRunning()274     public void systemRunning() {
275         synchronized (mLock) {
276             if (D) Log.d(TAG, "systemRunning()");
277 
278             // fetch package manager
279             mPackageManager = mContext.getPackageManager();
280 
281             // fetch power manager
282             mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
283 
284             // fetch activity manager
285             mActivityManager
286                     = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
287 
288             // prepare worker thread
289             mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
290 
291             // prepare mLocationHandler's dependents
292             mLocationFudger = new LocationFudger(mContext, mLocationHandler);
293             mBlacklist = new LocationBlacklist(mContext, mLocationHandler);
294             mBlacklist.init();
295             mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
296 
297             // Monitor for app ops mode changes.
298             AppOpsManager.OnOpChangedListener callback
299                     = new AppOpsManager.OnOpChangedInternalListener() {
300                 public void onOpChanged(int op, String packageName) {
301                     synchronized (mLock) {
302                         for (Receiver receiver : mReceivers.values()) {
303                             receiver.updateMonitoring(true);
304                         }
305                         applyAllProviderRequirementsLocked();
306                     }
307                 }
308             };
309             mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback);
310 
311             PackageManager.OnPermissionsChangedListener permissionListener
312                     = new PackageManager.OnPermissionsChangedListener() {
313                 @Override
314                 public void onPermissionsChanged(final int uid) {
315                     synchronized (mLock) {
316                         applyAllProviderRequirementsLocked();
317                     }
318                 }
319             };
320             mPackageManager.addOnPermissionsChangeListener(permissionListener);
321 
322             // listen for background/foreground changes
323             ActivityManager.OnUidImportanceListener uidImportanceListener
324                     = new ActivityManager.OnUidImportanceListener() {
325                 @Override
326                 public void onUidImportance(int uid, int importance) {
327                     boolean foreground = isImportanceForeground(importance);
328                     HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size());
329                     synchronized (mLock) {
330                         for (Entry<String, ArrayList<UpdateRecord>> entry
331                                 : mRecordsByProvider.entrySet()) {
332                             String provider = entry.getKey();
333                             for (UpdateRecord record : entry.getValue()) {
334                                 if (record.mReceiver.mIdentity.mUid == uid
335                                         && record.mIsForegroundUid != foreground) {
336                                     if (D) Log.d(TAG, "request from uid " + uid + " is now "
337                                             + (foreground ? "foreground" : "background)"));
338                                     record.mIsForegroundUid = foreground;
339 
340                                     if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
341                                         affectedProviders.add(provider);
342                                     }
343                                 }
344                             }
345                         }
346                         for (String provider : affectedProviders) {
347                             applyRequirementsLocked(provider);
348                         }
349 
350                         for (Entry<IGnssMeasurementsListener, Identity> entry
351                                 : mGnssMeasurementsListeners.entrySet()) {
352                             if (entry.getValue().mUid == uid) {
353                                 if (D) Log.d(TAG, "gnss measurements listener from uid " + uid
354                                     + " is now " + (foreground ? "foreground" : "background)"));
355                                 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
356                                     mGnssMeasurementsProvider.addListener(entry.getKey());
357                                 } else {
358                                     mGnssMeasurementsProvider.removeListener(entry.getKey());
359                                 }
360                             }
361                         }
362 
363                         for (Entry<IGnssNavigationMessageListener, Identity> entry
364                             : mGnssNavigationMessageListeners.entrySet()) {
365                             if (entry.getValue().mUid == uid) {
366                                 if (D) Log.d(TAG, "gnss navigation message listener from uid "
367                                     + uid + " is now "
368                                     + (foreground ? "foreground" : "background)"));
369                                 if (foreground || isThrottlingExemptLocked(entry.getValue())) {
370                                     mGnssNavigationMessageProvider.addListener(entry.getKey());
371                                 } else {
372                                     mGnssNavigationMessageProvider.removeListener(entry.getKey());
373                                 }
374                             }
375                         }
376                     }
377 
378                 }
379             };
380             mActivityManager.addOnUidImportanceListener(uidImportanceListener,
381                     FOREGROUND_IMPORTANCE_CUTOFF);
382 
383             mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
384             updateUserProfiles(mCurrentUserId);
385 
386             updateBackgroundThrottlingWhitelistLocked();
387 
388             // prepare providers
389             loadProvidersLocked();
390             updateProvidersLocked();
391         }
392 
393         // listen for settings changes
394         mContext.getContentResolver().registerContentObserver(
395                 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
396                 new ContentObserver(mLocationHandler) {
397                     @Override
398                     public void onChange(boolean selfChange) {
399                         synchronized (mLock) {
400                             updateProvidersLocked();
401                         }
402                     }
403                 }, UserHandle.USER_ALL);
404         mContext.getContentResolver().registerContentObserver(
405                 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
406                 true,
407                 new ContentObserver(mLocationHandler) {
408                     @Override
409                     public void onChange(boolean selfChange) {
410                         synchronized (mLock) {
411                             updateProvidersLocked();
412                         }
413                     }
414                 }, UserHandle.USER_ALL);
415         mContext.getContentResolver().registerContentObserver(
416             Settings.Global.getUriFor(
417                 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
418             true,
419             new ContentObserver(mLocationHandler) {
420                 @Override
421                 public void onChange(boolean selfChange) {
422                     synchronized (mLock) {
423                         updateBackgroundThrottlingWhitelistLocked();
424                         updateProvidersLocked();
425                     }
426                 }
427             }, UserHandle.USER_ALL);
428         mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true);
429 
430         // listen for user change
431         IntentFilter intentFilter = new IntentFilter();
432         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
433         intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
434         intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
435         intentFilter.addAction(Intent.ACTION_SHUTDOWN);
436 
437         mContext.registerReceiverAsUser(new BroadcastReceiver() {
438             @Override
439             public void onReceive(Context context, Intent intent) {
440                 String action = intent.getAction();
441                 if (Intent.ACTION_USER_SWITCHED.equals(action)) {
442                     switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
443                 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action)
444                         || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) {
445                     updateUserProfiles(mCurrentUserId);
446                 } else if (Intent.ACTION_SHUTDOWN.equals(action)) {
447                     // shutdown only if UserId indicates whole system, not just one user
448                     if(D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId());
449                     if (getSendingUserId() == UserHandle.USER_ALL) {
450                         shutdownComponents();
451                     }
452                 }
453             }
454         }, UserHandle.ALL, intentFilter, null, mLocationHandler);
455     }
456 
isImportanceForeground(int importance)457     private static boolean isImportanceForeground(int importance) {
458         return importance <= FOREGROUND_IMPORTANCE_CUTOFF;
459     }
460 
461     /**
462      * Provides a way for components held by the {@link LocationManagerService} to clean-up
463      * gracefully on system's shutdown.
464      *
465      * NOTES:
466      * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat
467      * support for components that do not wish to handle such event.
468      */
shutdownComponents()469     private void shutdownComponents() {
470         if(D) Log.d(TAG, "Shutting down components...");
471 
472         LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER);
473         if (gpsProvider != null && gpsProvider.isEnabled()) {
474             gpsProvider.disable();
475         }
476 
477         // it is needed to check if FLP HW provider is supported before accessing the instance, this
478         // avoids an exception to be thrown by the singleton factory method
479         if (FlpHardwareProvider.isSupported()) {
480             FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
481             flpHardwareProvider.cleanup();
482         }
483     }
484 
485     /**
486      * Makes a list of userids that are related to the current user. This is
487      * relevant when using managed profiles. Otherwise the list only contains
488      * the current user.
489      *
490      * @param currentUserId the current user, who might have an alter-ego.
491      */
updateUserProfiles(int currentUserId)492     void updateUserProfiles(int currentUserId) {
493         int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId);
494         synchronized (mLock) {
495             mCurrentUserProfiles = profileIds;
496         }
497     }
498 
499     /**
500      * Checks if the specified userId matches any of the current foreground
501      * users stored in mCurrentUserProfiles.
502      */
isCurrentProfile(int userId)503     private boolean isCurrentProfile(int userId) {
504         synchronized (mLock) {
505             return ArrayUtils.contains(mCurrentUserProfiles, userId);
506         }
507     }
508 
ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs)509     private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) {
510         PackageManager pm = mContext.getPackageManager();
511         String systemPackageName = mContext.getPackageName();
512         ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs);
513 
514         List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser(
515                 new Intent(FUSED_LOCATION_SERVICE_ACTION),
516                 PackageManager.GET_META_DATA, mCurrentUserId);
517         for (ResolveInfo rInfo : rInfos) {
518             String packageName = rInfo.serviceInfo.packageName;
519 
520             // Check that the signature is in the list of supported sigs. If it's not in
521             // this list the standard provider binding logic won't bind to it.
522             try {
523                 PackageInfo pInfo;
524                 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
525                 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) {
526                     Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION +
527                             ", but has wrong signature, ignoring");
528                     continue;
529                 }
530             } catch (NameNotFoundException e) {
531                 Log.e(TAG, "missing package: " + packageName);
532                 continue;
533             }
534 
535             // Get the version info
536             if (rInfo.serviceInfo.metaData == null) {
537                 Log.w(TAG, "Found fused provider without metadata: " + packageName);
538                 continue;
539             }
540 
541             int version = rInfo.serviceInfo.metaData.getInt(
542                     ServiceWatcher.EXTRA_SERVICE_VERSION, -1);
543             if (version == 0) {
544                 // This should be the fallback fused location provider.
545 
546                 // Make sure it's in the system partition.
547                 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
548                     if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName);
549                     continue;
550                 }
551 
552                 // Check that the fallback is signed the same as the OS
553                 // as a proxy for coreApp="true"
554                 if (pm.checkSignatures(systemPackageName, packageName)
555                         != PackageManager.SIGNATURE_MATCH) {
556                     if (D) Log.d(TAG, "Fallback candidate not signed the same as system: "
557                             + packageName);
558                     continue;
559                 }
560 
561                 // Found a valid fallback.
562                 if (D) Log.d(TAG, "Found fallback provider: " + packageName);
563                 return;
564             } else {
565                 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName);
566             }
567         }
568 
569         throw new IllegalStateException("Unable to find a fused location provider that is in the "
570                 + "system partition with version 0 and signed with the platform certificate. "
571                 + "Such a package is needed to provide a default fused location provider in the "
572                 + "event that no other fused location provider has been installed or is currently "
573                 + "available. For example, coreOnly boot mode when decrypting the data "
574                 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest");
575     }
576 
loadProvidersLocked()577     private void loadProvidersLocked() {
578         // create a passive location provider, which is always enabled
579         PassiveProvider passiveProvider = new PassiveProvider(this);
580         addProviderLocked(passiveProvider);
581         mEnabledProviders.add(passiveProvider.getName());
582         mPassiveProvider = passiveProvider;
583 
584         if (GnssLocationProvider.isSupported()) {
585             // Create a gps location provider
586             GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this,
587                     mLocationHandler.getLooper());
588             mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider();
589             mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider();
590             mGnssStatusProvider = gnssProvider.getGnssStatusProvider();
591             mNetInitiatedListener = gnssProvider.getNetInitiatedListener();
592             addProviderLocked(gnssProvider);
593             mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider);
594             mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider();
595             mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider();
596             mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy();
597         }
598 
599         /*
600         Load package name(s) containing location provider support.
601         These packages can contain services implementing location providers:
602         Geocoder Provider, Network Location Provider, and
603         Fused Location Provider. They will each be searched for
604         service components implementing these providers.
605         The location framework also has support for installation
606         of new location providers at run-time. The new package does not
607         have to be explicitly listed here, however it must have a signature
608         that matches the signature of at least one package on this list.
609         */
610         Resources resources = mContext.getResources();
611         ArrayList<String> providerPackageNames = new ArrayList<>();
612         String[] pkgs = resources.getStringArray(
613                 com.android.internal.R.array.config_locationProviderPackageNames);
614         if (D) Log.d(TAG, "certificates for location providers pulled from: " +
615                 Arrays.toString(pkgs));
616         if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs));
617 
618         ensureFallbackFusedProviderPresentLocked(providerPackageNames);
619 
620         // bind to network provider
621         LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind(
622                 mContext,
623                 LocationManager.NETWORK_PROVIDER,
624                 NETWORK_LOCATION_SERVICE_ACTION,
625                 com.android.internal.R.bool.config_enableNetworkLocationOverlay,
626                 com.android.internal.R.string.config_networkLocationProviderPackageName,
627                 com.android.internal.R.array.config_locationProviderPackageNames,
628                 mLocationHandler);
629         if (networkProvider != null) {
630             mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider);
631             mProxyProviders.add(networkProvider);
632             addProviderLocked(networkProvider);
633         } else {
634             Slog.w(TAG,  "no network location provider found");
635         }
636 
637         // bind to fused provider
638         LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind(
639                 mContext,
640                 LocationManager.FUSED_PROVIDER,
641                 FUSED_LOCATION_SERVICE_ACTION,
642                 com.android.internal.R.bool.config_enableFusedLocationOverlay,
643                 com.android.internal.R.string.config_fusedLocationProviderPackageName,
644                 com.android.internal.R.array.config_locationProviderPackageNames,
645                 mLocationHandler);
646         if (fusedLocationProvider != null) {
647             addProviderLocked(fusedLocationProvider);
648             mProxyProviders.add(fusedLocationProvider);
649             mEnabledProviders.add(fusedLocationProvider.getName());
650             mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider);
651         } else {
652             Slog.e(TAG, "no fused location provider found",
653                     new IllegalStateException("Location service needs a fused location provider"));
654         }
655 
656         // bind to geocoder provider
657         mGeocodeProvider = GeocoderProxy.createAndBind(mContext,
658                 com.android.internal.R.bool.config_enableGeocoderOverlay,
659                 com.android.internal.R.string.config_geocoderProviderPackageName,
660                 com.android.internal.R.array.config_locationProviderPackageNames,
661                 mLocationHandler);
662         if (mGeocodeProvider == null) {
663             Slog.e(TAG,  "no geocoder provider found");
664         }
665 
666         // bind to fused hardware provider if supported
667         // in devices without support, requesting an instance of FlpHardwareProvider will raise an
668         // exception, so make sure we only do that when supported
669         FlpHardwareProvider flpHardwareProvider;
670         if (FlpHardwareProvider.isSupported()) {
671             flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
672             FusedProxy fusedProxy = FusedProxy.createAndBind(
673                     mContext,
674                     mLocationHandler,
675                     flpHardwareProvider.getLocationHardware(),
676                     com.android.internal.R.bool.config_enableHardwareFlpOverlay,
677                     com.android.internal.R.string.config_hardwareFlpPackageName,
678                     com.android.internal.R.array.config_locationProviderPackageNames);
679             if (fusedProxy == null) {
680                 Slog.d(TAG, "Unable to bind FusedProxy.");
681             }
682         } else {
683             flpHardwareProvider = null;
684             Slog.d(TAG, "FLP HAL not supported");
685         }
686 
687         // bind to geofence provider
688         GeofenceProxy provider = GeofenceProxy.createAndBind(
689                 mContext,com.android.internal.R.bool.config_enableGeofenceOverlay,
690                 com.android.internal.R.string.config_geofenceProviderPackageName,
691                 com.android.internal.R.array.config_locationProviderPackageNames,
692                 mLocationHandler,
693                 mGpsGeofenceProxy,
694                 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
695         if (provider == null) {
696             Slog.d(TAG,  "Unable to bind FLP Geofence proxy.");
697         }
698 
699         // bind to hardware activity recognition
700         boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported();
701         ActivityRecognitionHardware activityRecognitionHardware = null;
702         if (activityRecognitionHardwareIsSupported) {
703             activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext);
704         } else {
705             Slog.d(TAG, "Hardware Activity-Recognition not supported.");
706         }
707         ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind(
708                 mContext,
709                 mLocationHandler,
710                 activityRecognitionHardwareIsSupported,
711                 activityRecognitionHardware,
712                 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay,
713                 com.android.internal.R.string.config_activityRecognitionHardwarePackageName,
714                 com.android.internal.R.array.config_locationProviderPackageNames);
715         if (proxy == null) {
716             Slog.d(TAG, "Unable to bind ActivityRecognitionProxy.");
717         }
718 
719         String[] testProviderStrings = resources.getStringArray(
720                 com.android.internal.R.array.config_testLocationProviders);
721         for (String testProviderString : testProviderStrings) {
722             String fragments[] = testProviderString.split(",");
723             String name = fragments[0].trim();
724             if (mProvidersByName.get(name) != null) {
725                 throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
726             }
727             ProviderProperties properties = new ProviderProperties(
728                     Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
729                     Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
730                     Boolean.parseBoolean(fragments[3]) /* requiresCell */,
731                     Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
732                     Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
733                     Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
734                     Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
735                     Integer.parseInt(fragments[8]) /* powerRequirement */,
736                     Integer.parseInt(fragments[9]) /* accuracy */);
737             addTestProviderLocked(name, properties);
738         }
739     }
740 
741     /**
742      * Called when the device's active user changes.
743      * @param userId the new active user's UserId
744      */
switchUser(int userId)745     private void switchUser(int userId) {
746         if (mCurrentUserId == userId) {
747             return;
748         }
749         mBlacklist.switchUser(userId);
750         mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
751         synchronized (mLock) {
752             mLastLocation.clear();
753             mLastLocationCoarseInterval.clear();
754             for (LocationProviderInterface p : mProviders) {
755                 updateProviderListenersLocked(p.getName(), false);
756             }
757             mCurrentUserId = userId;
758             updateUserProfiles(userId);
759             updateProvidersLocked();
760         }
761     }
762 
763     private static final class Identity {
764         final int mUid;
765         final int mPid;
766         final String mPackageName;
767 
Identity(int uid, int pid, String packageName)768         Identity(int uid, int pid, String packageName) {
769             mUid = uid;
770             mPid = pid;
771             mPackageName = packageName;
772         }
773     }
774 
775     /**
776      * A wrapper class holding either an ILocationListener or a PendingIntent to receive
777      * location updates.
778      */
779     private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished {
780         final Identity mIdentity;
781         final int mAllowedResolutionLevel;  // resolution level allowed to receiver
782 
783         final ILocationListener mListener;
784         final PendingIntent mPendingIntent;
785         final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller.
786         final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver.
787         final Object mKey;
788 
789         final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<>();
790 
791         // True if app ops has started monitoring this receiver for locations.
792         boolean mOpMonitoring;
793         // True if app ops has started monitoring this receiver for high power (gps) locations.
794         boolean mOpHighPowerMonitoring;
795         int mPendingBroadcasts;
796         PowerManager.WakeLock mWakeLock;
797 
Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps)798         Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
799                 String packageName, WorkSource workSource, boolean hideFromAppOps) {
800             mListener = listener;
801             mPendingIntent = intent;
802             if (listener != null) {
803                 mKey = listener.asBinder();
804             } else {
805                 mKey = intent;
806             }
807             mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid);
808             mIdentity = new Identity(uid, pid, packageName);
809             if (workSource != null && workSource.size() <= 0) {
810                 workSource = null;
811             }
812             mWorkSource = workSource;
813             mHideFromAppOps = hideFromAppOps;
814 
815             updateMonitoring(true);
816 
817             // construct/configure wakelock
818             mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
819             if (workSource == null) {
820                 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName);
821             }
822             mWakeLock.setWorkSource(workSource);
823         }
824 
825         @Override
equals(Object otherObj)826         public boolean equals(Object otherObj) {
827             return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
828         }
829 
830         @Override
hashCode()831         public int hashCode() {
832             return mKey.hashCode();
833         }
834 
835         @Override
toString()836         public String toString() {
837             StringBuilder s = new StringBuilder();
838             s.append("Reciever[");
839             s.append(Integer.toHexString(System.identityHashCode(this)));
840             if (mListener != null) {
841                 s.append(" listener");
842             } else {
843                 s.append(" intent");
844             }
845             for (String p : mUpdateRecords.keySet()) {
846                 s.append(" ").append(mUpdateRecords.get(p).toString());
847             }
848             s.append("]");
849             return s.toString();
850         }
851 
852         /**
853          * Update AppOp monitoring for this receiver.
854          *
855          * @param allow If true receiver is currently active, if false it's been removed.
856          */
updateMonitoring(boolean allow)857         public void updateMonitoring(boolean allow) {
858             if (mHideFromAppOps) {
859                 return;
860             }
861 
862             boolean requestingLocation = false;
863             boolean requestingHighPowerLocation = false;
864             if (allow) {
865                 // See if receiver has any enabled update records.  Also note if any update records
866                 // are high power (has a high power provider with an interval under a threshold).
867                 for (UpdateRecord updateRecord : mUpdateRecords.values()) {
868                     if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) {
869                         requestingLocation = true;
870                         LocationProviderInterface locationProvider
871                                 = mProvidersByName.get(updateRecord.mProvider);
872                         ProviderProperties properties = locationProvider != null
873                                 ? locationProvider.getProperties() : null;
874                         if (properties != null
875                                 && properties.mPowerRequirement == Criteria.POWER_HIGH
876                                 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) {
877                             requestingHighPowerLocation = true;
878                             break;
879                         }
880                     }
881                 }
882             }
883 
884             // First update monitoring of any location request (including high power).
885             mOpMonitoring = updateMonitoring(
886                     requestingLocation,
887                     mOpMonitoring,
888                     AppOpsManager.OP_MONITOR_LOCATION);
889 
890             // Now update monitoring of high power requests only.
891             boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
892             mOpHighPowerMonitoring = updateMonitoring(
893                     requestingHighPowerLocation,
894                     mOpHighPowerMonitoring,
895                     AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
896             if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
897                 // Send an intent to notify that a high power request has been added/removed.
898                 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
899                 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
900             }
901         }
902 
903         /**
904          * Update AppOps monitoring for a single location request and op type.
905          *
906          * @param allowMonitoring True if monitoring is allowed for this request/op.
907          * @param currentlyMonitoring True if AppOps is currently monitoring this request/op.
908          * @param op AppOps code for the op to update.
909          * @return True if monitoring is on for this request/op after updating.
910          */
updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring, int op)911         private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring,
912                 int op) {
913             if (!currentlyMonitoring) {
914                 if (allowMonitoring) {
915                     return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
916                             == AppOpsManager.MODE_ALLOWED;
917                 }
918             } else {
919                 if (!allowMonitoring
920                         || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName)
921                         != AppOpsManager.MODE_ALLOWED) {
922                     mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName);
923                     return false;
924                 }
925             }
926 
927             return currentlyMonitoring;
928         }
929 
isListener()930         public boolean isListener() {
931             return mListener != null;
932         }
933 
isPendingIntent()934         public boolean isPendingIntent() {
935             return mPendingIntent != null;
936         }
937 
getListener()938         public ILocationListener getListener() {
939             if (mListener != null) {
940                 return mListener;
941             }
942             throw new IllegalStateException("Request for non-existent listener");
943         }
944 
callStatusChangedLocked(String provider, int status, Bundle extras)945         public boolean callStatusChangedLocked(String provider, int status, Bundle extras) {
946             if (mListener != null) {
947                 try {
948                     synchronized (this) {
949                         // synchronize to ensure incrementPendingBroadcastsLocked()
950                         // is called before decrementPendingBroadcasts()
951                         mListener.onStatusChanged(provider, status, extras);
952                         // call this after broadcasting so we do not increment
953                         // if we throw an exeption.
954                         incrementPendingBroadcastsLocked();
955                     }
956                 } catch (RemoteException e) {
957                     return false;
958                 }
959             } else {
960                 Intent statusChanged = new Intent();
961                 statusChanged.putExtras(new Bundle(extras));
962                 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status);
963                 try {
964                     synchronized (this) {
965                         // synchronize to ensure incrementPendingBroadcastsLocked()
966                         // is called before decrementPendingBroadcasts()
967                         mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler,
968                                 getResolutionPermission(mAllowedResolutionLevel));
969                         // call this after broadcasting so we do not increment
970                         // if we throw an exeption.
971                         incrementPendingBroadcastsLocked();
972                     }
973                 } catch (PendingIntent.CanceledException e) {
974                     return false;
975                 }
976             }
977             return true;
978         }
979 
callLocationChangedLocked(Location location)980         public boolean callLocationChangedLocked(Location location) {
981             if (mListener != null) {
982                 try {
983                     synchronized (this) {
984                         // synchronize to ensure incrementPendingBroadcastsLocked()
985                         // is called before decrementPendingBroadcasts()
986                         mListener.onLocationChanged(new Location(location));
987                         // call this after broadcasting so we do not increment
988                         // if we throw an exeption.
989                         incrementPendingBroadcastsLocked();
990                     }
991                 } catch (RemoteException e) {
992                     return false;
993                 }
994             } else {
995                 Intent locationChanged = new Intent();
996                 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location));
997                 try {
998                     synchronized (this) {
999                         // synchronize to ensure incrementPendingBroadcastsLocked()
1000                         // is called before decrementPendingBroadcasts()
1001                         mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler,
1002                                 getResolutionPermission(mAllowedResolutionLevel));
1003                         // call this after broadcasting so we do not increment
1004                         // if we throw an exeption.
1005                         incrementPendingBroadcastsLocked();
1006                     }
1007                 } catch (PendingIntent.CanceledException e) {
1008                     return false;
1009                 }
1010             }
1011             return true;
1012         }
1013 
callProviderEnabledLocked(String provider, boolean enabled)1014         public boolean callProviderEnabledLocked(String provider, boolean enabled) {
1015             // First update AppOp monitoring.
1016             // An app may get/lose location access as providers are enabled/disabled.
1017             updateMonitoring(true);
1018 
1019             if (mListener != null) {
1020                 try {
1021                     synchronized (this) {
1022                         // synchronize to ensure incrementPendingBroadcastsLocked()
1023                         // is called before decrementPendingBroadcasts()
1024                         if (enabled) {
1025                             mListener.onProviderEnabled(provider);
1026                         } else {
1027                             mListener.onProviderDisabled(provider);
1028                         }
1029                         // call this after broadcasting so we do not increment
1030                         // if we throw an exeption.
1031                         incrementPendingBroadcastsLocked();
1032                     }
1033                 } catch (RemoteException e) {
1034                     return false;
1035                 }
1036             } else {
1037                 Intent providerIntent = new Intent();
1038                 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled);
1039                 try {
1040                     synchronized (this) {
1041                         // synchronize to ensure incrementPendingBroadcastsLocked()
1042                         // is called before decrementPendingBroadcasts()
1043                         mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler,
1044                                 getResolutionPermission(mAllowedResolutionLevel));
1045                         // call this after broadcasting so we do not increment
1046                         // if we throw an exeption.
1047                         incrementPendingBroadcastsLocked();
1048                     }
1049                 } catch (PendingIntent.CanceledException e) {
1050                     return false;
1051                 }
1052             }
1053             return true;
1054         }
1055 
1056         @Override
binderDied()1057         public void binderDied() {
1058             if (D) Log.d(TAG, "Location listener died");
1059 
1060             synchronized (mLock) {
1061                 removeUpdatesLocked(this);
1062             }
1063             synchronized (this) {
1064                 clearPendingBroadcastsLocked();
1065             }
1066         }
1067 
1068         @Override
onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)1069         public void onSendFinished(PendingIntent pendingIntent, Intent intent,
1070                 int resultCode, String resultData, Bundle resultExtras) {
1071             synchronized (this) {
1072                 decrementPendingBroadcastsLocked();
1073             }
1074         }
1075 
1076         // this must be called while synchronized by caller in a synchronized block
1077         // containing the sending of the broadcaset
incrementPendingBroadcastsLocked()1078         private void incrementPendingBroadcastsLocked() {
1079             if (mPendingBroadcasts++ == 0) {
1080                 mWakeLock.acquire();
1081             }
1082         }
1083 
decrementPendingBroadcastsLocked()1084         private void decrementPendingBroadcastsLocked() {
1085             if (--mPendingBroadcasts == 0) {
1086                 if (mWakeLock.isHeld()) {
1087                     mWakeLock.release();
1088                 }
1089             }
1090         }
1091 
clearPendingBroadcastsLocked()1092         public void clearPendingBroadcastsLocked() {
1093             if (mPendingBroadcasts > 0) {
1094                 mPendingBroadcasts = 0;
1095                 if (mWakeLock.isHeld()) {
1096                     mWakeLock.release();
1097                 }
1098             }
1099         }
1100     }
1101 
1102     @Override
locationCallbackFinished(ILocationListener listener)1103     public void locationCallbackFinished(ILocationListener listener) {
1104         //Do not use getReceiverLocked here as that will add the ILocationListener to
1105         //the receiver list if it is not found.  If it is not found then the
1106         //LocationListener was removed when it had a pending broadcast and should
1107         //not be added back.
1108         synchronized (mLock) {
1109             IBinder binder = listener.asBinder();
1110             Receiver receiver = mReceivers.get(binder);
1111             if (receiver != null) {
1112                 synchronized (receiver) {
1113                     // so wakelock calls will succeed
1114                     long identity = Binder.clearCallingIdentity();
1115                     receiver.decrementPendingBroadcastsLocked();
1116                     Binder.restoreCallingIdentity(identity);
1117                 }
1118             }
1119         }
1120     }
1121 
1122     /**
1123      * Returns the system information of the GNSS hardware.
1124      */
1125     @Override
getGnssYearOfHardware()1126     public int getGnssYearOfHardware() {
1127         if (mGnssSystemInfoProvider != null) {
1128             return mGnssSystemInfoProvider.getGnssYearOfHardware();
1129         } else {
1130             return 0;
1131         }
1132     }
1133 
1134     /**
1135      * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly
1136      * (try to) access GNSS information at this layer.
1137      */
hasGnssPermissions(String packageName)1138     private boolean hasGnssPermissions(String packageName) {
1139         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1140         checkResolutionLevelIsSufficientForProviderUse(
1141                 allowedResolutionLevel,
1142                 LocationManager.GPS_PROVIDER);
1143 
1144         int pid = Binder.getCallingPid();
1145         int uid = Binder.getCallingUid();
1146         long identity = Binder.clearCallingIdentity();
1147         boolean hasLocationAccess;
1148         try {
1149             hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
1150         } finally {
1151             Binder.restoreCallingIdentity(identity);
1152         }
1153 
1154         return hasLocationAccess;
1155     }
1156 
1157     /**
1158      * Returns the GNSS batching size, if available.
1159      */
1160     @Override
getGnssBatchSize(String packageName)1161     public int getGnssBatchSize(String packageName) {
1162         mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1163                 "Location Hardware permission not granted to access hardware batching");
1164 
1165         if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) {
1166             return mGnssBatchingProvider.getSize();
1167         } else {
1168             return 0;
1169         }
1170     }
1171 
1172     /**
1173      * Adds a callback for GNSS Batching events, if permissions allow, which are transported
1174      * to potentially multiple listeners by the BatchedLocationCallbackTransport above this.
1175      */
1176     @Override
addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName)1177     public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) {
1178         mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1179                 "Location Hardware permission not granted to access hardware batching");
1180 
1181         if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1182             return false;
1183         }
1184 
1185         mGnssBatchingCallback = callback;
1186         mGnssBatchingDeathCallback = new LinkedCallback(callback);
1187         try {
1188             callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */);
1189         } catch (RemoteException e) {
1190             // if the remote process registering the listener is already dead, just swallow the
1191             // exception and return
1192             Log.e(TAG, "Remote listener already died.", e);
1193             return false;
1194         }
1195 
1196         return true;
1197     }
1198 
1199     private class LinkedCallback implements IBinder.DeathRecipient {
1200         private final IBatchedLocationCallback mCallback;
1201 
LinkedCallback(@onNull IBatchedLocationCallback callback)1202         public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
1203             mCallback = callback;
1204         }
1205 
1206         @NonNull
getUnderlyingListener()1207         public IBatchedLocationCallback getUnderlyingListener() {
1208             return mCallback;
1209         }
1210 
1211         @Override
binderDied()1212         public void binderDied() {
1213             Log.d(TAG, "Remote Batching Callback died: " + mCallback);
1214             stopGnssBatch();
1215             removeGnssBatchingCallback();
1216         }
1217     }
1218 
1219     /**
1220      * Removes callback for GNSS batching
1221      */
1222     @Override
removeGnssBatchingCallback()1223     public void removeGnssBatchingCallback() {
1224         try {
1225             mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback,
1226                     0 /* flags */);
1227         } catch (NoSuchElementException e) {
1228             // if the death callback isn't connected (it should be...), log error, swallow the
1229             // exception and return
1230             Log.e(TAG, "Couldn't unlink death callback.", e);
1231         }
1232         mGnssBatchingCallback = null;
1233         mGnssBatchingDeathCallback = null;
1234     }
1235 
1236 
1237     /**
1238      * Starts GNSS batching, if available.
1239      */
1240     @Override
startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName)1241     public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) {
1242         mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1243                 "Location Hardware permission not granted to access hardware batching");
1244 
1245         if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) {
1246             return false;
1247         }
1248 
1249         if (mGnssBatchingInProgress) {
1250             // Current design does not expect multiple starts to be called repeatedly
1251             Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch");
1252             // Try to clean up anyway, and continue
1253             stopGnssBatch();
1254         }
1255 
1256         mGnssBatchingInProgress = true;
1257         return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull);
1258     }
1259 
1260     /**
1261      * Flushes a GNSS batch in progress
1262      */
1263     @Override
flushGnssBatch(String packageName)1264     public void flushGnssBatch(String packageName) {
1265         mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1266                 "Location Hardware permission not granted to access hardware batching");
1267 
1268         if (!hasGnssPermissions(packageName)) {
1269             Log.e(TAG, "flushGnssBatch called without GNSS permissions");
1270             return;
1271         }
1272 
1273         if (!mGnssBatchingInProgress) {
1274             Log.w(TAG, "flushGnssBatch called with no batch in progress");
1275         }
1276 
1277         if (mGnssBatchingProvider != null) {
1278              mGnssBatchingProvider.flush();
1279         }
1280     }
1281 
1282     /**
1283      * Stops GNSS batching
1284      */
1285     @Override
stopGnssBatch()1286     public boolean stopGnssBatch() {
1287         mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE,
1288                 "Location Hardware permission not granted to access hardware batching");
1289 
1290         if (mGnssBatchingProvider != null) {
1291             mGnssBatchingInProgress = false;
1292             return mGnssBatchingProvider.stop();
1293         } else  {
1294             return false;
1295         }
1296     }
1297 
1298     @Override
reportLocationBatch(List<Location> locations)1299     public void reportLocationBatch(List<Location> locations) {
1300         checkCallerIsProvider();
1301 
1302         // Currently used only for GNSS locations - update permissions check if changed
1303         if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) {
1304             if (mGnssBatchingCallback == null) {
1305                 Slog.e(TAG, "reportLocationBatch() called without active Callback");
1306                 return;
1307             }
1308             try {
1309                 mGnssBatchingCallback.onLocationBatch(locations);
1310             } catch (RemoteException e) {
1311                 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e);
1312             }
1313         } else {
1314             Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked");
1315         }
1316     }
1317 
addProviderLocked(LocationProviderInterface provider)1318     private void addProviderLocked(LocationProviderInterface provider) {
1319         mProviders.add(provider);
1320         mProvidersByName.put(provider.getName(), provider);
1321     }
1322 
removeProviderLocked(LocationProviderInterface provider)1323     private void removeProviderLocked(LocationProviderInterface provider) {
1324         provider.disable();
1325         mProviders.remove(provider);
1326         mProvidersByName.remove(provider.getName());
1327     }
1328 
1329     /**
1330      * Returns "true" if access to the specified location provider is allowed by the current
1331      * user's settings. Access to all location providers is forbidden to non-location-provider
1332      * processes belonging to background users.
1333      *
1334      * @param provider the name of the location provider
1335      */
isAllowedByCurrentUserSettingsLocked(String provider)1336     private boolean isAllowedByCurrentUserSettingsLocked(String provider) {
1337         if (mEnabledProviders.contains(provider)) {
1338             return true;
1339         }
1340         if (mDisabledProviders.contains(provider)) {
1341             return false;
1342         }
1343         // Use system settings
1344         ContentResolver resolver = mContext.getContentResolver();
1345 
1346         return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId);
1347     }
1348 
1349     /**
1350      * Returns "true" if access to the specified location provider is allowed by the specified
1351      * user's settings. Access to all location providers is forbidden to non-location-provider
1352      * processes belonging to background users.
1353      *
1354      * @param provider the name of the location provider
1355      * @param uid the requestor's UID
1356      */
isAllowedByUserSettingsLocked(String provider, int uid)1357     private boolean isAllowedByUserSettingsLocked(String provider, int uid) {
1358         if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) {
1359             return false;
1360         }
1361         return isAllowedByCurrentUserSettingsLocked(provider);
1362     }
1363 
1364     /**
1365      * Returns the permission string associated with the specified resolution level.
1366      *
1367      * @param resolutionLevel the resolution level
1368      * @return the permission string
1369      */
getResolutionPermission(int resolutionLevel)1370     private String getResolutionPermission(int resolutionLevel) {
1371         switch (resolutionLevel) {
1372             case RESOLUTION_LEVEL_FINE:
1373                 return android.Manifest.permission.ACCESS_FINE_LOCATION;
1374             case RESOLUTION_LEVEL_COARSE:
1375                 return android.Manifest.permission.ACCESS_COARSE_LOCATION;
1376             default:
1377                 return null;
1378         }
1379     }
1380 
1381     /**
1382      * Returns the resolution level allowed to the given PID/UID pair.
1383      *
1384      * @param pid the PID
1385      * @param uid the UID
1386      * @return resolution level allowed to the pid/uid pair
1387      */
getAllowedResolutionLevel(int pid, int uid)1388     private int getAllowedResolutionLevel(int pid, int uid) {
1389         if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION,
1390                 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1391             return RESOLUTION_LEVEL_FINE;
1392         } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION,
1393                 pid, uid) == PackageManager.PERMISSION_GRANTED) {
1394             return RESOLUTION_LEVEL_COARSE;
1395         } else {
1396             return RESOLUTION_LEVEL_NONE;
1397         }
1398     }
1399 
1400     /**
1401      * Returns the resolution level allowed to the caller
1402      *
1403      * @return resolution level allowed to caller
1404      */
getCallerAllowedResolutionLevel()1405     private int getCallerAllowedResolutionLevel() {
1406         return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid());
1407     }
1408 
1409     /**
1410      * Throw SecurityException if specified resolution level is insufficient to use geofences.
1411      *
1412      * @param allowedResolutionLevel resolution level allowed to caller
1413      */
checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel)1414     private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) {
1415         if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
1416             throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission");
1417         }
1418     }
1419 
1420     /**
1421      * Return the minimum resolution level required to use the specified location provider.
1422      *
1423      * @param provider the name of the location provider
1424      * @return minimum resolution level required for provider
1425      */
getMinimumResolutionLevelForProviderUse(String provider)1426     private int getMinimumResolutionLevelForProviderUse(String provider) {
1427         if (LocationManager.GPS_PROVIDER.equals(provider) ||
1428                 LocationManager.PASSIVE_PROVIDER.equals(provider)) {
1429             // gps and passive providers require FINE permission
1430             return RESOLUTION_LEVEL_FINE;
1431         } else if (LocationManager.NETWORK_PROVIDER.equals(provider) ||
1432                 LocationManager.FUSED_PROVIDER.equals(provider)) {
1433             // network and fused providers are ok with COARSE or FINE
1434             return RESOLUTION_LEVEL_COARSE;
1435         } else {
1436             // mock providers
1437             LocationProviderInterface lp = mMockProviders.get(provider);
1438             if (lp != null) {
1439                 ProviderProperties properties = lp.getProperties();
1440                 if (properties != null) {
1441                     if (properties.mRequiresSatellite) {
1442                         // provider requiring satellites require FINE permission
1443                         return RESOLUTION_LEVEL_FINE;
1444                     } else if (properties.mRequiresNetwork || properties.mRequiresCell) {
1445                         // provider requiring network and or cell require COARSE or FINE
1446                         return RESOLUTION_LEVEL_COARSE;
1447                     }
1448                 }
1449             }
1450         }
1451         return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE
1452     }
1453 
1454     /**
1455      * Throw SecurityException if specified resolution level is insufficient to use the named
1456      * location provider.
1457      *
1458      * @param allowedResolutionLevel resolution level allowed to caller
1459      * @param providerName the name of the location provider
1460      */
checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel, String providerName)1461     private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel,
1462             String providerName) {
1463         int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName);
1464         if (allowedResolutionLevel < requiredResolutionLevel) {
1465             switch (requiredResolutionLevel) {
1466                 case RESOLUTION_LEVEL_FINE:
1467                     throw new SecurityException("\"" + providerName + "\" location provider " +
1468                             "requires ACCESS_FINE_LOCATION permission.");
1469                 case RESOLUTION_LEVEL_COARSE:
1470                     throw new SecurityException("\"" + providerName + "\" location provider " +
1471                             "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission.");
1472                 default:
1473                     throw new SecurityException("Insufficient permission for \"" + providerName +
1474                             "\" location provider.");
1475             }
1476         }
1477     }
1478 
1479     /**
1480      * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages
1481      * for battery).
1482      */
checkDeviceStatsAllowed()1483     private void checkDeviceStatsAllowed() {
1484         mContext.enforceCallingOrSelfPermission(
1485                 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
1486     }
1487 
checkUpdateAppOpsAllowed()1488     private void checkUpdateAppOpsAllowed() {
1489         mContext.enforceCallingOrSelfPermission(
1490                 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
1491     }
1492 
resolutionLevelToOp(int allowedResolutionLevel)1493     public static int resolutionLevelToOp(int allowedResolutionLevel) {
1494         if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) {
1495             if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) {
1496                 return AppOpsManager.OP_COARSE_LOCATION;
1497             } else {
1498                 return AppOpsManager.OP_FINE_LOCATION;
1499             }
1500         }
1501         return -1;
1502     }
1503 
reportLocationAccessNoThrow( int pid, int uid, String packageName, int allowedResolutionLevel)1504     boolean reportLocationAccessNoThrow(
1505             int pid, int uid, String packageName, int allowedResolutionLevel) {
1506         int op = resolutionLevelToOp(allowedResolutionLevel);
1507         if (op >= 0) {
1508             if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1509                 return false;
1510             }
1511         }
1512 
1513         return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
1514     }
1515 
checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel)1516     boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) {
1517         int op = resolutionLevelToOp(allowedResolutionLevel);
1518         if (op >= 0) {
1519             if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
1520                 return false;
1521             }
1522         }
1523 
1524         return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel;
1525     }
1526 
1527     /**
1528      * Returns all providers by name, including passive, but excluding
1529      * fused, also including ones that are not permitted to
1530      * be accessed by the calling activity or are currently disabled.
1531      */
1532     @Override
getAllProviders()1533     public List<String> getAllProviders() {
1534         ArrayList<String> out;
1535         synchronized (mLock) {
1536             out = new ArrayList<>(mProviders.size());
1537             for (LocationProviderInterface provider : mProviders) {
1538                 String name = provider.getName();
1539                 if (LocationManager.FUSED_PROVIDER.equals(name)) {
1540                     continue;
1541                 }
1542                 out.add(name);
1543             }
1544         }
1545 
1546         if (D) Log.d(TAG, "getAllProviders()=" + out);
1547         return out;
1548     }
1549 
1550     /**
1551      * Return all providers by name, that match criteria and are optionally
1552      * enabled.
1553      * Can return passive provider, but never returns fused provider.
1554      */
1555     @Override
getProviders(Criteria criteria, boolean enabledOnly)1556     public List<String> getProviders(Criteria criteria, boolean enabledOnly) {
1557         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
1558         ArrayList<String> out;
1559         int uid = Binder.getCallingUid();
1560         long identity = Binder.clearCallingIdentity();
1561         try {
1562             synchronized (mLock) {
1563                 out = new ArrayList<>(mProviders.size());
1564                 for (LocationProviderInterface provider : mProviders) {
1565                     String name = provider.getName();
1566                     if (LocationManager.FUSED_PROVIDER.equals(name)) {
1567                         continue;
1568                     }
1569                     if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) {
1570                         if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) {
1571                             continue;
1572                         }
1573                         if (criteria != null && !LocationProvider.propertiesMeetCriteria(
1574                                 name, provider.getProperties(), criteria)) {
1575                             continue;
1576                         }
1577                         out.add(name);
1578                     }
1579                 }
1580             }
1581         } finally {
1582             Binder.restoreCallingIdentity(identity);
1583         }
1584 
1585         if (D) Log.d(TAG, "getProviders()=" + out);
1586         return out;
1587     }
1588 
1589     /**
1590      * Return the name of the best provider given a Criteria object.
1591      * This method has been deprecated from the public API,
1592      * and the whole LocationProvider (including #meetsCriteria)
1593      * has been deprecated as well. So this method now uses
1594      * some simplified logic.
1595      */
1596     @Override
getBestProvider(Criteria criteria, boolean enabledOnly)1597     public String getBestProvider(Criteria criteria, boolean enabledOnly) {
1598         String result = null;
1599 
1600         List<String> providers = getProviders(criteria, enabledOnly);
1601         if (!providers.isEmpty()) {
1602             result = pickBest(providers);
1603             if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1604             return result;
1605         }
1606         providers = getProviders(null, enabledOnly);
1607         if (!providers.isEmpty()) {
1608             result = pickBest(providers);
1609             if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1610             return result;
1611         }
1612 
1613         if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result);
1614         return null;
1615     }
1616 
pickBest(List<String> providers)1617     private String pickBest(List<String> providers) {
1618         if (providers.contains(LocationManager.GPS_PROVIDER)) {
1619             return LocationManager.GPS_PROVIDER;
1620         } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) {
1621             return LocationManager.NETWORK_PROVIDER;
1622         } else {
1623             return providers.get(0);
1624         }
1625     }
1626 
1627     @Override
providerMeetsCriteria(String provider, Criteria criteria)1628     public boolean providerMeetsCriteria(String provider, Criteria criteria) {
1629         LocationProviderInterface p = mProvidersByName.get(provider);
1630         if (p == null) {
1631             throw new IllegalArgumentException("provider=" + provider);
1632         }
1633 
1634         boolean result = LocationProvider.propertiesMeetCriteria(
1635                 p.getName(), p.getProperties(), criteria);
1636         if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result);
1637         return result;
1638     }
1639 
updateProvidersLocked()1640     private void updateProvidersLocked() {
1641         boolean changesMade = false;
1642         for (int i = mProviders.size() - 1; i >= 0; i--) {
1643             LocationProviderInterface p = mProviders.get(i);
1644             boolean isEnabled = p.isEnabled();
1645             String name = p.getName();
1646             boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
1647             if (isEnabled && !shouldBeEnabled) {
1648                 updateProviderListenersLocked(name, false);
1649                 // If any provider has been disabled, clear all last locations for all providers.
1650                 // This is to be on the safe side in case a provider has location derived from
1651                 // this disabled provider.
1652                 mLastLocation.clear();
1653                 mLastLocationCoarseInterval.clear();
1654                 changesMade = true;
1655             } else if (!isEnabled && shouldBeEnabled) {
1656                 updateProviderListenersLocked(name, true);
1657                 changesMade = true;
1658             }
1659         }
1660         if (changesMade) {
1661             mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
1662                     UserHandle.ALL);
1663             mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
1664                     UserHandle.ALL);
1665         }
1666     }
1667 
updateProviderListenersLocked(String provider, boolean enabled)1668     private void updateProviderListenersLocked(String provider, boolean enabled) {
1669         int listeners = 0;
1670 
1671         LocationProviderInterface p = mProvidersByName.get(provider);
1672         if (p == null) return;
1673 
1674         ArrayList<Receiver> deadReceivers = null;
1675 
1676         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1677         if (records != null) {
1678             for (UpdateRecord record : records) {
1679                 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
1680                     // Sends a notification message to the receiver
1681                     if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
1682                         if (deadReceivers == null) {
1683                             deadReceivers = new ArrayList<>();
1684                         }
1685                         deadReceivers.add(record.mReceiver);
1686                     }
1687                     listeners++;
1688                 }
1689             }
1690         }
1691 
1692         if (deadReceivers != null) {
1693             for (int i = deadReceivers.size() - 1; i >= 0; i--) {
1694                 removeUpdatesLocked(deadReceivers.get(i));
1695             }
1696         }
1697 
1698         if (enabled) {
1699             p.enable();
1700             if (listeners > 0) {
1701                 applyRequirementsLocked(provider);
1702             }
1703         } else {
1704             p.disable();
1705         }
1706     }
1707 
applyRequirementsLocked(String provider)1708     private void applyRequirementsLocked(String provider) {
1709         LocationProviderInterface p = mProvidersByName.get(provider);
1710         if (p == null) return;
1711 
1712         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1713         WorkSource worksource = new WorkSource();
1714         ProviderRequest providerRequest = new ProviderRequest();
1715 
1716         ContentResolver resolver = mContext.getContentResolver();
1717         long backgroundThrottleInterval = Settings.Global.getLong(
1718                 resolver,
1719                 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
1720                 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
1721 
1722         if (records != null) {
1723             for (UpdateRecord record : records) {
1724                 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
1725                     if (checkLocationAccess(
1726                             record.mReceiver.mIdentity.mPid,
1727                             record.mReceiver.mIdentity.mUid,
1728                             record.mReceiver.mIdentity.mPackageName,
1729                             record.mReceiver.mAllowedResolutionLevel)) {
1730                         LocationRequest locationRequest = record.mRealRequest;
1731                         long interval = locationRequest.getInterval();
1732 
1733                         if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) {
1734                             if (!record.mIsForegroundUid) {
1735                                 interval = Math.max(interval, backgroundThrottleInterval);
1736                             }
1737                             if (interval != locationRequest.getInterval()) {
1738                                 locationRequest = new LocationRequest(locationRequest);
1739                                 locationRequest.setInterval(interval);
1740                             }
1741                         }
1742 
1743                         record.mRequest = locationRequest;
1744                         providerRequest.locationRequests.add(locationRequest);
1745                         if (interval < providerRequest.interval) {
1746                             providerRequest.reportLocation = true;
1747                             providerRequest.interval = interval;
1748                         }
1749                     }
1750                 }
1751             }
1752 
1753             if (providerRequest.reportLocation) {
1754                 // calculate who to blame for power
1755                 // This is somewhat arbitrary. We pick a threshold interval
1756                 // that is slightly higher that the minimum interval, and
1757                 // spread the blame across all applications with a request
1758                 // under that threshold.
1759                 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2;
1760                 for (UpdateRecord record : records) {
1761                     if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
1762                         LocationRequest locationRequest = record.mRequest;
1763 
1764                         // Don't assign battery blame for update records whose
1765                         // client has no permission to receive location data.
1766                         if (!providerRequest.locationRequests.contains(locationRequest)) {
1767                             continue;
1768                         }
1769 
1770                         if (locationRequest.getInterval() <= thresholdInterval) {
1771                             if (record.mReceiver.mWorkSource != null
1772                                     && record.mReceiver.mWorkSource.size() > 0
1773                                     && record.mReceiver.mWorkSource.getName(0) != null) {
1774                                 // Assign blame to another work source.
1775                                 // Can only assign blame if the WorkSource contains names.
1776                                 worksource.add(record.mReceiver.mWorkSource);
1777                             } else {
1778                                 // Assign blame to caller.
1779                                 worksource.add(
1780                                         record.mReceiver.mIdentity.mUid,
1781                                         record.mReceiver.mIdentity.mPackageName);
1782                             }
1783                         }
1784                     }
1785                 }
1786             }
1787         }
1788 
1789         if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest);
1790         p.setRequest(providerRequest, worksource);
1791     }
1792 
1793     @Override
getBackgroundThrottlingWhitelist()1794     public String[] getBackgroundThrottlingWhitelist() {
1795         synchronized (mLock) {
1796             return mBackgroundThrottlePackageWhitelist.toArray(
1797                 new String[mBackgroundThrottlePackageWhitelist.size()]);
1798         }
1799     }
1800 
updateBackgroundThrottlingWhitelistLocked()1801     private void updateBackgroundThrottlingWhitelistLocked() {
1802         String setting = Settings.Global.getString(
1803             mContext.getContentResolver(),
1804             Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
1805         if (setting == null) {
1806             setting = "";
1807         }
1808 
1809         mBackgroundThrottlePackageWhitelist.clear();
1810         mBackgroundThrottlePackageWhitelist.addAll(
1811             SystemConfig.getInstance().getAllowUnthrottledLocation());
1812         mBackgroundThrottlePackageWhitelist.addAll(
1813             Arrays.asList(setting.split(",")));
1814     }
1815 
isThrottlingExemptLocked(Identity identity)1816     private boolean isThrottlingExemptLocked(Identity identity) {
1817         if (identity.mUid == Process.SYSTEM_UID) {
1818             return true;
1819         }
1820 
1821         if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) {
1822             return true;
1823         }
1824 
1825         for (LocationProviderProxy provider : mProxyProviders) {
1826             if (identity.mPackageName.equals(provider.getConnectedPackageName())) {
1827                 return true;
1828             }
1829         }
1830 
1831         return false;
1832     }
1833 
1834     private class UpdateRecord {
1835         final String mProvider;
1836         final LocationRequest mRealRequest;  // original request from client
1837         LocationRequest mRequest;  // possibly throttled version of the request
1838         final Receiver mReceiver;
1839         boolean mIsForegroundUid;
1840         Location mLastFixBroadcast;
1841         long mLastStatusBroadcast;
1842 
1843         /**
1844          * Note: must be constructed with lock held.
1845          */
UpdateRecord(String provider, LocationRequest request, Receiver receiver)1846         UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
1847             mProvider = provider;
1848             mRealRequest = request;
1849             mRequest = request;
1850             mReceiver = receiver;
1851             mIsForegroundUid = isImportanceForeground(
1852                     mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName));
1853 
1854             ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
1855             if (records == null) {
1856                 records = new ArrayList<>();
1857                 mRecordsByProvider.put(provider, records);
1858             }
1859             if (!records.contains(this)) {
1860                 records.add(this);
1861             }
1862 
1863             // Update statistics for historical location requests by package/provider
1864             mRequestStatistics.startRequesting(
1865                     mReceiver.mIdentity.mPackageName, provider, request.getInterval());
1866         }
1867 
1868         /**
1869          * Method to be called when a record will no longer be used.
1870          */
disposeLocked(boolean removeReceiver)1871         void disposeLocked(boolean removeReceiver) {
1872             mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider);
1873 
1874             // remove from mRecordsByProvider
1875             ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
1876             if (globalRecords != null) {
1877                 globalRecords.remove(this);
1878             }
1879 
1880             if (!removeReceiver) return;  // the caller will handle the rest
1881 
1882             // remove from Receiver#mUpdateRecords
1883             HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords;
1884             if (receiverRecords != null) {
1885                 receiverRecords.remove(this.mProvider);
1886 
1887                 // and also remove the Receiver if it has no more update records
1888                 if (receiverRecords.size() == 0) {
1889                     removeUpdatesLocked(mReceiver);
1890                 }
1891             }
1892         }
1893 
1894         @Override
toString()1895         public String toString() {
1896             return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
1897                     + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
1898                     + ")" + " " + mRealRequest + "]";
1899         }
1900     }
1901 
getReceiverLocked(ILocationListener listener, int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps)1902     private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
1903             String packageName, WorkSource workSource, boolean hideFromAppOps) {
1904         IBinder binder = listener.asBinder();
1905         Receiver receiver = mReceivers.get(binder);
1906         if (receiver == null) {
1907             receiver = new Receiver(listener, null, pid, uid, packageName, workSource,
1908                     hideFromAppOps);
1909             try {
1910                 receiver.getListener().asBinder().linkToDeath(receiver, 0);
1911             } catch (RemoteException e) {
1912                 Slog.e(TAG, "linkToDeath failed:", e);
1913                 return null;
1914             }
1915             mReceivers.put(binder, receiver);
1916         }
1917         return receiver;
1918     }
1919 
getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps)1920     private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName,
1921             WorkSource workSource, boolean hideFromAppOps) {
1922         Receiver receiver = mReceivers.get(intent);
1923         if (receiver == null) {
1924             receiver = new Receiver(null, intent, pid, uid, packageName, workSource,
1925                     hideFromAppOps);
1926             mReceivers.put(intent, receiver);
1927         }
1928         return receiver;
1929     }
1930 
1931     /**
1932      * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution
1933      * and consistency requirements.
1934      *
1935      * @param request the LocationRequest from which to create a sanitized version
1936      * @return a version of request that meets the given resolution and consistency requirements
1937      * @hide
1938      */
createSanitizedRequest(LocationRequest request, int resolutionLevel)1939     private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) {
1940         LocationRequest sanitizedRequest = new LocationRequest(request);
1941         if (resolutionLevel < RESOLUTION_LEVEL_FINE) {
1942             switch (sanitizedRequest.getQuality()) {
1943                 case LocationRequest.ACCURACY_FINE:
1944                     sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK);
1945                     break;
1946                 case LocationRequest.POWER_HIGH:
1947                     sanitizedRequest.setQuality(LocationRequest.POWER_LOW);
1948                     break;
1949             }
1950             // throttle
1951             if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1952                 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS);
1953             }
1954             if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) {
1955                 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS);
1956             }
1957         }
1958         // make getFastestInterval() the minimum of interval and fastest interval
1959         if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) {
1960             request.setFastestInterval(request.getInterval());
1961         }
1962         return sanitizedRequest;
1963     }
1964 
checkPackageName(String packageName)1965     private void checkPackageName(String packageName) {
1966         if (packageName == null) {
1967             throw new SecurityException("invalid package name: " + packageName);
1968         }
1969         int uid = Binder.getCallingUid();
1970         String[] packages = mPackageManager.getPackagesForUid(uid);
1971         if (packages == null) {
1972             throw new SecurityException("invalid UID " + uid);
1973         }
1974         for (String pkg : packages) {
1975             if (packageName.equals(pkg)) return;
1976         }
1977         throw new SecurityException("invalid package name: " + packageName);
1978     }
1979 
checkPendingIntent(PendingIntent intent)1980     private void checkPendingIntent(PendingIntent intent) {
1981         if (intent == null) {
1982             throw new IllegalArgumentException("invalid pending intent: " + intent);
1983         }
1984     }
1985 
checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent, int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps)1986     private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
1987             int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) {
1988         if (intent == null && listener == null) {
1989             throw new IllegalArgumentException("need either listener or intent");
1990         } else if (intent != null && listener != null) {
1991             throw new IllegalArgumentException("cannot register both listener and intent");
1992         } else if (intent != null) {
1993             checkPendingIntent(intent);
1994             return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps);
1995         } else {
1996             return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps);
1997         }
1998     }
1999 
2000     @Override
requestLocationUpdates(LocationRequest request, ILocationListener listener, PendingIntent intent, String packageName)2001     public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
2002             PendingIntent intent, String packageName) {
2003         if (request == null) request = DEFAULT_LOCATION_REQUEST;
2004         checkPackageName(packageName);
2005         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2006         checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2007                 request.getProvider());
2008         WorkSource workSource = request.getWorkSource();
2009         if (workSource != null && workSource.size() > 0) {
2010             checkDeviceStatsAllowed();
2011         }
2012         boolean hideFromAppOps = request.getHideFromAppOps();
2013         if (hideFromAppOps) {
2014             checkUpdateAppOpsAllowed();
2015         }
2016         LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
2017 
2018         final int pid = Binder.getCallingPid();
2019         final int uid = Binder.getCallingUid();
2020         // providers may use public location API's, need to clear identity
2021         long identity = Binder.clearCallingIdentity();
2022         try {
2023             // We don't check for MODE_IGNORED here; we will do that when we go to deliver
2024             // a location.
2025             checkLocationAccess(pid, uid, packageName, allowedResolutionLevel);
2026 
2027             synchronized (mLock) {
2028                 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
2029                         packageName, workSource, hideFromAppOps);
2030                 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
2031             }
2032         } finally {
2033             Binder.restoreCallingIdentity(identity);
2034         }
2035     }
2036 
requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, int pid, int uid, String packageName)2037     private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver,
2038             int pid, int uid, String packageName) {
2039         // Figure out the provider. Either its explicitly request (legacy use cases), or
2040         // use the fused provider
2041         if (request == null) request = DEFAULT_LOCATION_REQUEST;
2042         String name = request.getProvider();
2043         if (name == null) {
2044             throw new IllegalArgumentException("provider name must not be null");
2045         }
2046 
2047         LocationProviderInterface provider = mProvidersByName.get(name);
2048         if (provider == null) {
2049             throw new IllegalArgumentException("provider doesn't exist: " + name);
2050         }
2051 
2052         UpdateRecord record = new UpdateRecord(name, request, receiver);
2053         if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver))
2054                 + " " + name + " " + request + " from " + packageName + "(" + uid + " "
2055                 + (record.mIsForegroundUid ? "foreground" : "background")
2056                 + (isThrottlingExemptLocked(receiver.mIdentity)
2057                     ? " [whitelisted]" : "") + ")");
2058 
2059         UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record);
2060         if (oldRecord != null) {
2061             oldRecord.disposeLocked(false);
2062         }
2063 
2064         boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid);
2065         if (isProviderEnabled) {
2066             applyRequirementsLocked(name);
2067         } else {
2068             // Notify the listener that updates are currently disabled
2069             receiver.callProviderEnabledLocked(name, false);
2070         }
2071         // Update the monitoring here just in case multiple location requests were added to the
2072         // same receiver (this request may be high power and the initial might not have been).
2073         receiver.updateMonitoring(true);
2074     }
2075 
2076     @Override
removeUpdates(ILocationListener listener, PendingIntent intent, String packageName)2077     public void removeUpdates(ILocationListener listener, PendingIntent intent,
2078             String packageName) {
2079         checkPackageName(packageName);
2080 
2081         final int pid = Binder.getCallingPid();
2082         final int uid = Binder.getCallingUid();
2083 
2084         synchronized (mLock) {
2085             WorkSource workSource = null;
2086             boolean hideFromAppOps = false;
2087             Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid,
2088                     packageName, workSource, hideFromAppOps);
2089 
2090             // providers may use public location API's, need to clear identity
2091             long identity = Binder.clearCallingIdentity();
2092             try {
2093                 removeUpdatesLocked(receiver);
2094             } finally {
2095                 Binder.restoreCallingIdentity(identity);
2096             }
2097         }
2098     }
2099 
removeUpdatesLocked(Receiver receiver)2100     private void removeUpdatesLocked(Receiver receiver) {
2101         if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver)));
2102 
2103         if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
2104             receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
2105             synchronized (receiver) {
2106                 receiver.clearPendingBroadcastsLocked();
2107             }
2108         }
2109 
2110         receiver.updateMonitoring(false);
2111 
2112         // Record which providers were associated with this listener
2113         HashSet<String> providers = new HashSet<>();
2114         HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords;
2115         if (oldRecords != null) {
2116             // Call dispose() on the obsolete update records.
2117             for (UpdateRecord record : oldRecords.values()) {
2118                 // Update statistics for historical location requests by package/provider
2119                 record.disposeLocked(false);
2120             }
2121             // Accumulate providers
2122             providers.addAll(oldRecords.keySet());
2123         }
2124 
2125         // update provider
2126         for (String provider : providers) {
2127             // If provider is already disabled, don't need to do anything
2128             if (!isAllowedByCurrentUserSettingsLocked(provider)) {
2129                 continue;
2130             }
2131 
2132             applyRequirementsLocked(provider);
2133         }
2134     }
2135 
applyAllProviderRequirementsLocked()2136     private void applyAllProviderRequirementsLocked() {
2137         for (LocationProviderInterface p : mProviders) {
2138             // If provider is already disabled, don't need to do anything
2139             if (!isAllowedByCurrentUserSettingsLocked(p.getName())) {
2140                 continue;
2141             }
2142 
2143             applyRequirementsLocked(p.getName());
2144         }
2145     }
2146 
2147     @Override
getLastLocation(LocationRequest request, String packageName)2148     public Location getLastLocation(LocationRequest request, String packageName) {
2149         if (D) Log.d(TAG, "getLastLocation: " + request);
2150         if (request == null) request = DEFAULT_LOCATION_REQUEST;
2151         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2152         checkPackageName(packageName);
2153         checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2154                 request.getProvider());
2155         // no need to sanitize this request, as only the provider name is used
2156 
2157         final int pid = Binder.getCallingPid();
2158         final int uid = Binder.getCallingUid();
2159         final long identity = Binder.clearCallingIdentity();
2160         try {
2161             if (mBlacklist.isBlacklisted(packageName)) {
2162                 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " +
2163                         packageName);
2164                 return null;
2165             }
2166 
2167             if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) {
2168                 if (D) Log.d(TAG, "not returning last loc for no op app: " +
2169                         packageName);
2170                 return null;
2171             }
2172 
2173             synchronized (mLock) {
2174                 // Figure out the provider. Either its explicitly request (deprecated API's),
2175                 // or use the fused provider
2176                 String name = request.getProvider();
2177                 if (name == null) name = LocationManager.FUSED_PROVIDER;
2178                 LocationProviderInterface provider = mProvidersByName.get(name);
2179                 if (provider == null) return null;
2180 
2181                 if (!isAllowedByUserSettingsLocked(name, uid)) return null;
2182 
2183                 Location location;
2184                 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2185                     // Make sure that an app with coarse permissions can't get frequent location
2186                     // updates by calling LocationManager.getLastKnownLocation repeatedly.
2187                     location = mLastLocationCoarseInterval.get(name);
2188                 } else {
2189                     location = mLastLocation.get(name);
2190                 }
2191                 if (location == null) {
2192                     return null;
2193                 }
2194                 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2195                     Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2196                     if (noGPSLocation != null) {
2197                         return new Location(mLocationFudger.getOrCreate(noGPSLocation));
2198                     }
2199                 } else {
2200                     return new Location(location);
2201                 }
2202             }
2203             return null;
2204         } finally {
2205             Binder.restoreCallingIdentity(identity);
2206         }
2207     }
2208 
2209     @Override
requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, String packageName)2210     public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent,
2211             String packageName) {
2212         if (request == null) request = DEFAULT_LOCATION_REQUEST;
2213         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
2214         checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel);
2215         checkPendingIntent(intent);
2216         checkPackageName(packageName);
2217         checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
2218                 request.getProvider());
2219         LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel);
2220 
2221         if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent);
2222 
2223         // geo-fence manager uses the public location API, need to clear identity
2224         int uid = Binder.getCallingUid();
2225         // TODO: http://b/23822629
2226         if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) {
2227             // temporary measure until geofences work for secondary users
2228             Log.w(TAG, "proximity alerts are currently available only to the primary user");
2229             return;
2230         }
2231         long identity = Binder.clearCallingIdentity();
2232         try {
2233             mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel,
2234                     uid, packageName);
2235         } finally {
2236             Binder.restoreCallingIdentity(identity);
2237         }
2238     }
2239 
2240     @Override
removeGeofence(Geofence geofence, PendingIntent intent, String packageName)2241     public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) {
2242         checkPendingIntent(intent);
2243         checkPackageName(packageName);
2244 
2245         if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent);
2246 
2247         // geo-fence manager uses the public location API, need to clear identity
2248         long identity = Binder.clearCallingIdentity();
2249         try {
2250             mGeofenceManager.removeFence(geofence, intent);
2251         } finally {
2252             Binder.restoreCallingIdentity(identity);
2253         }
2254     }
2255 
2256 
2257     @Override
registerGnssStatusCallback(IGnssStatusListener callback, String packageName)2258     public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) {
2259         if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) {
2260             return false;
2261         }
2262 
2263         try {
2264             mGnssStatusProvider.registerGnssStatusCallback(callback);
2265         } catch (RemoteException e) {
2266             Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e);
2267             return false;
2268         }
2269         return true;
2270     }
2271 
2272     @Override
unregisterGnssStatusCallback(IGnssStatusListener callback)2273     public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
2274         synchronized (mLock) {
2275             try {
2276                 mGnssStatusProvider.unregisterGnssStatusCallback(callback);
2277             } catch (Exception e) {
2278                 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e);
2279             }
2280         }
2281     }
2282 
2283     @Override
addGnssMeasurementsListener( IGnssMeasurementsListener listener, String packageName)2284     public boolean addGnssMeasurementsListener(
2285             IGnssMeasurementsListener listener,
2286             String packageName) {
2287         if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
2288             return false;
2289         }
2290 
2291         synchronized (mLock) {
2292             Identity callerIdentity
2293                     = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2294             mGnssMeasurementsListeners.put(listener, callerIdentity);
2295             long identity = Binder.clearCallingIdentity();
2296             try {
2297                 if (isThrottlingExemptLocked(callerIdentity)
2298                         || isImportanceForeground(
2299                                 mActivityManager.getPackageImportance(packageName))) {
2300                     return mGnssMeasurementsProvider.addListener(listener);
2301                 }
2302             } finally {
2303                 Binder.restoreCallingIdentity(identity);
2304             }
2305 
2306             return true;
2307         }
2308     }
2309 
2310     @Override
removeGnssMeasurementsListener(IGnssMeasurementsListener listener)2311     public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
2312         if (mGnssMeasurementsProvider != null) {
2313             synchronized (mLock) {
2314                 mGnssMeasurementsListeners.remove(listener);
2315                 mGnssMeasurementsProvider.removeListener(listener);
2316             }
2317         }
2318     }
2319 
2320     @Override
addGnssNavigationMessageListener( IGnssNavigationMessageListener listener, String packageName)2321     public boolean addGnssNavigationMessageListener(
2322             IGnssNavigationMessageListener listener,
2323             String packageName) {
2324         if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) {
2325             return false;
2326         }
2327 
2328         synchronized (mLock) {
2329             Identity callerIdentity
2330                 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName);
2331             mGnssNavigationMessageListeners.put(listener, callerIdentity);
2332             long identity = Binder.clearCallingIdentity();
2333             try {
2334                 if (isThrottlingExemptLocked(callerIdentity)
2335                         || isImportanceForeground(
2336                                 mActivityManager.getPackageImportance(packageName))) {
2337                     return mGnssNavigationMessageProvider.addListener(listener);
2338                 }
2339             } finally {
2340                 Binder.restoreCallingIdentity(identity);
2341             }
2342 
2343             return true;
2344         }
2345     }
2346 
2347     @Override
removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)2348     public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) {
2349         if (mGnssNavigationMessageProvider != null) {
2350             synchronized (mLock) {
2351                 mGnssNavigationMessageListeners.remove(listener);
2352                 mGnssNavigationMessageProvider.removeListener(listener);
2353             }
2354         }
2355     }
2356 
2357     @Override
sendExtraCommand(String provider, String command, Bundle extras)2358     public boolean sendExtraCommand(String provider, String command, Bundle extras) {
2359         if (provider == null) {
2360             // throw NullPointerException to remain compatible with previous implementation
2361             throw new NullPointerException();
2362         }
2363         checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2364                 provider);
2365 
2366         // and check for ACCESS_LOCATION_EXTRA_COMMANDS
2367         if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
2368                 != PackageManager.PERMISSION_GRANTED)) {
2369             throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission");
2370         }
2371 
2372         synchronized (mLock) {
2373             LocationProviderInterface p = mProvidersByName.get(provider);
2374             if (p == null) return false;
2375 
2376             return p.sendExtraCommand(command, extras);
2377         }
2378     }
2379 
2380     @Override
sendNiResponse(int notifId, int userResponse)2381     public boolean sendNiResponse(int notifId, int userResponse) {
2382         if (Binder.getCallingUid() != Process.myUid()) {
2383             throw new SecurityException(
2384                     "calling sendNiResponse from outside of the system is not allowed");
2385         }
2386         try {
2387             return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
2388         } catch (RemoteException e) {
2389             Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
2390             return false;
2391         }
2392     }
2393 
2394     /**
2395      * @return null if the provider does not exist
2396      * @throws SecurityException if the provider is not allowed to be
2397      * accessed by the caller
2398      */
2399     @Override
getProviderProperties(String provider)2400     public ProviderProperties getProviderProperties(String provider) {
2401         if (mProvidersByName.get(provider) == null) {
2402             return null;
2403         }
2404 
2405         checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
2406                 provider);
2407 
2408         LocationProviderInterface p;
2409         synchronized (mLock) {
2410             p = mProvidersByName.get(provider);
2411         }
2412 
2413         if (p == null) return null;
2414         return p.getProperties();
2415     }
2416 
2417     /**
2418      * @return null if the provider does not exist
2419      * @throws SecurityException if the provider is not allowed to be
2420      * accessed by the caller
2421      */
2422     @Override
getNetworkProviderPackage()2423     public String getNetworkProviderPackage() {
2424         LocationProviderInterface p;
2425         synchronized (mLock) {
2426             if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) {
2427                 return null;
2428             }
2429             p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER);
2430         }
2431 
2432         if (p instanceof LocationProviderProxy) {
2433             return ((LocationProviderProxy) p).getConnectedPackageName();
2434         }
2435         return null;
2436     }
2437 
2438     @Override
isProviderEnabled(String provider)2439     public boolean isProviderEnabled(String provider) {
2440         // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
2441         // so we discourage its use
2442         if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
2443 
2444         int uid = Binder.getCallingUid();
2445         long identity = Binder.clearCallingIdentity();
2446         try {
2447             synchronized (mLock) {
2448                 LocationProviderInterface p = mProvidersByName.get(provider);
2449                 return p != null && isAllowedByUserSettingsLocked(provider, uid);
2450             }
2451         } finally {
2452             Binder.restoreCallingIdentity(identity);
2453         }
2454     }
2455 
2456     /**
2457      * Returns "true" if the UID belongs to a bound location provider.
2458      *
2459      * @param uid the uid
2460      * @return true if uid belongs to a bound location provider
2461      */
isUidALocationProvider(int uid)2462     private boolean isUidALocationProvider(int uid) {
2463         if (uid == Process.SYSTEM_UID) {
2464             return true;
2465         }
2466         if (mGeocodeProvider != null) {
2467             if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true;
2468         }
2469         for (LocationProviderProxy proxy : mProxyProviders) {
2470             if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true;
2471         }
2472         return false;
2473     }
2474 
checkCallerIsProvider()2475     private void checkCallerIsProvider() {
2476         if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER)
2477                 == PackageManager.PERMISSION_GRANTED) {
2478             return;
2479         }
2480 
2481         // Previously we only used the INSTALL_LOCATION_PROVIDER
2482         // check. But that is system or signature
2483         // protection level which is not flexible enough for
2484         // providers installed oustide the system image. So
2485         // also allow providers with a UID matching the
2486         // currently bound package name
2487 
2488         if (isUidALocationProvider(Binder.getCallingUid())) {
2489             return;
2490         }
2491 
2492         throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " +
2493                 "or UID of a currently bound location provider");
2494     }
2495 
2496     /**
2497      * Returns true if the given package belongs to the given uid.
2498      */
doesUidHavePackage(int uid, String packageName)2499     private boolean doesUidHavePackage(int uid, String packageName) {
2500         if (packageName == null) {
2501             return false;
2502         }
2503         String[] packageNames = mPackageManager.getPackagesForUid(uid);
2504         if (packageNames == null) {
2505             return false;
2506         }
2507         for (String name : packageNames) {
2508             if (packageName.equals(name)) {
2509                 return true;
2510             }
2511         }
2512         return false;
2513     }
2514 
2515     @Override
reportLocation(Location location, boolean passive)2516     public void reportLocation(Location location, boolean passive) {
2517         checkCallerIsProvider();
2518 
2519         if (!location.isComplete()) {
2520             Log.w(TAG, "Dropping incomplete location: " + location);
2521             return;
2522         }
2523 
2524         mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location);
2525         Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location);
2526         m.arg1 = (passive ? 1 : 0);
2527         mLocationHandler.sendMessageAtFrontOfQueue(m);
2528     }
2529 
2530 
shouldBroadcastSafe( Location loc, Location lastLoc, UpdateRecord record, long now)2531     private static boolean shouldBroadcastSafe(
2532             Location loc, Location lastLoc, UpdateRecord record, long now) {
2533         // Always broadcast the first update
2534         if (lastLoc == null) {
2535             return true;
2536         }
2537 
2538         // Check whether sufficient time has passed
2539         long minTime = record.mRealRequest.getFastestInterval();
2540         long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
2541                 / NANOS_PER_MILLI;
2542         if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
2543             return false;
2544         }
2545 
2546         // Check whether sufficient distance has been traveled
2547         double minDistance = record.mRealRequest.getSmallestDisplacement();
2548         if (minDistance > 0.0) {
2549             if (loc.distanceTo(lastLoc) <= minDistance) {
2550                 return false;
2551             }
2552         }
2553 
2554         // Check whether sufficient number of udpates is left
2555         if (record.mRealRequest.getNumUpdates() <= 0) {
2556             return false;
2557         }
2558 
2559         // Check whether the expiry date has passed
2560         return record.mRealRequest.getExpireAt() >= now;
2561     }
2562 
handleLocationChangedLocked(Location location, boolean passive)2563     private void handleLocationChangedLocked(Location location, boolean passive) {
2564         if (D) Log.d(TAG, "incoming location: " + location);
2565 
2566         long now = SystemClock.elapsedRealtime();
2567         String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider());
2568 
2569         // Skip if the provider is unknown.
2570         LocationProviderInterface p = mProvidersByName.get(provider);
2571         if (p == null) return;
2572 
2573         // Update last known locations
2574         Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2575         Location lastNoGPSLocation;
2576         Location lastLocation = mLastLocation.get(provider);
2577         if (lastLocation == null) {
2578             lastLocation = new Location(provider);
2579             mLastLocation.put(provider, lastLocation);
2580         } else {
2581             lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2582             if (noGPSLocation == null && lastNoGPSLocation != null) {
2583                 // New location has no no-GPS location: adopt last no-GPS location. This is set
2584                 // directly into location because we do not want to notify COARSE clients.
2585                 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation);
2586             }
2587         }
2588         lastLocation.set(location);
2589 
2590         // Update last known coarse interval location if enough time has passed.
2591         Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
2592         if (lastLocationCoarseInterval == null) {
2593             lastLocationCoarseInterval = new Location(location);
2594             mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
2595         }
2596         long timeDiffNanos = location.getElapsedRealtimeNanos()
2597                 - lastLocationCoarseInterval.getElapsedRealtimeNanos();
2598         if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
2599             lastLocationCoarseInterval.set(location);
2600         }
2601         // Don't ever return a coarse location that is more recent than the allowed update
2602         // interval (i.e. don't allow an app to keep registering and unregistering for
2603         // location updates to overcome the minimum interval).
2604         noGPSLocation =
2605                 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
2606 
2607         // Skip if there are no UpdateRecords for this provider.
2608         ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
2609         if (records == null || records.size() == 0) return;
2610 
2611         // Fetch coarse location
2612         Location coarseLocation = null;
2613         if (noGPSLocation != null) {
2614             coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
2615         }
2616 
2617         // Fetch latest status update time
2618         long newStatusUpdateTime = p.getStatusUpdateTime();
2619 
2620         // Get latest status
2621         Bundle extras = new Bundle();
2622         int status = p.getStatus(extras);
2623 
2624         ArrayList<Receiver> deadReceivers = null;
2625         ArrayList<UpdateRecord> deadUpdateRecords = null;
2626 
2627         // Broadcast location or status to all listeners
2628         for (UpdateRecord r : records) {
2629             Receiver receiver = r.mReceiver;
2630             boolean receiverDead = false;
2631 
2632             int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid);
2633             if (!isCurrentProfile(receiverUserId)
2634                     && !isUidALocationProvider(receiver.mIdentity.mUid)) {
2635                 if (D) {
2636                     Log.d(TAG, "skipping loc update for background user " + receiverUserId +
2637                             " (current user: " + mCurrentUserId + ", app: " +
2638                             receiver.mIdentity.mPackageName + ")");
2639                 }
2640                 continue;
2641             }
2642 
2643             if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) {
2644                 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " +
2645                         receiver.mIdentity.mPackageName);
2646                 continue;
2647             }
2648 
2649             if (!reportLocationAccessNoThrow(
2650                     receiver.mIdentity.mPid,
2651                     receiver.mIdentity.mUid,
2652                     receiver.mIdentity.mPackageName,
2653                     receiver.mAllowedResolutionLevel)) {
2654                 if (D) Log.d(TAG, "skipping loc update for no op app: " +
2655                         receiver.mIdentity.mPackageName);
2656                 continue;
2657             }
2658 
2659             Location notifyLocation;
2660             if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
2661                 notifyLocation = coarseLocation;  // use coarse location
2662             } else {
2663                 notifyLocation = lastLocation;  // use fine location
2664             }
2665             if (notifyLocation != null) {
2666                 Location lastLoc = r.mLastFixBroadcast;
2667                 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) {
2668                     if (lastLoc == null) {
2669                         lastLoc = new Location(notifyLocation);
2670                         r.mLastFixBroadcast = lastLoc;
2671                     } else {
2672                         lastLoc.set(notifyLocation);
2673                     }
2674                     if (!receiver.callLocationChangedLocked(notifyLocation)) {
2675                         Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
2676                         receiverDead = true;
2677                     }
2678                     r.mRealRequest.decrementNumUpdates();
2679                 }
2680             }
2681 
2682             long prevStatusUpdateTime = r.mLastStatusBroadcast;
2683             if ((newStatusUpdateTime > prevStatusUpdateTime) &&
2684                     (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) {
2685 
2686                 r.mLastStatusBroadcast = newStatusUpdateTime;
2687                 if (!receiver.callStatusChangedLocked(provider, status, extras)) {
2688                     receiverDead = true;
2689                     Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver);
2690                 }
2691             }
2692 
2693             // track expired records
2694             if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
2695                 if (deadUpdateRecords == null) {
2696                     deadUpdateRecords = new ArrayList<>();
2697                 }
2698                 deadUpdateRecords.add(r);
2699             }
2700             // track dead receivers
2701             if (receiverDead) {
2702                 if (deadReceivers == null) {
2703                     deadReceivers = new ArrayList<>();
2704                 }
2705                 if (!deadReceivers.contains(receiver)) {
2706                     deadReceivers.add(receiver);
2707                 }
2708             }
2709         }
2710 
2711         // remove dead records and receivers outside the loop
2712         if (deadReceivers != null) {
2713             for (Receiver receiver : deadReceivers) {
2714                 removeUpdatesLocked(receiver);
2715             }
2716         }
2717         if (deadUpdateRecords != null) {
2718             for (UpdateRecord r : deadUpdateRecords) {
2719                 r.disposeLocked(true);
2720             }
2721             applyRequirementsLocked(provider);
2722         }
2723     }
2724 
2725     private class LocationWorkerHandler extends Handler {
LocationWorkerHandler(Looper looper)2726         public LocationWorkerHandler(Looper looper) {
2727             super(looper, null, true);
2728         }
2729 
2730         @Override
handleMessage(Message msg)2731         public void handleMessage(Message msg) {
2732             switch (msg.what) {
2733                 case MSG_LOCATION_CHANGED:
2734                     handleLocationChanged((Location) msg.obj, msg.arg1 == 1);
2735                     break;
2736             }
2737         }
2738     }
2739 
isMockProvider(String provider)2740     private boolean isMockProvider(String provider) {
2741         synchronized (mLock) {
2742             return mMockProviders.containsKey(provider);
2743         }
2744     }
2745 
handleLocationChanged(Location location, boolean passive)2746     private void handleLocationChanged(Location location, boolean passive) {
2747         // create a working copy of the incoming Location so that the service can modify it without
2748         // disturbing the caller's copy
2749         Location myLocation = new Location(location);
2750         String provider = myLocation.getProvider();
2751 
2752         // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this
2753         // bit if location did not come from a mock provider because passive/fused providers can
2754         // forward locations from mock providers, and should not grant them legitimacy in doing so.
2755         if (!myLocation.isFromMockProvider() && isMockProvider(provider)) {
2756             myLocation.setIsFromMockProvider(true);
2757         }
2758 
2759         synchronized (mLock) {
2760             if (isAllowedByCurrentUserSettingsLocked(provider)) {
2761                 if (!passive) {
2762                     // notify passive provider of the new location
2763                     mPassiveProvider.updateLocation(myLocation);
2764                 }
2765                 handleLocationChangedLocked(myLocation, passive);
2766             }
2767         }
2768     }
2769 
2770     private final PackageMonitor mPackageMonitor = new PackageMonitor() {
2771         @Override
2772         public void onPackageDisappeared(String packageName, int reason) {
2773             // remove all receivers associated with this package name
2774             synchronized (mLock) {
2775                 ArrayList<Receiver> deadReceivers = null;
2776 
2777                 for (Receiver receiver : mReceivers.values()) {
2778                     if (receiver.mIdentity.mPackageName.equals(packageName)) {
2779                         if (deadReceivers == null) {
2780                             deadReceivers = new ArrayList<>();
2781                         }
2782                         deadReceivers.add(receiver);
2783                     }
2784                 }
2785 
2786                 // perform removal outside of mReceivers loop
2787                 if (deadReceivers != null) {
2788                     for (Receiver receiver : deadReceivers) {
2789                         removeUpdatesLocked(receiver);
2790                     }
2791                 }
2792             }
2793         }
2794     };
2795 
2796     // Geocoder
2797 
2798     @Override
geocoderIsPresent()2799     public boolean geocoderIsPresent() {
2800         return mGeocodeProvider != null;
2801     }
2802 
2803     @Override
getFromLocation(double latitude, double longitude, int maxResults, GeocoderParams params, List<Address> addrs)2804     public String getFromLocation(double latitude, double longitude, int maxResults,
2805             GeocoderParams params, List<Address> addrs) {
2806         if (mGeocodeProvider != null) {
2807             return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults,
2808                     params, addrs);
2809         }
2810         return null;
2811     }
2812 
2813 
2814     @Override
getFromLocationName(String locationName, double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude, int maxResults, GeocoderParams params, List<Address> addrs)2815     public String getFromLocationName(String locationName,
2816             double lowerLeftLatitude, double lowerLeftLongitude,
2817             double upperRightLatitude, double upperRightLongitude, int maxResults,
2818             GeocoderParams params, List<Address> addrs) {
2819 
2820         if (mGeocodeProvider != null) {
2821             return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude,
2822                     lowerLeftLongitude, upperRightLatitude, upperRightLongitude,
2823                     maxResults, params, addrs);
2824         }
2825         return null;
2826     }
2827 
2828     // Mock Providers
2829 
canCallerAccessMockLocation(String opPackageName)2830     private boolean canCallerAccessMockLocation(String opPackageName) {
2831         return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(),
2832                 opPackageName) == AppOpsManager.MODE_ALLOWED;
2833     }
2834 
2835     @Override
addTestProvider(String name, ProviderProperties properties, String opPackageName)2836     public void addTestProvider(String name, ProviderProperties properties, String opPackageName) {
2837         if (!canCallerAccessMockLocation(opPackageName)) {
2838             return;
2839         }
2840 
2841         if (LocationManager.PASSIVE_PROVIDER.equals(name)) {
2842             throw new IllegalArgumentException("Cannot mock the passive location provider");
2843         }
2844 
2845         long identity = Binder.clearCallingIdentity();
2846         synchronized (mLock) {
2847             // remove the real provider if we are replacing GPS or network provider
2848             if (LocationManager.GPS_PROVIDER.equals(name)
2849                     || LocationManager.NETWORK_PROVIDER.equals(name)
2850                     || LocationManager.FUSED_PROVIDER.equals(name)) {
2851                 LocationProviderInterface p = mProvidersByName.get(name);
2852                 if (p != null) {
2853                     removeProviderLocked(p);
2854                 }
2855             }
2856             addTestProviderLocked(name, properties);
2857             updateProvidersLocked();
2858         }
2859         Binder.restoreCallingIdentity(identity);
2860     }
2861 
addTestProviderLocked(String name, ProviderProperties properties)2862     private void addTestProviderLocked(String name, ProviderProperties properties) {
2863         if (mProvidersByName.get(name) != null) {
2864             throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
2865         }
2866         MockProvider provider = new MockProvider(name, this, properties);
2867         addProviderLocked(provider);
2868         mMockProviders.put(name, provider);
2869         mLastLocation.put(name, null);
2870         mLastLocationCoarseInterval.put(name, null);
2871     }
2872 
2873     @Override
removeTestProvider(String provider, String opPackageName)2874     public void removeTestProvider(String provider, String opPackageName) {
2875         if (!canCallerAccessMockLocation(opPackageName)) {
2876             return;
2877         }
2878 
2879         synchronized (mLock) {
2880 
2881             // These methods can't be called after removing the test provider, so first make sure
2882             // we don't leave anything dangling.
2883             clearTestProviderEnabled(provider, opPackageName);
2884             clearTestProviderLocation(provider, opPackageName);
2885             clearTestProviderStatus(provider, opPackageName);
2886 
2887             MockProvider mockProvider = mMockProviders.remove(provider);
2888             if (mockProvider == null) {
2889                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2890             }
2891             long identity = Binder.clearCallingIdentity();
2892             removeProviderLocked(mProvidersByName.get(provider));
2893 
2894             // reinstate real provider if available
2895             LocationProviderInterface realProvider = mRealProviders.get(provider);
2896             if (realProvider != null) {
2897                 addProviderLocked(realProvider);
2898             }
2899             mLastLocation.put(provider, null);
2900             mLastLocationCoarseInterval.put(provider, null);
2901             updateProvidersLocked();
2902             Binder.restoreCallingIdentity(identity);
2903         }
2904     }
2905 
2906     @Override
setTestProviderLocation(String provider, Location loc, String opPackageName)2907     public void setTestProviderLocation(String provider, Location loc, String opPackageName) {
2908         if (!canCallerAccessMockLocation(opPackageName)) {
2909             return;
2910         }
2911 
2912         synchronized (mLock) {
2913             MockProvider mockProvider = mMockProviders.get(provider);
2914             if (mockProvider == null) {
2915                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2916             }
2917 
2918             // Ensure that the location is marked as being mock. There's some logic to do this in
2919             // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107).
2920             Location mock = new Location(loc);
2921             mock.setIsFromMockProvider(true);
2922 
2923             if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) {
2924                 // The location has an explicit provider that is different from the mock provider
2925                 // name. The caller may be trying to fool us via bug 33091107.
2926                 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(),
2927                         provider + "!=" + loc.getProvider());
2928             }
2929 
2930             // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required
2931             long identity = Binder.clearCallingIdentity();
2932             mockProvider.setLocation(mock);
2933             Binder.restoreCallingIdentity(identity);
2934         }
2935     }
2936 
2937     @Override
clearTestProviderLocation(String provider, String opPackageName)2938     public void clearTestProviderLocation(String provider, String opPackageName) {
2939         if (!canCallerAccessMockLocation(opPackageName)) {
2940             return;
2941         }
2942 
2943         synchronized (mLock) {
2944             MockProvider mockProvider = mMockProviders.get(provider);
2945             if (mockProvider == null) {
2946                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2947             }
2948             mockProvider.clearLocation();
2949         }
2950     }
2951 
2952     @Override
setTestProviderEnabled(String provider, boolean enabled, String opPackageName)2953     public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) {
2954         if (!canCallerAccessMockLocation(opPackageName)) {
2955             return;
2956         }
2957 
2958         synchronized (mLock) {
2959             MockProvider mockProvider = mMockProviders.get(provider);
2960             if (mockProvider == null) {
2961                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2962             }
2963             long identity = Binder.clearCallingIdentity();
2964             if (enabled) {
2965                 mockProvider.enable();
2966                 mEnabledProviders.add(provider);
2967                 mDisabledProviders.remove(provider);
2968             } else {
2969                 mockProvider.disable();
2970                 mEnabledProviders.remove(provider);
2971                 mDisabledProviders.add(provider);
2972             }
2973             updateProvidersLocked();
2974             Binder.restoreCallingIdentity(identity);
2975         }
2976     }
2977 
2978     @Override
clearTestProviderEnabled(String provider, String opPackageName)2979     public void clearTestProviderEnabled(String provider, String opPackageName) {
2980         if (!canCallerAccessMockLocation(opPackageName)) {
2981             return;
2982         }
2983 
2984         synchronized (mLock) {
2985             MockProvider mockProvider = mMockProviders.get(provider);
2986             if (mockProvider == null) {
2987                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
2988             }
2989             long identity = Binder.clearCallingIdentity();
2990             mEnabledProviders.remove(provider);
2991             mDisabledProviders.remove(provider);
2992             updateProvidersLocked();
2993             Binder.restoreCallingIdentity(identity);
2994         }
2995     }
2996 
2997     @Override
setTestProviderStatus(String provider, int status, Bundle extras, long updateTime, String opPackageName)2998     public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime,
2999             String opPackageName) {
3000         if (!canCallerAccessMockLocation(opPackageName)) {
3001             return;
3002         }
3003 
3004         synchronized (mLock) {
3005             MockProvider mockProvider = mMockProviders.get(provider);
3006             if (mockProvider == null) {
3007                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3008             }
3009             mockProvider.setStatus(status, extras, updateTime);
3010         }
3011     }
3012 
3013     @Override
clearTestProviderStatus(String provider, String opPackageName)3014     public void clearTestProviderStatus(String provider, String opPackageName) {
3015         if (!canCallerAccessMockLocation(opPackageName)) {
3016             return;
3017         }
3018 
3019         synchronized (mLock) {
3020             MockProvider mockProvider = mMockProviders.get(provider);
3021             if (mockProvider == null) {
3022                 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown");
3023             }
3024             mockProvider.clearStatus();
3025         }
3026     }
3027 
log(String log)3028     private void log(String log) {
3029         if (Log.isLoggable(TAG, Log.VERBOSE)) {
3030             Slog.d(TAG, log);
3031         }
3032     }
3033 
3034     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)3035     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3036         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
3037 
3038         synchronized (mLock) {
3039             pw.println("Current Location Manager state:");
3040             pw.println("  Location Listeners:");
3041             for (Receiver receiver : mReceivers.values()) {
3042                 pw.println("    " + receiver);
3043             }
3044             pw.println("  Active Records by Provider:");
3045             for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) {
3046                 pw.println("    " + entry.getKey() + ":");
3047                 for (UpdateRecord record : entry.getValue()) {
3048                     pw.println("      " + record);
3049                 }
3050             }
3051             pw.println("  Overlay Provider Packages:");
3052             for (LocationProviderInterface provider : mProviders) {
3053                 if (provider instanceof LocationProviderProxy) {
3054                     pw.println("    " + provider.getName() + ": "
3055                             + ((LocationProviderProxy) provider).getConnectedPackageName());
3056                 }
3057             }
3058             pw.println("  Historical Records by Provider:");
3059             for (Map.Entry<PackageProviderKey, PackageStatistics> entry
3060                     : mRequestStatistics.statistics.entrySet()) {
3061                 PackageProviderKey key = entry.getKey();
3062                 PackageStatistics stats = entry.getValue();
3063                 pw.println("    " + key.packageName + ": " + key.providerName + ": " + stats);
3064             }
3065             pw.println("  Last Known Locations:");
3066             for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) {
3067                 String provider = entry.getKey();
3068                 Location location = entry.getValue();
3069                 pw.println("    " + provider + ": " + location);
3070             }
3071 
3072             pw.println("  Last Known Locations Coarse Intervals:");
3073             for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
3074                 String provider = entry.getKey();
3075                 Location location = entry.getValue();
3076                 pw.println("    " + provider + ": " + location);
3077             }
3078 
3079             mGeofenceManager.dump(pw);
3080 
3081             if (mEnabledProviders.size() > 0) {
3082                 pw.println("  Enabled Providers:");
3083                 for (String i : mEnabledProviders) {
3084                     pw.println("    " + i);
3085                 }
3086 
3087             }
3088             if (mDisabledProviders.size() > 0) {
3089                 pw.println("  Disabled Providers:");
3090                 for (String i : mDisabledProviders) {
3091                     pw.println("    " + i);
3092                 }
3093             }
3094             pw.append("  ");
3095             mBlacklist.dump(pw);
3096             if (mMockProviders.size() > 0) {
3097                 pw.println("  Mock Providers:");
3098                 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) {
3099                     i.getValue().dump(pw, "      ");
3100                 }
3101             }
3102 
3103             if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
3104                 pw.println("  Throttling Whitelisted Packages:");
3105                 for (String packageName : mBackgroundThrottlePackageWhitelist) {
3106                     pw.println("    " + packageName);
3107                 }
3108             }
3109 
3110             pw.append("  fudger: ");
3111             mLocationFudger.dump(fd, pw,  args);
3112 
3113             if (args.length > 0 && "short".equals(args[0])) {
3114                 return;
3115             }
3116             for (LocationProviderInterface provider: mProviders) {
3117                 pw.print(provider.getName() + " Internal State");
3118                 if (provider instanceof LocationProviderProxy) {
3119                     LocationProviderProxy proxy = (LocationProviderProxy) provider;
3120                     pw.print(" (" + proxy.getConnectedPackageName() + ")");
3121                 }
3122                 pw.println(":");
3123                 provider.dump(fd, pw, args);
3124             }
3125             if (mGnssBatchingInProgress) {
3126                 pw.println("  GNSS batching in progress");
3127             }
3128         }
3129     }
3130 }
3131