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