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