Home | History | Annotate | Download | only in server
      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 
    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 
    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 
    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      */
    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      */
    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      */
    503     private boolean isCurrentProfile(int userId) {
    504         synchronized (mLock) {
    505             return ArrayUtils.contains(mCurrentUserProfiles, userId);
    506         }
    507     }
    508 
    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 
    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      */
    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 
    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 
    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
    826         public boolean equals(Object otherObj) {
    827             return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey);
    828         }
    829 
    830         @Override
    831         public int hashCode() {
    832             return mKey.hashCode();
    833         }
    834 
    835         @Override
    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          */
    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          */
    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 
    930         public boolean isListener() {
    931             return mListener != null;
    932         }
    933 
    934         public boolean isPendingIntent() {
    935             return mPendingIntent != null;
    936         }
    937 
    938         public ILocationListener getListener() {
    939             if (mListener != null) {
    940                 return mListener;
    941             }
    942             throw new IllegalStateException("Request for non-existent listener");
    943         }
    944 
    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 
    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 
   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
   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
   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
   1078         private void incrementPendingBroadcastsLocked() {
   1079             if (mPendingBroadcasts++ == 0) {
   1080                 mWakeLock.acquire();
   1081             }
   1082         }
   1083 
   1084         private void decrementPendingBroadcastsLocked() {
   1085             if (--mPendingBroadcasts == 0) {
   1086                 if (mWakeLock.isHeld()) {
   1087                     mWakeLock.release();
   1088                 }
   1089             }
   1090         }
   1091 
   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
   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
   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      */
   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
   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
   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 
   1202         public LinkedCallback(@NonNull IBatchedLocationCallback callback) {
   1203             mCallback = callback;
   1204         }
   1205 
   1206         @NonNull
   1207         public IBatchedLocationCallback getUnderlyingListener() {
   1208             return mCallback;
   1209         }
   1210 
   1211         @Override
   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
   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
   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
   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
   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
   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 
   1318     private void addProviderLocked(LocationProviderInterface provider) {
   1319         mProviders.add(provider);
   1320         mProvidersByName.put(provider.getName(), provider);
   1321     }
   1322 
   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      */
   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      */
   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      */
   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      */
   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      */
   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      */
   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      */
   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      */
   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      */
   1483     private void checkDeviceStatsAllowed() {
   1484         mContext.enforceCallingOrSelfPermission(
   1485                 android.Manifest.permission.UPDATE_DEVICE_STATS, null);
   1486     }
   1487 
   1488     private void checkUpdateAppOpsAllowed() {
   1489         mContext.enforceCallingOrSelfPermission(
   1490                 android.Manifest.permission.UPDATE_APP_OPS_STATS, null);
   1491     }
   1492 
   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 
   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 
   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
   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
   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
   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 
   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
   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 
   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 
   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 
   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
   1794     public String[] getBackgroundThrottlingWhitelist() {
   1795         synchronized (mLock) {
   1796             return mBackgroundThrottlePackageWhitelist.toArray(
   1797                 new String[mBackgroundThrottlePackageWhitelist.size()]);
   1798         }
   1799     }
   1800 
   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 
   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          */
   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          */
   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
   1895         public String toString() {
   1896             return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName
   1897                     + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" : " background")
   1898                     + ")" + " " + mRealRequest + "]";
   1899         }
   1900     }
   1901 
   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 
   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      */
   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 
   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 
   1980     private void checkPendingIntent(PendingIntent intent) {
   1981         if (intent == null) {
   1982             throw new IllegalArgumentException("invalid pending intent: " + intent);
   1983         }
   1984     }
   1985 
   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
   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 
   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
   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 
   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 
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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
   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      */
   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 
   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      */
   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
   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 
   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 
   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 {
   2726         public LocationWorkerHandler(Looper looper) {
   2727             super(looper, null, true);
   2728         }
   2729 
   2730         @Override
   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 
   2740     private boolean isMockProvider(String provider) {
   2741         synchronized (mLock) {
   2742             return mMockProviders.containsKey(provider);
   2743         }
   2744     }
   2745 
   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
   2799     public boolean geocoderIsPresent() {
   2800         return mGeocodeProvider != null;
   2801     }
   2802 
   2803     @Override
   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
   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 
   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
   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 
   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
   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
   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
   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
   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
   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
   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
   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 
   3028     private void log(String log) {
   3029         if (Log.isLoggable(TAG, Log.VERBOSE)) {
   3030             Slog.d(TAG, log);
   3031         }
   3032     }
   3033 
   3034     @Override
   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