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