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