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