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