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