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