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