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