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