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