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