1 /* 2 * Copyright (C) 2020 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.location; 18 19 import static android.Manifest.permission.ACCESS_FINE_LOCATION; 20 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; 21 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; 22 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 23 import static android.location.LocationManager.FUSED_PROVIDER; 24 import static android.location.LocationManager.GPS_PROVIDER; 25 import static android.location.LocationManager.NETWORK_PROVIDER; 26 import static android.location.LocationManager.PASSIVE_PROVIDER; 27 import static android.os.PowerManager.locationPowerSaveModeToString; 28 29 import static com.android.server.location.CallerIdentity.PERMISSION_COARSE; 30 import static com.android.server.location.CallerIdentity.PERMISSION_FINE; 31 import static com.android.server.location.UserInfoHelper.UserListener.CURRENT_USER_CHANGED; 32 import static com.android.server.location.UserInfoHelper.UserListener.USER_STARTED; 33 import static com.android.server.location.UserInfoHelper.UserListener.USER_STOPPED; 34 35 import static java.util.concurrent.TimeUnit.NANOSECONDS; 36 37 import android.Manifest; 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.annotation.UserIdInt; 41 import android.app.ActivityManager; 42 import android.app.AppOpsManager; 43 import android.app.PendingIntent; 44 import android.content.BroadcastReceiver; 45 import android.content.Context; 46 import android.content.Intent; 47 import android.content.IntentFilter; 48 import android.location.Address; 49 import android.location.Criteria; 50 import android.location.GeocoderParams; 51 import android.location.Geofence; 52 import android.location.GnssCapabilities; 53 import android.location.GnssMeasurementCorrections; 54 import android.location.GnssRequest; 55 import android.location.IBatchedLocationCallback; 56 import android.location.IGnssAntennaInfoListener; 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.Location; 64 import android.location.LocationManager; 65 import android.location.LocationManagerInternal; 66 import android.location.LocationProvider; 67 import android.location.LocationRequest; 68 import android.location.LocationTime; 69 import android.os.Binder; 70 import android.os.Build; 71 import android.os.Bundle; 72 import android.os.CancellationSignal; 73 import android.os.Handler; 74 import android.os.IBinder; 75 import android.os.ICancellationSignal; 76 import android.os.ParcelFileDescriptor; 77 import android.os.PowerManager; 78 import android.os.PowerManager.ServiceType; 79 import android.os.PowerManagerInternal; 80 import android.os.Process; 81 import android.os.RemoteException; 82 import android.os.SystemClock; 83 import android.os.UserHandle; 84 import android.os.WorkSource; 85 import android.os.WorkSource.WorkChain; 86 import android.stats.location.LocationStatsEnums; 87 import android.text.TextUtils; 88 import android.util.EventLog; 89 import android.util.Log; 90 import android.util.SparseArray; 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.DumpUtils; 98 import com.android.internal.util.IndentingPrintWriter; 99 import com.android.internal.util.Preconditions; 100 import com.android.server.FgThread; 101 import com.android.server.LocalServices; 102 import com.android.server.PendingIntentUtils; 103 import com.android.server.SystemService; 104 import com.android.server.location.AbstractLocationProvider.State; 105 import com.android.server.location.CallerIdentity.PermissionLevel; 106 import com.android.server.location.LocationRequestStatistics.PackageProviderKey; 107 import com.android.server.location.LocationRequestStatistics.PackageStatistics; 108 import com.android.server.location.UserInfoHelper.UserListener.UserChange; 109 import com.android.server.location.gnss.GnssManagerService; 110 import com.android.server.pm.permission.PermissionManagerServiceInternal; 111 112 import java.io.ByteArrayOutputStream; 113 import java.io.FileDescriptor; 114 import java.io.PrintStream; 115 import java.io.PrintWriter; 116 import java.util.ArrayList; 117 import java.util.Collections; 118 import java.util.HashMap; 119 import java.util.HashSet; 120 import java.util.List; 121 import java.util.Map; 122 import java.util.Map.Entry; 123 import java.util.Objects; 124 import java.util.Set; 125 import java.util.TreeMap; 126 import java.util.concurrent.CopyOnWriteArrayList; 127 128 /** 129 * The service class that manages LocationProviders and issues location 130 * updates and alerts. 131 */ 132 public class LocationManagerService extends ILocationManager.Stub { 133 134 /** 135 * Controls lifecycle of LocationManagerService. 136 */ 137 public static class Lifecycle extends SystemService { 138 139 private final UserInfoHelper mUserInfoHelper; 140 private final LocationManagerService mService; 141 Lifecycle(Context context)142 public Lifecycle(Context context) { 143 super(context); 144 mUserInfoHelper = new SystemUserInfoHelper(context); 145 mService = new LocationManagerService(context, mUserInfoHelper); 146 } 147 148 @Override onStart()149 public void onStart() { 150 // enable client caches by doing the first invalidate 151 LocationManager.invalidateLocalLocationEnabledCaches(); 152 153 publishBinderService(Context.LOCATION_SERVICE, mService); 154 // disable caching for whatever process contains LocationManagerService 155 ((LocationManager) mService.mContext.getSystemService(LocationManager.class)) 156 .disableLocalLocationEnabledCaches(); 157 } 158 159 @Override onBootPhase(int phase)160 public void onBootPhase(int phase) { 161 if (phase == PHASE_SYSTEM_SERVICES_READY) { 162 // the location service must be functioning after this boot phase 163 mService.onSystemReady(); 164 } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 165 // some providers rely on third party code, so we wait to initialize 166 // providers until third party code is allowed to run 167 mService.onSystemThirdPartyAppsCanStart(); 168 } 169 } 170 171 @Override onUserStarting(TargetUser user)172 public void onUserStarting(TargetUser user) { 173 mUserInfoHelper.dispatchOnUserStarted(user.getUserIdentifier()); 174 } 175 176 @Override onUserSwitching(TargetUser from, TargetUser to)177 public void onUserSwitching(TargetUser from, TargetUser to) { 178 mUserInfoHelper.dispatchOnCurrentUserChanged(from.getUserIdentifier(), 179 to.getUserIdentifier()); 180 } 181 182 @Override onUserStopped(TargetUser user)183 public void onUserStopped(TargetUser user) { 184 mUserInfoHelper.dispatchOnUserStopped(user.getUserIdentifier()); 185 } 186 187 private static class SystemUserInfoHelper extends UserInfoHelper { 188 SystemUserInfoHelper(Context context)189 SystemUserInfoHelper(Context context) { 190 super(context); 191 } 192 } 193 } 194 195 public static final String TAG = "LocationManagerService"; 196 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); 197 198 private static final String WAKELOCK_KEY = "*location*"; 199 200 private static final String NETWORK_LOCATION_SERVICE_ACTION = 201 "com.android.location.service.v3.NetworkLocationProvider"; 202 private static final String FUSED_LOCATION_SERVICE_ACTION = 203 "com.android.location.service.FusedLocationProvider"; 204 205 // The maximum interval a location request can have and still be considered "high power". 206 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000; 207 208 // The fastest interval that applications can receive coarse locations 209 private static final long FASTEST_COARSE_INTERVAL_MS = 10 * 60 * 1000; 210 211 // maximum age of a location before it is no longer considered "current" 212 private static final long MAX_CURRENT_LOCATION_AGE_MS = 10 * 1000; 213 214 // Location Providers may sometimes deliver location updates 215 // slightly faster that requested - provide grace period so 216 // we don't unnecessarily filter events that are otherwise on 217 // time 218 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100; 219 220 private static final String ATTRIBUTION_TAG = "LocationService"; 221 222 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest(); 223 224 private final Object mLock = new Object(); 225 private final Context mContext; 226 private final Handler mHandler; 227 private final LocalService mLocalService; 228 private final AppOpsHelper mAppOpsHelper; 229 private final UserInfoHelper mUserInfoHelper; 230 private final SettingsHelper mSettingsHelper; 231 private final AppForegroundHelper mAppForegroundHelper; 232 private final LocationUsageLogger mLocationUsageLogger; 233 234 @Nullable private volatile GnssManagerService mGnssManagerService = null; 235 236 private final PassiveLocationProviderManager mPassiveManager; 237 238 private PowerManager mPowerManager; 239 240 private GeofenceManager mGeofenceManager; 241 private GeocoderProxy mGeocodeProvider; 242 243 @GuardedBy("mLock") 244 private String mExtraLocationControllerPackage; 245 @GuardedBy("mLock") 246 private boolean mExtraLocationControllerPackageEnabled; 247 248 // @GuardedBy("mLock") 249 // hold lock for write or to prevent write, no lock for read 250 private final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers = 251 new CopyOnWriteArrayList<>(); 252 253 @GuardedBy("mLock") 254 private final HashMap<Object, Receiver> mReceivers = new HashMap<>(); 255 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider = 256 new HashMap<>(); 257 258 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics(); 259 260 @GuardedBy("mLock") 261 @PowerManager.LocationPowerSaveMode 262 private int mBatterySaverMode; 263 LocationManagerService(Context context, UserInfoHelper userInfoHelper)264 private LocationManagerService(Context context, UserInfoHelper userInfoHelper) { 265 mContext = context.createAttributionContext(ATTRIBUTION_TAG); 266 mHandler = FgThread.getHandler(); 267 mLocalService = new LocalService(); 268 269 LocalServices.addService(LocationManagerInternal.class, mLocalService); 270 271 mAppOpsHelper = new AppOpsHelper(mContext); 272 mUserInfoHelper = userInfoHelper; 273 mSettingsHelper = new SettingsHelper(mContext, mHandler); 274 mAppForegroundHelper = new AppForegroundHelper(mContext); 275 mLocationUsageLogger = new LocationUsageLogger(); 276 277 // set up passive provider - we do this early because it has no dependencies on system 278 // services or external code that isn't ready yet, and because this allows the variable to 279 // be final. other more complex providers are initialized later, when system services are 280 // ready 281 mPassiveManager = new PassiveLocationProviderManager(); 282 mProviderManagers.add(mPassiveManager); 283 mPassiveManager.setRealProvider(new PassiveProvider(mContext)); 284 285 // Let the package manager query which are the default location 286 // providers as they get certain permissions granted by default. 287 PermissionManagerServiceInternal permissionManagerInternal = LocalServices.getService( 288 PermissionManagerServiceInternal.class); 289 permissionManagerInternal.setLocationPackagesProvider( 290 userId -> mContext.getResources().getStringArray( 291 com.android.internal.R.array.config_locationProviderPackageNames)); 292 permissionManagerInternal.setLocationExtraPackagesProvider( 293 userId -> mContext.getResources().getStringArray( 294 com.android.internal.R.array.config_locationExtraPackageNames)); 295 296 // most startup is deferred until systemReady() 297 } 298 onSystemReady()299 private void onSystemReady() { 300 mAppOpsHelper.onSystemReady(); 301 mUserInfoHelper.onSystemReady(); 302 mSettingsHelper.onSystemReady(); 303 mAppForegroundHelper.onSystemReady(); 304 305 synchronized (mLock) { 306 mPowerManager = mContext.getSystemService(PowerManager.class); 307 mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper); 308 309 // add listeners 310 mContext.getPackageManager().addOnPermissionsChangeListener( 311 uid -> { 312 // listener invoked on ui thread, move to our thread to reduce risk of 313 // blocking ui thread 314 mHandler.post(() -> { 315 synchronized (mLock) { 316 onPermissionsChangedLocked(); 317 } 318 }); 319 }); 320 321 LocalServices.getService(PowerManagerInternal.class).registerLowPowerModeObserver( 322 ServiceType.LOCATION, 323 state -> { 324 // listener invoked on ui thread, move to our thread to reduce risk of 325 // blocking ui thread 326 mHandler.post(() -> { 327 synchronized (mLock) { 328 onBatterySaverModeChangedLocked(state.locationMode); 329 } 330 }); 331 }); 332 mBatterySaverMode = mPowerManager.getLocationPowerSaveMode(); 333 334 mAppOpsHelper.addListener(this::onAppOpChanged); 335 336 mSettingsHelper.addOnLocationEnabledChangedListener(this::onLocationModeChanged); 337 mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener( 338 this::onBackgroundThrottleIntervalChanged); 339 mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener( 340 this::onBackgroundThrottleWhitelistChanged); 341 mSettingsHelper.addOnIgnoreSettingsPackageWhitelistChangedListener( 342 this::onIgnoreSettingsWhitelistChanged); 343 344 PackageMonitor packageMonitor = new PackageMonitor() { 345 @Override 346 public void onPackageDisappeared(String packageName, int reason) { 347 synchronized (mLock) { 348 LocationManagerService.this.onPackageDisappeared(packageName); 349 } 350 } 351 }; 352 packageMonitor.register(mContext, null, true, mHandler); 353 354 mUserInfoHelper.addListener(this::onUserChanged); 355 356 mAppForegroundHelper.addListener(this::onAppForegroundChanged); 357 358 IntentFilter screenIntentFilter = new IntentFilter(); 359 screenIntentFilter.addAction(Intent.ACTION_SCREEN_OFF); 360 screenIntentFilter.addAction(Intent.ACTION_SCREEN_ON); 361 mContext.registerReceiverAsUser(new BroadcastReceiver() { 362 @Override 363 public void onReceive(Context context, Intent intent) { 364 if (Intent.ACTION_SCREEN_ON.equals(intent.getAction()) 365 || Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { 366 onScreenStateChanged(); 367 } 368 } 369 }, UserHandle.ALL, screenIntentFilter, null, mHandler); 370 371 // initialize the current users. we would get the user started notifications for these 372 // users eventually anyways, but this takes care of it as early as possible. 373 for (int userId: mUserInfoHelper.getCurrentUserIds()) { 374 onUserChanged(userId, USER_STARTED); 375 } 376 } 377 } 378 onSystemThirdPartyAppsCanStart()379 private void onSystemThirdPartyAppsCanStart() { 380 synchronized (mLock) { 381 // prepare providers 382 initializeProvidersLocked(); 383 } 384 385 // initialize gnss last because it has no awareness of boot phases and blindly assumes that 386 // all other location providers are loaded at initialization 387 initializeGnss(); 388 } 389 onAppOpChanged(String packageName)390 private void onAppOpChanged(String packageName) { 391 synchronized (mLock) { 392 for (Receiver receiver : mReceivers.values()) { 393 if (receiver.mCallerIdentity.packageName.equals(packageName)) { 394 receiver.updateMonitoring(true); 395 } 396 } 397 398 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size()); 399 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 400 String provider = entry.getKey(); 401 for (UpdateRecord record : entry.getValue()) { 402 if (record.mReceiver.mCallerIdentity.packageName.equals(packageName)) { 403 affectedProviders.add(provider); 404 } 405 } 406 } 407 for (String provider : affectedProviders) { 408 applyRequirementsLocked(provider); 409 } 410 } 411 } 412 413 @GuardedBy("mLock") onPermissionsChangedLocked()414 private void onPermissionsChangedLocked() { 415 for (LocationProviderManager manager : mProviderManagers) { 416 applyRequirementsLocked(manager); 417 } 418 } 419 420 @GuardedBy("mLock") onBatterySaverModeChangedLocked(int newLocationMode)421 private void onBatterySaverModeChangedLocked(int newLocationMode) { 422 if (mBatterySaverMode == newLocationMode) { 423 return; 424 } 425 426 if (D) { 427 Log.d(TAG, 428 "Battery Saver location mode changed from " 429 + locationPowerSaveModeToString(mBatterySaverMode) + " to " 430 + locationPowerSaveModeToString(newLocationMode)); 431 } 432 433 mBatterySaverMode = newLocationMode; 434 435 for (LocationProviderManager manager : mProviderManagers) { 436 applyRequirementsLocked(manager); 437 } 438 } 439 onScreenStateChanged()440 private void onScreenStateChanged() { 441 synchronized (mLock) { 442 if (mBatterySaverMode == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF) { 443 for (LocationProviderManager manager : mProviderManagers) { 444 applyRequirementsLocked(manager); 445 } 446 } 447 } 448 } 449 onLocationModeChanged(int userId)450 private void onLocationModeChanged(int userId) { 451 boolean enabled = mSettingsHelper.isLocationEnabled(userId); 452 LocationManager.invalidateLocalLocationEnabledCaches(); 453 454 if (D) { 455 Log.d(TAG, "[u" + userId + "] location enabled = " + enabled); 456 } 457 458 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION) 459 .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled) 460 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) 461 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 462 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); 463 464 synchronized (mLock) { 465 for (LocationProviderManager manager : mProviderManagers) { 466 manager.onEnabledChangedLocked(userId); 467 } 468 } 469 } 470 onPackageDisappeared(String packageName)471 private void onPackageDisappeared(String packageName) { 472 synchronized (mLock) { 473 ArrayList<Receiver> deadReceivers = null; 474 475 for (Receiver receiver : mReceivers.values()) { 476 if (receiver.mCallerIdentity.packageName.equals(packageName)) { 477 if (deadReceivers == null) { 478 deadReceivers = new ArrayList<>(); 479 } 480 deadReceivers.add(receiver); 481 } 482 } 483 484 // perform removal outside of mReceivers loop 485 if (deadReceivers != null) { 486 for (Receiver receiver : deadReceivers) { 487 removeUpdatesLocked(receiver); 488 } 489 } 490 } 491 } 492 onAppForegroundChanged(int uid, boolean foreground)493 private void onAppForegroundChanged(int uid, boolean foreground) { 494 synchronized (mLock) { 495 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size()); 496 for (Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 497 String provider = entry.getKey(); 498 for (UpdateRecord record : entry.getValue()) { 499 if (record.mReceiver.mCallerIdentity.uid == uid 500 && record.mIsForegroundUid != foreground) { 501 record.updateForeground(foreground); 502 503 if (!isThrottlingExempt(record.mReceiver.mCallerIdentity)) { 504 affectedProviders.add(provider); 505 } 506 } 507 } 508 } 509 for (String provider : affectedProviders) { 510 applyRequirementsLocked(provider); 511 } 512 } 513 } 514 onBackgroundThrottleIntervalChanged()515 private void onBackgroundThrottleIntervalChanged() { 516 synchronized (mLock) { 517 for (LocationProviderManager manager : mProviderManagers) { 518 applyRequirementsLocked(manager); 519 } 520 } 521 } 522 onBackgroundThrottleWhitelistChanged()523 private void onBackgroundThrottleWhitelistChanged() { 524 synchronized (mLock) { 525 for (LocationProviderManager manager : mProviderManagers) { 526 applyRequirementsLocked(manager); 527 } 528 } 529 } 530 onIgnoreSettingsWhitelistChanged()531 private void onIgnoreSettingsWhitelistChanged() { 532 synchronized (mLock) { 533 for (LocationProviderManager manager : mProviderManagers) { 534 applyRequirementsLocked(manager); 535 } 536 } 537 } 538 539 @GuardedBy("mLock") initializeProvidersLocked()540 private void initializeProvidersLocked() { 541 LocationProviderProxy networkProvider = LocationProviderProxy.createAndRegister( 542 mContext, 543 NETWORK_LOCATION_SERVICE_ACTION, 544 com.android.internal.R.bool.config_enableNetworkLocationOverlay, 545 com.android.internal.R.string.config_networkLocationProviderPackageName); 546 if (networkProvider != null) { 547 LocationProviderManager networkManager = new LocationProviderManager(NETWORK_PROVIDER); 548 mProviderManagers.add(networkManager); 549 networkManager.setRealProvider(networkProvider); 550 } else { 551 Log.w(TAG, "no network location provider found"); 552 } 553 554 // ensure that a fused provider exists which will work in direct boot 555 Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser( 556 new Intent(FUSED_LOCATION_SERVICE_ACTION), 557 MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(), 558 "Unable to find a direct boot aware fused location provider"); 559 560 // bind to fused provider 561 LocationProviderProxy fusedProvider = LocationProviderProxy.createAndRegister( 562 mContext, 563 FUSED_LOCATION_SERVICE_ACTION, 564 com.android.internal.R.bool.config_enableFusedLocationOverlay, 565 com.android.internal.R.string.config_fusedLocationProviderPackageName); 566 if (fusedProvider != null) { 567 LocationProviderManager fusedManager = new LocationProviderManager(FUSED_PROVIDER); 568 mProviderManagers.add(fusedManager); 569 fusedManager.setRealProvider(fusedProvider); 570 } else { 571 Log.e(TAG, "no fused location provider found"); 572 } 573 574 // bind to geocoder provider 575 mGeocodeProvider = GeocoderProxy.createAndRegister(mContext); 576 if (mGeocodeProvider == null) { 577 Log.e(TAG, "no geocoder provider found"); 578 } 579 580 // bind to hardware activity recognition 581 HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy = 582 HardwareActivityRecognitionProxy.createAndRegister(mContext); 583 if (hardwareActivityRecognitionProxy == null) { 584 Log.e(TAG, "unable to bind ActivityRecognitionProxy"); 585 } 586 587 String[] testProviderStrings = mContext.getResources().getStringArray( 588 com.android.internal.R.array.config_testLocationProviders); 589 for (String testProviderString : testProviderStrings) { 590 String[] fragments = testProviderString.split(","); 591 String name = fragments[0].trim(); 592 ProviderProperties properties = new ProviderProperties( 593 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */, 594 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */, 595 Boolean.parseBoolean(fragments[3]) /* requiresCell */, 596 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */, 597 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */, 598 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */, 599 Boolean.parseBoolean(fragments[7]) /* supportsBearing */, 600 Integer.parseInt(fragments[8]) /* powerRequirement */, 601 Integer.parseInt(fragments[9]) /* accuracy */); 602 LocationProviderManager manager = getLocationProviderManager(name); 603 if (manager == null) { 604 manager = new LocationProviderManager(name); 605 mProviderManagers.add(manager); 606 } 607 manager.setMockProvider(new MockProvider(properties)); 608 } 609 } 610 initializeGnss()611 private void initializeGnss() { 612 // Do not hold mLock when calling GnssManagerService#isGnssSupported() which calls into HAL. 613 if (GnssManagerService.isGnssSupported()) { 614 mGnssManagerService = new GnssManagerService(mContext, mAppOpsHelper, mSettingsHelper, 615 mAppForegroundHelper, mLocationUsageLogger); 616 mGnssManagerService.onSystemReady(); 617 618 LocationProviderManager gnssManager = new LocationProviderManager(GPS_PROVIDER); 619 synchronized (mLock) { 620 mProviderManagers.add(gnssManager); 621 } 622 gnssManager.setRealProvider(mGnssManagerService.getGnssLocationProvider()); 623 624 // bind to geofence proxy 625 IGpsGeofenceHardware gpsGeofenceHardware = mGnssManagerService.getGpsGeofenceProxy(); 626 if (gpsGeofenceHardware != null) { 627 GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, gpsGeofenceHardware); 628 if (provider == null) { 629 Log.e(TAG, "unable to bind to GeofenceProxy"); 630 } 631 } 632 } 633 } 634 onUserChanged(@serIdInt int userId, @UserChange int change)635 private void onUserChanged(@UserIdInt int userId, @UserChange int change) { 636 switch (change) { 637 case CURRENT_USER_CHANGED: 638 synchronized (mLock) { 639 for (LocationProviderManager manager : mProviderManagers) { 640 manager.onEnabledChangedLocked(userId); 641 } 642 } 643 break; 644 case USER_STARTED: 645 synchronized (mLock) { 646 for (LocationProviderManager manager : mProviderManagers) { 647 manager.onUserStarted(userId); 648 } 649 } 650 break; 651 case USER_STOPPED: 652 synchronized (mLock) { 653 for (LocationProviderManager manager : mProviderManagers) { 654 manager.onUserStopped(userId); 655 } 656 } 657 break; 658 } 659 } 660 661 /** 662 * Location provider manager, manages a LocationProvider. 663 */ 664 class LocationProviderManager implements MockableLocationProvider.Listener { 665 666 private final String mName; 667 668 private final LocationFudger mLocationFudger; 669 670 // if the provider is enabled for a given user id - null or not present means unknown 671 @GuardedBy("mLock") 672 private final SparseArray<Boolean> mEnabled; 673 674 // last location for a given user 675 @GuardedBy("mLock") 676 private final SparseArray<Location> mLastLocation; 677 678 // last coarse location for a given user 679 @GuardedBy("mLock") 680 private final SparseArray<Location> mLastCoarseLocation; 681 682 // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary 683 protected final MockableLocationProvider mProvider; 684 LocationProviderManager(String name)685 private LocationProviderManager(String name) { 686 mName = name; 687 mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM()); 688 mEnabled = new SparseArray<>(2); 689 mLastLocation = new SparseArray<>(2); 690 mLastCoarseLocation = new SparseArray<>(2); 691 692 // initialize last since this lets our reference escape 693 mProvider = new MockableLocationProvider(mLock, this); 694 } 695 getName()696 public String getName() { 697 return mName; 698 } 699 hasProvider()700 public boolean hasProvider() { 701 return mProvider.getProvider() != null; 702 } 703 setRealProvider(AbstractLocationProvider provider)704 public void setRealProvider(AbstractLocationProvider provider) { 705 mProvider.setRealProvider(provider); 706 } 707 setMockProvider(@ullable MockProvider provider)708 public void setMockProvider(@Nullable MockProvider provider) { 709 synchronized (mLock) { 710 mProvider.setMockProvider(provider); 711 712 // when removing a mock provider, also clear any mock last locations and reset the 713 // location fudger. the mock provider could have been used to infer the current 714 // location fudger offsets. 715 if (provider == null) { 716 for (int i = 0; i < mLastLocation.size(); i++) { 717 Location lastLocation = mLastLocation.valueAt(i); 718 if (lastLocation != null && lastLocation.isFromMockProvider()) { 719 mLastLocation.setValueAt(i, null); 720 } 721 } 722 723 for (int i = 0; i < mLastCoarseLocation.size(); i++) { 724 Location lastCoarseLocation = mLastCoarseLocation.valueAt(i); 725 if (lastCoarseLocation != null && lastCoarseLocation.isFromMockProvider()) { 726 mLastCoarseLocation.setValueAt(i, null); 727 } 728 } 729 730 mLocationFudger.resetOffsets(); 731 } 732 } 733 } 734 getPackages()735 public Set<String> getPackages() { 736 return mProvider.getState().providerPackageNames; 737 } 738 739 @Nullable getProperties()740 public ProviderProperties getProperties() { 741 return mProvider.getState().properties; 742 } 743 744 @Nullable getLastLocation(int userId, @PermissionLevel int permissionlevel)745 public Location getLastLocation(int userId, @PermissionLevel int permissionlevel) { 746 synchronized (mLock) { 747 switch (permissionlevel) { 748 case PERMISSION_COARSE: 749 return mLastCoarseLocation.get(userId); 750 case PERMISSION_FINE: 751 return mLastLocation.get(userId); 752 default: 753 throw new AssertionError(); 754 } 755 } 756 } 757 injectLastLocation(Location location, int userId)758 public void injectLastLocation(Location location, int userId) { 759 synchronized (mLock) { 760 if (mLastLocation.get(userId) == null) { 761 setLastLocation(location, userId); 762 } 763 } 764 } 765 setLastLocation(Location location, int userId)766 private void setLastLocation(Location location, int userId) { 767 synchronized (mLock) { 768 mLastLocation.put(userId, location); 769 770 // update last coarse interval only if enough time has passed 771 long timeDeltaMs = Long.MAX_VALUE; 772 Location coarseLocation = mLastCoarseLocation.get(userId); 773 if (coarseLocation != null) { 774 timeDeltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeNanos()) 775 - NANOSECONDS.toMillis(coarseLocation.getElapsedRealtimeNanos()); 776 } 777 if (timeDeltaMs > FASTEST_COARSE_INTERVAL_MS) { 778 mLastCoarseLocation.put(userId, mLocationFudger.createCoarse(location)); 779 } 780 } 781 } 782 setMockProviderAllowed(boolean enabled)783 public void setMockProviderAllowed(boolean enabled) { 784 synchronized (mLock) { 785 if (!mProvider.isMock()) { 786 throw new IllegalArgumentException(mName + " provider is not a test provider"); 787 } 788 789 mProvider.setMockProviderAllowed(enabled); 790 } 791 } 792 setMockProviderLocation(Location location)793 public void setMockProviderLocation(Location location) { 794 synchronized (mLock) { 795 if (!mProvider.isMock()) { 796 throw new IllegalArgumentException(mName + " provider is not a test provider"); 797 } 798 799 String locationProvider = location.getProvider(); 800 if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) { 801 // The location has an explicit provider that is different from the mock 802 // provider name. The caller may be trying to fool us via b/33091107. 803 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(), 804 mName + "!=" + locationProvider); 805 } 806 807 mProvider.setMockProviderLocation(location); 808 } 809 } 810 getMockProviderRequests()811 public List<LocationRequest> getMockProviderRequests() { 812 synchronized (mLock) { 813 if (!mProvider.isMock()) { 814 throw new IllegalArgumentException(mName + " provider is not a test provider"); 815 } 816 817 return mProvider.getCurrentRequest().locationRequests; 818 } 819 } 820 setRequest(ProviderRequest request)821 public void setRequest(ProviderRequest request) { 822 mProvider.setRequest(request); 823 } 824 sendExtraCommand(int uid, int pid, String command, Bundle extras)825 public void sendExtraCommand(int uid, int pid, String command, Bundle extras) { 826 mProvider.sendExtraCommand(uid, pid, command, extras); 827 } 828 829 @GuardedBy("mLock") 830 @Override onReportLocation(Location location)831 public void onReportLocation(Location location) { 832 // don't validate mock locations 833 if (!location.isFromMockProvider()) { 834 if (location.getLatitude() == 0 && location.getLongitude() == 0) { 835 Log.w(TAG, "blocking 0,0 location from " + mName + " provider"); 836 return; 837 } 838 } 839 840 if (!location.isComplete()) { 841 Log.w(TAG, "blocking incomplete location from " + mName + " provider"); 842 return; 843 } 844 845 // update last location if the provider is enabled or if servicing a bypass request 846 boolean locationSettingsIgnored = mProvider.getCurrentRequest().locationSettingsIgnored; 847 for (int userId : mUserInfoHelper.getCurrentUserIds()) { 848 if (locationSettingsIgnored || isEnabled(userId)) { 849 setLastLocation(location, userId); 850 } 851 } 852 853 handleLocationChangedLocked(this, location, mLocationFudger.createCoarse(location)); 854 } 855 856 @GuardedBy("mLock") 857 @Override onReportLocation(List<Location> locations)858 public void onReportLocation(List<Location> locations) { 859 if (mGnssManagerService == null || !GPS_PROVIDER.equals(mName)) { 860 return; 861 } 862 863 mGnssManagerService.onReportLocation(locations); 864 } 865 866 @GuardedBy("mLock") 867 @Override onStateChanged(State oldState, State newState)868 public void onStateChanged(State oldState, State newState) { 869 if (oldState.allowed != newState.allowed) { 870 onEnabledChangedLocked(UserHandle.USER_ALL); 871 } 872 } 873 onUserStarted(int userId)874 public void onUserStarted(int userId) { 875 synchronized (mLock) { 876 // clear the user's enabled state in order to force a reevalution of whether the 877 // provider is enabled or disabled for the given user. we clear the user's state 878 // first to ensure that a user starting never causes any change notifications. it's 879 // possible for us to observe a user before we observe it's been started (for 880 // example, another component gets a user started notification before us and 881 // registers a location request immediately), which would cause us to already have 882 // some state in place. when we eventually do get the user started notification 883 // ourselves we don't want to send a change notification based on the prior state 884 mEnabled.put(userId, null); 885 onEnabledChangedLocked(userId); 886 } 887 } 888 onUserStopped(int userId)889 public void onUserStopped(int userId) { 890 synchronized (mLock) { 891 mEnabled.remove(userId); 892 mLastLocation.remove(userId); 893 mLastCoarseLocation.remove(userId); 894 } 895 } 896 isEnabled(int userId)897 public boolean isEnabled(int userId) { 898 if (userId == UserHandle.USER_NULL) { 899 // used during initialization - ignore since many lower level operations (checking 900 // settings for instance) do not support the null user 901 return false; 902 } 903 904 synchronized (mLock) { 905 Boolean enabled = mEnabled.get(userId); 906 if (enabled == null) { 907 // this generally shouldn't occur, but might be possible due to race conditions 908 // on when we are notified of new users 909 910 // hack to fix b/171910679. mutating the user enabled state within this method 911 // may cause unexpected changes to other state (for instance, this could cause 912 // provider enable/disable notifications to be sent to clients, which could 913 // result in a dead client being detected, which could result in the client 914 // being removed, which means that if this function is called while clients are 915 // being iterated over we have now unexpectedly mutated the iterated 916 // collection). instead, we return a correct value immediately here, and 917 // schedule the actual update for later. this has been completely rewritten and 918 // is no longer a problem in the next version of android. 919 enabled = mProvider.getState().allowed 920 && mUserInfoHelper.isCurrentUserId(userId) 921 && mSettingsHelper.isLocationEnabled(userId); 922 923 Log.w(TAG, mName + " provider saw user " + userId + " unexpectedly"); 924 mHandler.post(() -> { 925 synchronized (mLock) { 926 onEnabledChangedLocked(userId); 927 } 928 }); 929 } 930 931 return enabled; 932 } 933 } 934 935 @GuardedBy("mLock") onEnabledChangedLocked(int userId)936 public void onEnabledChangedLocked(int userId) { 937 if (userId == UserHandle.USER_NULL) { 938 // used during initialization - ignore since many lower level operations (checking 939 // settings for instance) do not support the null user 940 return; 941 } else if (userId == UserHandle.USER_ALL) { 942 // we know enabled changes can only happen for current users since providers are 943 // always disabled for all non-current users 944 for (int currentUserId : mUserInfoHelper.getCurrentUserIds()) { 945 onEnabledChangedLocked(currentUserId); 946 } 947 return; 948 } 949 950 // if any property that contributes to "enabled" here changes state, it MUST result 951 // in a direct or indrect call to onEnabledChangedLocked. this allows the provider to 952 // guarantee that it will always eventually reach the correct state. 953 boolean enabled = mProvider.getState().allowed 954 && mUserInfoHelper.isCurrentUserId(userId) 955 && mSettingsHelper.isLocationEnabled(userId); 956 957 Boolean wasEnabled = mEnabled.get(userId); 958 if (wasEnabled != null && wasEnabled == enabled) { 959 return; 960 } 961 962 mEnabled.put(userId, enabled); 963 964 if (D) { 965 Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled); 966 } 967 968 // clear last locations if we become disabled and if not servicing a bypass request 969 if (!enabled && !mProvider.getCurrentRequest().locationSettingsIgnored) { 970 mLastLocation.put(userId, null); 971 mLastCoarseLocation.put(userId, null); 972 } 973 974 // update LOCATION_PROVIDERS_ALLOWED for best effort backwards compatibility 975 mSettingsHelper.setLocationProviderAllowed(mName, enabled, userId); 976 977 // do not send change notifications if we just saw this user for the first time 978 if (wasEnabled != null) { 979 // fused and passive provider never get public updates for legacy reasons 980 if (!FUSED_PROVIDER.equals(mName) && !PASSIVE_PROVIDER.equals(mName)) { 981 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION) 982 .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName) 983 .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled) 984 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) 985 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 986 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); 987 } 988 } 989 990 updateProviderEnabledLocked(this, enabled); 991 } 992 dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args)993 public void dump(FileDescriptor fd, IndentingPrintWriter pw, String[] args) { 994 synchronized (mLock) { 995 pw.print(mName + " provider"); 996 if (mProvider.isMock()) { 997 pw.print(" [mock]"); 998 } 999 pw.println(":"); 1000 1001 pw.increaseIndent(); 1002 1003 // for now we only dump for the parent user 1004 int[] userIds = mUserInfoHelper.getCurrentUserIds(); 1005 if (userIds.length == 1) { 1006 int userId = userIds[0]; 1007 pw.println("last location=" + mLastLocation.get(userId)); 1008 pw.println("last coarse location=" + mLastCoarseLocation.get(userId)); 1009 pw.println("enabled=" + isEnabled(userId)); 1010 } else { 1011 for (int userId : userIds) { 1012 pw.println("user " + userId + ":"); 1013 pw.increaseIndent(); 1014 pw.println("last location=" + mLastLocation.get(userId)); 1015 pw.println("last coarse location=" + mLastCoarseLocation.get(userId)); 1016 pw.println("enabled=" + isEnabled(userId)); 1017 pw.decreaseIndent(); 1018 } 1019 } 1020 } 1021 1022 mProvider.dump(fd, pw, args); 1023 1024 pw.decreaseIndent(); 1025 } 1026 } 1027 1028 class PassiveLocationProviderManager extends LocationProviderManager { 1029 PassiveLocationProviderManager()1030 private PassiveLocationProviderManager() { 1031 super(PASSIVE_PROVIDER); 1032 } 1033 1034 @Override setRealProvider(AbstractLocationProvider provider)1035 public void setRealProvider(AbstractLocationProvider provider) { 1036 Preconditions.checkArgument(provider instanceof PassiveProvider); 1037 super.setRealProvider(provider); 1038 } 1039 1040 @Override setMockProvider(@ullable MockProvider provider)1041 public void setMockProvider(@Nullable MockProvider provider) { 1042 if (provider != null) { 1043 throw new IllegalArgumentException("Cannot mock the passive provider"); 1044 } 1045 } 1046 updateLocation(Location location)1047 public void updateLocation(Location location) { 1048 synchronized (mLock) { 1049 PassiveProvider passiveProvider = (PassiveProvider) mProvider.getProvider(); 1050 Preconditions.checkState(passiveProvider != null); 1051 1052 long identity = Binder.clearCallingIdentity(); 1053 try { 1054 passiveProvider.updateLocation(location); 1055 } finally { 1056 Binder.restoreCallingIdentity(identity); 1057 } 1058 } 1059 } 1060 } 1061 1062 /** 1063 * A wrapper class holding either an ILocationListener or a PendingIntent to receive 1064 * location updates. 1065 */ 1066 private final class Receiver extends LocationManagerServiceUtils.LinkedListenerBase implements 1067 PendingIntent.OnFinished { 1068 private static final long WAKELOCK_TIMEOUT_MILLIS = 60 * 1000; 1069 1070 private final ILocationListener mListener; 1071 final PendingIntent mPendingIntent; 1072 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller. 1073 private final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver. 1074 private final Object mKey; 1075 1076 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>(); 1077 1078 // True if app ops has started monitoring this receiver for locations. 1079 private boolean mOpMonitoring; 1080 // True if app ops has started monitoring this receiver for high power (gps) locations. 1081 private boolean mOpHighPowerMonitoring; 1082 private int mPendingBroadcasts; 1083 PowerManager.WakeLock mWakeLock; 1084 Receiver(ILocationListener listener, PendingIntent intent, CallerIdentity identity, WorkSource workSource, boolean hideFromAppOps)1085 private Receiver(ILocationListener listener, PendingIntent intent, CallerIdentity identity, 1086 WorkSource workSource, boolean hideFromAppOps) { 1087 super(identity); 1088 mListener = listener; 1089 mPendingIntent = intent; 1090 if (listener != null) { 1091 mKey = listener.asBinder(); 1092 } else { 1093 mKey = intent; 1094 } 1095 if (workSource != null && workSource.isEmpty()) { 1096 workSource = null; 1097 } 1098 mWorkSource = workSource; 1099 mHideFromAppOps = hideFromAppOps; 1100 1101 updateMonitoring(true); 1102 1103 // construct/configure wakelock 1104 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 1105 if (workSource == null) { 1106 workSource = new WorkSource(mCallerIdentity.uid, mCallerIdentity.packageName); 1107 } 1108 mWakeLock.setWorkSource(workSource); 1109 1110 // For a non-reference counted wakelock, each acquire will reset the timeout, and we 1111 // only need to release it once. 1112 mWakeLock.setReferenceCounted(false); 1113 } 1114 1115 @Override equals(Object otherObj)1116 public boolean equals(Object otherObj) { 1117 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey); 1118 } 1119 1120 @Override hashCode()1121 public int hashCode() { 1122 return mKey.hashCode(); 1123 } 1124 1125 @Override toString()1126 public String toString() { 1127 StringBuilder s = new StringBuilder(); 1128 s.append("Reciever["); 1129 s.append(Integer.toHexString(System.identityHashCode(this))); 1130 if (mListener != null) { 1131 s.append(" listener"); 1132 } else { 1133 s.append(" intent"); 1134 } 1135 for (String p : mUpdateRecords.keySet()) { 1136 s.append(" ").append(mUpdateRecords.get(p).toString()); 1137 } 1138 s.append(" monitoring location: ").append(mOpMonitoring); 1139 s.append("]"); 1140 return s.toString(); 1141 } 1142 1143 /** 1144 * Update AppOp monitoring for this receiver. 1145 * 1146 * @param allow If true receiver is currently active, if false it's been removed. 1147 */ updateMonitoring(boolean allow)1148 public void updateMonitoring(boolean allow) { 1149 if (mHideFromAppOps) { 1150 return; 1151 } 1152 1153 boolean requestingLocation = false; 1154 boolean requestingHighPowerLocation = false; 1155 if (allow) { 1156 // See if receiver has any enabled update records. Also note if any update records 1157 // are high power (has a high power provider with an interval under a threshold). 1158 for (UpdateRecord updateRecord : mUpdateRecords.values()) { 1159 LocationProviderManager manager = getLocationProviderManager( 1160 updateRecord.mProvider); 1161 if (manager == null) { 1162 continue; 1163 } 1164 if (!manager.isEnabled(UserHandle.getUserId(mCallerIdentity.uid)) 1165 && !isSettingsExempt(updateRecord)) { 1166 continue; 1167 } 1168 1169 requestingLocation = true; 1170 ProviderProperties properties = manager.getProperties(); 1171 if (properties != null 1172 && properties.mPowerRequirement == Criteria.POWER_HIGH 1173 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) { 1174 requestingHighPowerLocation = true; 1175 break; 1176 } 1177 } 1178 } 1179 1180 // First update monitoring of any location request (including high power). 1181 mOpMonitoring = updateMonitoring( 1182 requestingLocation, 1183 mOpMonitoring, 1184 false); 1185 1186 // Now update monitoring of high power requests only. 1187 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring; 1188 mOpHighPowerMonitoring = updateMonitoring( 1189 requestingHighPowerLocation, 1190 mOpHighPowerMonitoring, 1191 true); 1192 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) { 1193 long identity = Binder.clearCallingIdentity(); 1194 try { 1195 // Send an intent to notify that a high power request has been added/removed. 1196 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION); 1197 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 1198 } finally { 1199 Binder.restoreCallingIdentity(identity); 1200 } 1201 } 1202 } 1203 updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring, boolean highPower)1204 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring, 1205 boolean highPower) { 1206 if (!currentlyMonitoring) { 1207 if (allowMonitoring) { 1208 if (!highPower) { 1209 return mAppOpsHelper.startLocationMonitoring(mCallerIdentity); 1210 } else { 1211 return mAppOpsHelper.startHighPowerLocationMonitoring(mCallerIdentity); 1212 } 1213 } 1214 } else { 1215 if (!allowMonitoring || !mAppOpsHelper.checkLocationAccess(mCallerIdentity)) { 1216 if (!highPower) { 1217 mAppOpsHelper.stopLocationMonitoring(mCallerIdentity); 1218 } else { 1219 mAppOpsHelper.stopHighPowerLocationMonitoring(mCallerIdentity); 1220 } 1221 return false; 1222 } 1223 } 1224 1225 return currentlyMonitoring; 1226 } 1227 isListener()1228 public boolean isListener() { 1229 return mListener != null; 1230 } 1231 isPendingIntent()1232 public boolean isPendingIntent() { 1233 return mPendingIntent != null; 1234 } 1235 getListener()1236 public ILocationListener getListener() { 1237 if (mListener != null) { 1238 return mListener; 1239 } 1240 throw new IllegalStateException("Request for non-existent listener"); 1241 } 1242 callLocationChangedLocked(Location location)1243 public boolean callLocationChangedLocked(Location location) { 1244 if (mListener != null) { 1245 try { 1246 mListener.onLocationChanged(new Location(location)); 1247 // call this after broadcasting so we do not increment 1248 // if we throw an exception. 1249 incrementPendingBroadcastsLocked(); 1250 } catch (RemoteException e) { 1251 return false; 1252 } 1253 } else { 1254 Intent locationChanged = new Intent(); 1255 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, 1256 new Location(location)); 1257 try { 1258 mPendingIntent.send(mContext, 0, locationChanged, this, mHandler, 1259 CallerIdentity.asPermission(mCallerIdentity.permissionLevel), 1260 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); 1261 // call this after broadcasting so we do not increment 1262 // if we throw an exception. 1263 incrementPendingBroadcastsLocked(); 1264 } catch (PendingIntent.CanceledException e) { 1265 return false; 1266 } 1267 } 1268 return true; 1269 } 1270 callProviderEnabledLocked(String provider, boolean enabled)1271 private boolean callProviderEnabledLocked(String provider, boolean enabled) { 1272 // First update AppOp monitoring. 1273 // An app may get/lose location access as providers are enabled/disabled. 1274 updateMonitoring(true); 1275 1276 if (mListener != null) { 1277 try { 1278 if (enabled) { 1279 mListener.onProviderEnabled(provider); 1280 } else { 1281 mListener.onProviderDisabled(provider); 1282 } 1283 // call this after broadcasting so we do not increment 1284 // if we throw an exception. 1285 incrementPendingBroadcastsLocked(); 1286 } catch (RemoteException e) { 1287 return false; 1288 } 1289 } else { 1290 Intent providerIntent = new Intent(); 1291 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); 1292 try { 1293 mPendingIntent.send(mContext, 0, providerIntent, this, mHandler, 1294 CallerIdentity.asPermission(mCallerIdentity.permissionLevel), 1295 PendingIntentUtils.createDontSendToRestrictedAppsBundle(null)); 1296 // call this after broadcasting so we do not increment 1297 // if we throw an exception. 1298 incrementPendingBroadcastsLocked(); 1299 } catch (PendingIntent.CanceledException e) { 1300 return false; 1301 } 1302 } 1303 return true; 1304 } 1305 callRemovedLocked()1306 public void callRemovedLocked() { 1307 if (mListener != null) { 1308 try { 1309 mListener.onRemoved(); 1310 } catch (RemoteException e) { 1311 // doesn't matter 1312 } 1313 } 1314 } 1315 1316 @Override binderDied()1317 public void binderDied() { 1318 synchronized (mLock) { 1319 removeUpdatesLocked(this); 1320 clearPendingBroadcastsLocked(); 1321 } 1322 } 1323 1324 @Override onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode, String resultData, Bundle resultExtras)1325 public void onSendFinished(PendingIntent pendingIntent, Intent intent, 1326 int resultCode, String resultData, Bundle resultExtras) { 1327 synchronized (mLock) { 1328 decrementPendingBroadcastsLocked(); 1329 } 1330 } 1331 1332 // this must be called while synchronized by caller in a synchronized block 1333 // containing the sending of the broadcaset incrementPendingBroadcastsLocked()1334 private void incrementPendingBroadcastsLocked() { 1335 mPendingBroadcasts++; 1336 // so wakelock calls will succeed 1337 long identity = Binder.clearCallingIdentity(); 1338 try { 1339 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS); 1340 } finally { 1341 Binder.restoreCallingIdentity(identity); 1342 } 1343 } 1344 decrementPendingBroadcastsLocked()1345 private void decrementPendingBroadcastsLocked() { 1346 if (--mPendingBroadcasts == 0) { 1347 // so wakelock calls will succeed 1348 long identity = Binder.clearCallingIdentity(); 1349 try { 1350 if (mWakeLock.isHeld()) { 1351 mWakeLock.release(); 1352 } 1353 } finally { 1354 Binder.restoreCallingIdentity(identity); 1355 } 1356 } 1357 } 1358 clearPendingBroadcastsLocked()1359 public void clearPendingBroadcastsLocked() { 1360 if (mPendingBroadcasts > 0) { 1361 mPendingBroadcasts = 0; 1362 // so wakelock calls will succeed 1363 long identity = Binder.clearCallingIdentity(); 1364 try { 1365 if (mWakeLock.isHeld()) { 1366 mWakeLock.release(); 1367 } 1368 } finally { 1369 Binder.restoreCallingIdentity(identity); 1370 } 1371 } 1372 } 1373 } 1374 1375 @Override locationCallbackFinished(ILocationListener listener)1376 public void locationCallbackFinished(ILocationListener listener) { 1377 //Do not use getReceiverLocked here as that will add the ILocationListener to 1378 //the receiver list if it is not found. If it is not found then the 1379 //LocationListener was removed when it had a pending broadcast and should 1380 //not be added back. 1381 synchronized (mLock) { 1382 Receiver receiver = mReceivers.get(listener.asBinder()); 1383 if (receiver != null) { 1384 receiver.decrementPendingBroadcastsLocked(); 1385 } 1386 } 1387 } 1388 1389 @Override getGnssYearOfHardware()1390 public int getGnssYearOfHardware() { 1391 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware(); 1392 } 1393 1394 @Override 1395 @Nullable getGnssHardwareModelName()1396 public String getGnssHardwareModelName() { 1397 return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName(); 1398 } 1399 1400 @Override getGnssBatchSize(String packageName)1401 public int getGnssBatchSize(String packageName) { 1402 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(packageName); 1403 } 1404 1405 @Override addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName, String featureId)1406 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName, 1407 String featureId) { 1408 return mGnssManagerService != null && mGnssManagerService.addGnssBatchingCallback( 1409 callback, packageName, featureId); 1410 } 1411 1412 @Override removeGnssBatchingCallback()1413 public void removeGnssBatchingCallback() { 1414 if (mGnssManagerService != null) mGnssManagerService.removeGnssBatchingCallback(); 1415 } 1416 1417 @Override startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, String featureId)1418 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, 1419 String featureId) { 1420 return mGnssManagerService != null && mGnssManagerService.startGnssBatch(periodNanos, 1421 wakeOnFifoFull, packageName, featureId); 1422 } 1423 1424 @Override flushGnssBatch(String packageName)1425 public void flushGnssBatch(String packageName) { 1426 if (mGnssManagerService != null) mGnssManagerService.flushGnssBatch(packageName); 1427 } 1428 1429 @Override stopGnssBatch()1430 public boolean stopGnssBatch() { 1431 return mGnssManagerService != null && mGnssManagerService.stopGnssBatch(); 1432 } 1433 1434 @Nullable getLocationProviderManager(String providerName)1435 private LocationProviderManager getLocationProviderManager(String providerName) { 1436 for (LocationProviderManager manager : mProviderManagers) { 1437 if (providerName.equals(manager.getName())) { 1438 return manager; 1439 } 1440 } 1441 1442 return null; 1443 } 1444 1445 @Override getAllProviders()1446 public List<String> getAllProviders() { 1447 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size()); 1448 for (LocationProviderManager manager : mProviderManagers) { 1449 if (FUSED_PROVIDER.equals(manager.getName())) { 1450 continue; 1451 } 1452 providers.add(manager.getName()); 1453 } 1454 return providers; 1455 } 1456 1457 @Override getProviders(Criteria criteria, boolean enabledOnly)1458 public List<String> getProviders(Criteria criteria, boolean enabledOnly) { 1459 if (!CallerIdentity.checkCallingOrSelfLocationPermission(mContext)) { 1460 return Collections.emptyList(); 1461 } 1462 1463 synchronized (mLock) { 1464 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size()); 1465 for (LocationProviderManager manager : mProviderManagers) { 1466 String name = manager.getName(); 1467 if (FUSED_PROVIDER.equals(name)) { 1468 continue; 1469 } 1470 if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) { 1471 continue; 1472 } 1473 if (criteria != null && !LocationProvider.propertiesMeetCriteria(name, 1474 manager.getProperties(), criteria)) { 1475 continue; 1476 } 1477 providers.add(name); 1478 } 1479 return providers; 1480 } 1481 } 1482 1483 @Override getBestProvider(Criteria criteria, boolean enabledOnly)1484 public String getBestProvider(Criteria criteria, boolean enabledOnly) { 1485 List<String> providers; 1486 synchronized (mLock) { 1487 providers = getProviders(criteria, enabledOnly); 1488 if (providers.isEmpty()) { 1489 providers = getProviders(null, enabledOnly); 1490 } 1491 } 1492 1493 if (!providers.isEmpty()) { 1494 if (providers.contains(GPS_PROVIDER)) { 1495 return GPS_PROVIDER; 1496 } else if (providers.contains(NETWORK_PROVIDER)) { 1497 return NETWORK_PROVIDER; 1498 } else { 1499 return providers.get(0); 1500 } 1501 } 1502 1503 return null; 1504 } 1505 1506 @GuardedBy("mLock") updateProviderEnabledLocked(LocationProviderManager manager, boolean enabled)1507 private void updateProviderEnabledLocked(LocationProviderManager manager, boolean enabled) { 1508 ArrayList<Receiver> deadReceivers = null; 1509 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName()); 1510 if (records != null) { 1511 for (UpdateRecord record : records) { 1512 if (!mUserInfoHelper.isCurrentUserId( 1513 UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) { 1514 continue; 1515 } 1516 1517 // requests that ignore location settings will never provide notifications 1518 if (isSettingsExempt(record)) { 1519 continue; 1520 } 1521 1522 // Sends a notification message to the receiver 1523 if (!record.mReceiver.callProviderEnabledLocked(manager.getName(), enabled)) { 1524 if (deadReceivers == null) { 1525 deadReceivers = new ArrayList<>(); 1526 } 1527 deadReceivers.add(record.mReceiver); 1528 } 1529 } 1530 } 1531 1532 if (deadReceivers != null) { 1533 for (int i = deadReceivers.size() - 1; i >= 0; i--) { 1534 removeUpdatesLocked(deadReceivers.get(i)); 1535 } 1536 } 1537 1538 applyRequirementsLocked(manager); 1539 } 1540 1541 @GuardedBy("mLock") applyRequirementsLocked(String providerName)1542 private void applyRequirementsLocked(String providerName) { 1543 LocationProviderManager manager = getLocationProviderManager(providerName); 1544 if (manager != null) { 1545 applyRequirementsLocked(manager); 1546 } 1547 } 1548 1549 @GuardedBy("mLock") applyRequirementsLocked(LocationProviderManager manager)1550 private void applyRequirementsLocked(LocationProviderManager manager) { 1551 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName()); 1552 ProviderRequest.Builder providerRequest = new ProviderRequest.Builder(); 1553 1554 // if provider is not active, it should not respond to requests 1555 1556 if (mProviderManagers.contains(manager) && records != null && !records.isEmpty()) { 1557 long backgroundThrottleInterval = mSettingsHelper.getBackgroundThrottleIntervalMs(); 1558 1559 ArrayList<LocationRequest> requests = new ArrayList<>(records.size()); 1560 1561 final boolean isForegroundOnlyMode = 1562 mBatterySaverMode == PowerManager.LOCATION_MODE_FOREGROUND_ONLY; 1563 final boolean shouldThrottleRequests = 1564 mBatterySaverMode 1565 == PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF 1566 && !mPowerManager.isInteractive(); 1567 // initialize the low power mode to true and set to false if any of the records requires 1568 providerRequest.setLowPowerMode(true); 1569 for (UpdateRecord record : records) { 1570 CallerIdentity identity = record.mReceiver.mCallerIdentity; 1571 if (!mUserInfoHelper.isCurrentUserId(identity.userId)) { 1572 continue; 1573 } 1574 1575 if (!mAppOpsHelper.checkLocationAccess(identity)) { 1576 continue; 1577 } 1578 final boolean isBatterySaverDisablingLocation = shouldThrottleRequests 1579 || (isForegroundOnlyMode && !record.mIsForegroundUid); 1580 if (!manager.isEnabled(identity.userId) || isBatterySaverDisablingLocation) { 1581 if (isSettingsExempt(record)) { 1582 providerRequest.setLocationSettingsIgnored(true); 1583 providerRequest.setLowPowerMode(false); 1584 } else { 1585 continue; 1586 } 1587 } 1588 1589 LocationRequest locationRequest = record.mRealRequest; 1590 long interval = locationRequest.getInterval(); 1591 1592 1593 // if we're forcing location, don't apply any throttling 1594 if (!providerRequest.isLocationSettingsIgnored() && !isThrottlingExempt( 1595 record.mReceiver.mCallerIdentity)) { 1596 if (!record.mIsForegroundUid) { 1597 interval = Math.max(interval, backgroundThrottleInterval); 1598 } 1599 if (interval != locationRequest.getInterval()) { 1600 locationRequest = new LocationRequest(locationRequest); 1601 locationRequest.setInterval(interval); 1602 } 1603 } 1604 1605 record.mRequest = locationRequest; 1606 record.mReceiver.updateMonitoring(true); 1607 requests.add(locationRequest); 1608 if (!locationRequest.isLowPowerMode()) { 1609 providerRequest.setLowPowerMode(false); 1610 } 1611 if (interval < providerRequest.getInterval()) { 1612 providerRequest.setInterval(interval); 1613 } 1614 } 1615 1616 providerRequest.setLocationRequests(requests); 1617 1618 if (providerRequest.getInterval() < Long.MAX_VALUE) { 1619 // calculate who to blame for power 1620 // This is somewhat arbitrary. We pick a threshold interval 1621 // that is slightly higher that the minimum interval, and 1622 // spread the blame across all applications with a request 1623 // under that threshold. 1624 // TODO: overflow 1625 long thresholdInterval = (providerRequest.getInterval() + 1000) * 3 / 2; 1626 for (UpdateRecord record : records) { 1627 if (mUserInfoHelper.isCurrentUserId( 1628 UserHandle.getUserId(record.mReceiver.mCallerIdentity.uid))) { 1629 LocationRequest locationRequest = record.mRequest; 1630 1631 // Don't assign battery blame for update records whose 1632 // client has no permission to receive location data. 1633 if (!providerRequest.getLocationRequests().contains(locationRequest)) { 1634 continue; 1635 } 1636 1637 if (locationRequest.getInterval() <= thresholdInterval) { 1638 if (record.mReceiver.mWorkSource != null 1639 && isValidWorkSource(record.mReceiver.mWorkSource)) { 1640 providerRequest.getWorkSource().add(record.mReceiver.mWorkSource); 1641 } else { 1642 // Assign blame to caller if there's no WorkSource associated with 1643 // the request or if it's invalid. 1644 providerRequest.getWorkSource().add( 1645 record.mReceiver.mCallerIdentity.uid, 1646 record.mReceiver.mCallerIdentity.packageName); 1647 } 1648 } 1649 } 1650 } 1651 } 1652 } 1653 1654 manager.setRequest(providerRequest.build()); 1655 } 1656 1657 /** 1658 * Whether a given {@code WorkSource} associated with a Location request is valid. 1659 */ isValidWorkSource(WorkSource workSource)1660 private static boolean isValidWorkSource(WorkSource workSource) { 1661 if (workSource.size() > 0) { 1662 // If the WorkSource has one or more non-chained UIDs, make sure they're accompanied 1663 // by tags. 1664 return workSource.getPackageName(0) != null; 1665 } else { 1666 // For now, make sure callers have supplied an attribution tag for use with 1667 // AppOpsManager. This might be relaxed in the future. 1668 final List<WorkChain> workChains = workSource.getWorkChains(); 1669 return workChains != null && !workChains.isEmpty() 1670 && workChains.get(0).getAttributionTag() != null; 1671 } 1672 } 1673 1674 @Override getBackgroundThrottlingWhitelist()1675 public String[] getBackgroundThrottlingWhitelist() { 1676 return mSettingsHelper.getBackgroundThrottlePackageWhitelist().toArray(new String[0]); 1677 } 1678 1679 @Override getIgnoreSettingsWhitelist()1680 public String[] getIgnoreSettingsWhitelist() { 1681 return mSettingsHelper.getIgnoreSettingsPackageWhitelist().toArray(new String[0]); 1682 } 1683 isThrottlingExempt(CallerIdentity callerIdentity)1684 private boolean isThrottlingExempt(CallerIdentity callerIdentity) { 1685 if (callerIdentity.uid == Process.SYSTEM_UID) { 1686 return true; 1687 } 1688 1689 if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains( 1690 callerIdentity.packageName)) { 1691 return true; 1692 } 1693 1694 return mLocalService.isProviderPackage(callerIdentity.packageName); 1695 1696 } 1697 isSettingsExempt(UpdateRecord record)1698 private boolean isSettingsExempt(UpdateRecord record) { 1699 if (!record.mRealRequest.isLocationSettingsIgnored()) { 1700 return false; 1701 } 1702 1703 if (mSettingsHelper.getIgnoreSettingsPackageWhitelist().contains( 1704 record.mReceiver.mCallerIdentity.packageName)) { 1705 return true; 1706 } 1707 1708 return mLocalService.isProviderPackage(record.mReceiver.mCallerIdentity.packageName); 1709 1710 } 1711 1712 private class UpdateRecord { 1713 final String mProvider; 1714 private final LocationRequest mRealRequest; // original request from client 1715 LocationRequest mRequest; // possibly throttled version of the request 1716 private final Receiver mReceiver; 1717 private boolean mIsForegroundUid; 1718 private Location mLastFixBroadcast; 1719 private Throwable mStackTrace; // for debugging only 1720 private long mExpirationRealtimeMs; 1721 1722 /** 1723 * Note: must be constructed with lock held. 1724 */ UpdateRecord(String provider, LocationRequest request, Receiver receiver)1725 private UpdateRecord(String provider, LocationRequest request, Receiver receiver) { 1726 if (Build.IS_DEBUGGABLE) { 1727 Preconditions.checkState(Thread.holdsLock(mLock)); 1728 } 1729 mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime()); 1730 mProvider = provider; 1731 mRealRequest = request; 1732 mRequest = request; 1733 mReceiver = receiver; 1734 mIsForegroundUid = mAppForegroundHelper.isAppForeground(mReceiver.mCallerIdentity.uid); 1735 1736 if (D && receiver.mCallerIdentity.pid == Process.myPid()) { 1737 mStackTrace = new Throwable(); 1738 } 1739 1740 ArrayList<UpdateRecord> records = mRecordsByProvider.computeIfAbsent(provider, 1741 k -> new ArrayList<>()); 1742 if (!records.contains(this)) { 1743 records.add(this); 1744 } 1745 1746 // Update statistics for historical location requests by package/provider 1747 mRequestStatistics.startRequesting( 1748 mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId, 1749 provider, request.getInterval(), mIsForegroundUid); 1750 } 1751 1752 /** 1753 * Method to be called when record changes foreground/background 1754 */ updateForeground(boolean isForeground)1755 private void updateForeground(boolean isForeground) { 1756 mIsForegroundUid = isForeground; 1757 mRequestStatistics.updateForeground( 1758 mReceiver.mCallerIdentity.packageName, mReceiver.mCallerIdentity.featureId, 1759 mProvider, isForeground); 1760 } 1761 1762 /** 1763 * Method to be called when a record will no longer be used. 1764 */ disposeLocked(boolean removeReceiver)1765 private void disposeLocked(boolean removeReceiver) { 1766 if (Build.IS_DEBUGGABLE) { 1767 Preconditions.checkState(Thread.holdsLock(mLock)); 1768 } 1769 1770 CallerIdentity identity = mReceiver.mCallerIdentity; 1771 mRequestStatistics.stopRequesting(identity.packageName, identity.featureId, mProvider); 1772 1773 mLocationUsageLogger.logLocationApiUsage( 1774 LocationStatsEnums.USAGE_ENDED, 1775 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES, 1776 identity.packageName, 1777 mRealRequest, 1778 mReceiver.isListener(), 1779 mReceiver.isPendingIntent(), 1780 /* geofence= */ null, 1781 mAppForegroundHelper.getImportance(mReceiver.mCallerIdentity.uid)); 1782 1783 // remove from mRecordsByProvider 1784 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); 1785 if (globalRecords != null) { 1786 globalRecords.remove(this); 1787 } 1788 1789 if (!removeReceiver) return; // the caller will handle the rest 1790 1791 // remove from Receiver#mUpdateRecords 1792 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords; 1793 receiverRecords.remove(this.mProvider); 1794 1795 // and also remove the Receiver if it has no more update records 1796 if (receiverRecords.size() == 0) { 1797 removeUpdatesLocked(mReceiver); 1798 } 1799 } 1800 1801 @Override toString()1802 public String toString() { 1803 StringBuilder b = new StringBuilder("UpdateRecord["); 1804 b.append(mProvider).append(" "); 1805 b.append(mReceiver.mCallerIdentity).append(" "); 1806 if (!mIsForegroundUid) { 1807 b.append("(background) "); 1808 } 1809 b.append(mRealRequest).append(" ").append(mReceiver.mWorkSource); 1810 1811 if (mStackTrace != null) { 1812 ByteArrayOutputStream tmp = new ByteArrayOutputStream(); 1813 mStackTrace.printStackTrace(new PrintStream(tmp)); 1814 b.append("\n\n").append(tmp.toString()).append("\n"); 1815 } 1816 1817 b.append("]"); 1818 return b.toString(); 1819 } 1820 } 1821 1822 @GuardedBy("mLock") getReceiverLocked(ILocationListener listener, CallerIdentity identity, WorkSource workSource, boolean hideFromAppOps)1823 private Receiver getReceiverLocked(ILocationListener listener, CallerIdentity identity, 1824 WorkSource workSource, boolean hideFromAppOps) { 1825 IBinder binder = listener.asBinder(); 1826 Receiver receiver = mReceivers.get(binder); 1827 if (receiver == null && identity != null) { 1828 receiver = new Receiver(listener, null, identity, workSource, 1829 hideFromAppOps); 1830 if (!receiver.linkToListenerDeathNotificationLocked( 1831 receiver.getListener().asBinder())) { 1832 return null; 1833 } 1834 mReceivers.put(binder, receiver); 1835 } 1836 return receiver; 1837 } 1838 1839 @GuardedBy("mLock") getReceiverLocked(PendingIntent intent, CallerIdentity identity, WorkSource workSource, boolean hideFromAppOps)1840 private Receiver getReceiverLocked(PendingIntent intent, CallerIdentity identity, 1841 WorkSource workSource, boolean hideFromAppOps) { 1842 Receiver receiver = mReceivers.get(intent); 1843 if (receiver == null && identity != null) { 1844 receiver = new Receiver(null, intent, identity, workSource, 1845 hideFromAppOps); 1846 mReceivers.put(intent, receiver); 1847 } 1848 return receiver; 1849 } 1850 1851 /** 1852 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution 1853 * and consistency requirements. 1854 * 1855 * @param request the LocationRequest from which to create a sanitized version 1856 * @return a version of request that meets the given resolution and consistency requirements 1857 * @hide 1858 */ createSanitizedRequest(LocationRequest request, CallerIdentity identity, boolean callerHasLocationHardwarePermission)1859 private LocationRequest createSanitizedRequest(LocationRequest request, CallerIdentity identity, 1860 boolean callerHasLocationHardwarePermission) { 1861 LocationRequest sanitizedRequest = new LocationRequest(request); 1862 if (!callerHasLocationHardwarePermission) { 1863 // allow setting low power mode only for callers with location hardware permission 1864 sanitizedRequest.setLowPowerMode(false); 1865 } 1866 if (identity.permissionLevel < PERMISSION_FINE) { 1867 switch (sanitizedRequest.getQuality()) { 1868 case LocationRequest.ACCURACY_FINE: 1869 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK); 1870 break; 1871 case LocationRequest.POWER_HIGH: 1872 sanitizedRequest.setQuality(LocationRequest.POWER_LOW); 1873 break; 1874 } 1875 // throttle 1876 if (sanitizedRequest.getInterval() < FASTEST_COARSE_INTERVAL_MS) { 1877 sanitizedRequest.setInterval(FASTEST_COARSE_INTERVAL_MS); 1878 } 1879 if (sanitizedRequest.getFastestInterval() < FASTEST_COARSE_INTERVAL_MS) { 1880 sanitizedRequest.setFastestInterval(FASTEST_COARSE_INTERVAL_MS); 1881 } 1882 } 1883 // make getFastestInterval() the minimum of interval and fastest interval 1884 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) { 1885 sanitizedRequest.setFastestInterval(request.getInterval()); 1886 } 1887 return sanitizedRequest; 1888 } 1889 1890 @Override requestLocationUpdates(LocationRequest request, ILocationListener listener, PendingIntent intent, String packageName, String featureId, String listenerId)1891 public void requestLocationUpdates(LocationRequest request, ILocationListener listener, 1892 PendingIntent intent, String packageName, String featureId, String listenerId) { 1893 if (request == null) { 1894 request = DEFAULT_LOCATION_REQUEST; 1895 } 1896 if (listenerId == null && intent != null) { 1897 listenerId = AppOpsManager.toReceiverId(intent); 1898 } 1899 1900 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId, 1901 listenerId); 1902 identity.enforceLocationPermission(); 1903 1904 WorkSource workSource = request.getWorkSource(); 1905 if (workSource != null && !workSource.isEmpty()) { 1906 mContext.enforceCallingOrSelfPermission( 1907 Manifest.permission.UPDATE_DEVICE_STATS, null); 1908 } 1909 boolean hideFromAppOps = request.getHideFromAppOps(); 1910 if (hideFromAppOps) { 1911 mContext.enforceCallingOrSelfPermission( 1912 Manifest.permission.UPDATE_APP_OPS_STATS, null); 1913 } 1914 if (request.isLocationSettingsIgnored()) { 1915 mContext.enforceCallingOrSelfPermission( 1916 Manifest.permission.WRITE_SECURE_SETTINGS, null); 1917 } 1918 boolean callerHasLocationHardwarePermission = 1919 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE) 1920 == PERMISSION_GRANTED; 1921 LocationRequest sanitizedRequest = createSanitizedRequest(request, 1922 identity, 1923 callerHasLocationHardwarePermission); 1924 1925 if (intent == null && listener == null) { 1926 throw new IllegalArgumentException("need either listener or intent"); 1927 } else if (intent != null && listener != null) { 1928 throw new IllegalArgumentException( 1929 "cannot register both listener and intent"); 1930 } 1931 1932 mLocationUsageLogger.logLocationApiUsage( 1933 LocationStatsEnums.USAGE_STARTED, 1934 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES, 1935 packageName, request, listener != null, intent != null, 1936 /* geofence= */ null, 1937 mAppForegroundHelper.getImportance(identity.uid)); 1938 1939 synchronized (mLock) { 1940 Receiver receiver; 1941 if (intent != null) { 1942 receiver = getReceiverLocked(intent, identity, workSource, hideFromAppOps); 1943 } else { 1944 receiver = getReceiverLocked(listener, identity, workSource, hideFromAppOps); 1945 } 1946 if (receiver != null) { 1947 requestLocationUpdatesLocked(sanitizedRequest, receiver); 1948 } 1949 } 1950 } 1951 1952 @GuardedBy("mLock") requestLocationUpdatesLocked(LocationRequest request, Receiver receiver)1953 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver) { 1954 // Figure out the provider. Either its explicitly request (legacy use cases), or 1955 // use the fused provider 1956 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1957 String name = request.getProvider(); 1958 if (name == null) { 1959 throw new IllegalArgumentException("provider name must not be null"); 1960 } 1961 1962 LocationProviderManager manager = getLocationProviderManager(name); 1963 if (manager == null) { 1964 throw new IllegalArgumentException("provider doesn't exist: " + name); 1965 } 1966 1967 UpdateRecord record = new UpdateRecord(name, request, receiver); 1968 1969 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record); 1970 if (oldRecord != null) { 1971 oldRecord.disposeLocked(false); 1972 } 1973 1974 long identity = Binder.clearCallingIdentity(); 1975 try { 1976 int userId = UserHandle.getUserId(receiver.mCallerIdentity.uid); 1977 if (!manager.isEnabled(userId) && !isSettingsExempt(record)) { 1978 // Notify the listener that updates are currently disabled - but only if the request 1979 // does not ignore location settings 1980 receiver.callProviderEnabledLocked(name, false); 1981 } 1982 1983 applyRequirementsLocked(name); 1984 1985 // Update the monitoring here just in case multiple location requests were added to the 1986 // same receiver (this request may be high power and the initial might not have been). 1987 receiver.updateMonitoring(true); 1988 } finally { 1989 Binder.restoreCallingIdentity(identity); 1990 } 1991 } 1992 1993 @Override removeUpdates(ILocationListener listener, PendingIntent intent)1994 public void removeUpdates(ILocationListener listener, PendingIntent intent) { 1995 if (intent == null && listener == null) { 1996 throw new IllegalArgumentException("need either listener or intent"); 1997 } else if (intent != null && listener != null) { 1998 throw new IllegalArgumentException("cannot register both listener and intent"); 1999 } 2000 2001 synchronized (mLock) { 2002 Receiver receiver; 2003 if (intent != null) { 2004 receiver = getReceiverLocked(intent, null, null, false); 2005 } else { 2006 receiver = getReceiverLocked(listener, null, null, false); 2007 } 2008 2009 if (receiver != null) { 2010 removeUpdatesLocked(receiver); 2011 } 2012 } 2013 } 2014 2015 @GuardedBy("mLock") removeUpdatesLocked(Receiver receiver)2016 private void removeUpdatesLocked(Receiver receiver) { 2017 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver))); 2018 2019 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 2020 receiver.unlinkFromListenerDeathNotificationLocked( 2021 receiver.getListener().asBinder()); 2022 receiver.clearPendingBroadcastsLocked(); 2023 } 2024 2025 receiver.updateMonitoring(false); 2026 2027 // Record which providers were associated with this listener 2028 HashSet<String> providers = new HashSet<>(); 2029 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords; 2030 if (oldRecords != null) { 2031 // Call dispose() on the obsolete update records. 2032 for (UpdateRecord record : oldRecords.values()) { 2033 // Update statistics for historical location requests by package/provider 2034 record.disposeLocked(false); 2035 } 2036 // Accumulate providers 2037 providers.addAll(oldRecords.keySet()); 2038 } 2039 2040 // update provider 2041 for (String provider : providers) { 2042 applyRequirementsLocked(provider); 2043 } 2044 } 2045 2046 @Override getLastLocation(LocationRequest request, String packageName, String featureId)2047 public Location getLastLocation(LocationRequest request, String packageName, String featureId) { 2048 if (request == null) { 2049 request = DEFAULT_LOCATION_REQUEST; 2050 } 2051 2052 // unsafe is ok because app ops will verify the package name 2053 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId); 2054 identity.enforceLocationPermission(); 2055 2056 if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId, identity.packageName)) { 2057 return null; 2058 } 2059 if (!mUserInfoHelper.isCurrentUserId(identity.userId)) { 2060 return null; 2061 } 2062 2063 synchronized (mLock) { 2064 LocationProviderManager manager = getLocationProviderManager(request.getProvider()); 2065 if (manager == null) { 2066 return null; 2067 } 2068 if (!manager.isEnabled(identity.userId) && !request.isLocationSettingsIgnored()) { 2069 return null; 2070 } 2071 2072 // appops check should always be right before delivery 2073 if (!mAppOpsHelper.noteLocationAccess(identity)) { 2074 return null; 2075 } 2076 2077 Location location = manager.getLastLocation(identity.userId, identity.permissionLevel); 2078 2079 // make a defensive copy - the client could be in the same process as us 2080 return location != null ? new Location(location) : null; 2081 } 2082 } 2083 2084 @Nullable 2085 @Override getCurrentLocation(LocationRequest locationRequest, ILocationListener listener, String packageName, String featureId, String listenerId)2086 public ICancellationSignal getCurrentLocation(LocationRequest locationRequest, 2087 ILocationListener listener, String packageName, String featureId, String listenerId) { 2088 ICancellationSignal remoteCancellationSignal = CancellationSignal.createTransport(); 2089 2090 // side effect of validating locationRequest and packageName 2091 Location lastLocation = getLastLocation(locationRequest, packageName, featureId); 2092 if (lastLocation != null) { 2093 long locationAgeMs = NANOSECONDS.toMillis( 2094 SystemClock.elapsedRealtimeNanos() - lastLocation.getElapsedRealtimeNanos()); 2095 2096 if (locationAgeMs < MAX_CURRENT_LOCATION_AGE_MS) { 2097 try { 2098 listener.onLocationChanged(lastLocation); 2099 return remoteCancellationSignal; 2100 } catch (RemoteException e) { 2101 Log.w(TAG, e); 2102 return null; 2103 } 2104 } 2105 2106 if (!mAppForegroundHelper.isAppForeground(Binder.getCallingUid())) { 2107 if (locationAgeMs < mSettingsHelper.getBackgroundThrottleIntervalMs()) { 2108 // not allowed to request new locations, so we can't return anything 2109 return null; 2110 } 2111 } 2112 } 2113 2114 requestLocationUpdates(locationRequest, listener, null, packageName, featureId, listenerId); 2115 CancellationSignal cancellationSignal = CancellationSignal.fromTransport( 2116 remoteCancellationSignal); 2117 cancellationSignal.setOnCancelListener(() -> removeUpdates(listener, null)); 2118 return remoteCancellationSignal; 2119 } 2120 2121 @Override getGnssTimeMillis()2122 public LocationTime getGnssTimeMillis() { 2123 synchronized (mLock) { 2124 LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER); 2125 if (gpsManager == null) { 2126 return null; 2127 } 2128 2129 Location location = gpsManager.getLastLocation(UserHandle.getCallingUserId(), 2130 PERMISSION_FINE); 2131 if (location == null) { 2132 return null; 2133 } 2134 2135 long currentNanos = SystemClock.elapsedRealtimeNanos(); 2136 long deltaMs = NANOSECONDS.toMillis(location.getElapsedRealtimeAgeNanos(currentNanos)); 2137 return new LocationTime(location.getTime() + deltaMs, currentNanos); 2138 } 2139 } 2140 2141 @Override injectLocation(Location location)2142 public void injectLocation(Location location) { 2143 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null); 2144 mContext.enforceCallingPermission(ACCESS_FINE_LOCATION, null); 2145 2146 Preconditions.checkArgument(location.isComplete()); 2147 2148 int userId = UserHandle.getCallingUserId(); 2149 synchronized (mLock) { 2150 LocationProviderManager manager = getLocationProviderManager(location.getProvider()); 2151 if (manager != null && manager.isEnabled(userId)) { 2152 manager.injectLastLocation(Objects.requireNonNull(location), userId); 2153 } 2154 } 2155 } 2156 2157 @Override requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, String packageName, String featureId)2158 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, 2159 String packageName, String featureId) { 2160 if (request == null) { 2161 request = DEFAULT_LOCATION_REQUEST; 2162 } 2163 2164 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId, 2165 AppOpsManager.toReceiverId(intent)); 2166 identity.enforceLocationPermission(); 2167 2168 Objects.requireNonNull(intent); 2169 2170 boolean callerHasLocationHardwarePermission = 2171 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE) 2172 == PERMISSION_GRANTED; 2173 LocationRequest sanitizedRequest = createSanitizedRequest(request, identity, 2174 callerHasLocationHardwarePermission); 2175 2176 if (D) { 2177 Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent); 2178 } 2179 2180 if (identity.userId != UserHandle.USER_SYSTEM) { 2181 // temporary measure until geofences work for secondary users 2182 Log.w(TAG, "proximity alerts are currently available only to the primary user"); 2183 return; 2184 } 2185 2186 mLocationUsageLogger.logLocationApiUsage( 2187 LocationStatsEnums.USAGE_STARTED, 2188 LocationStatsEnums.API_REQUEST_GEOFENCE, 2189 packageName, 2190 request, 2191 /* hasListener= */ false, 2192 true, 2193 geofence, 2194 mAppForegroundHelper.getImportance(identity.uid)); 2195 2196 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, identity); 2197 } 2198 2199 @Override removeGeofence(Geofence geofence, PendingIntent intent, String packageName)2200 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { 2201 if (intent == null) { 2202 throw new IllegalArgumentException("invalid pending intent: " + null); 2203 } 2204 2205 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); 2206 2207 mLocationUsageLogger.logLocationApiUsage( 2208 LocationStatsEnums.USAGE_ENDED, 2209 LocationStatsEnums.API_REQUEST_GEOFENCE, 2210 packageName, 2211 /* LocationRequest= */ null, 2212 /* hasListener= */ false, 2213 true, 2214 geofence, 2215 mAppForegroundHelper.getImportance(Binder.getCallingUid())); 2216 2217 // geo-fence manager uses the public location API, need to clear identity 2218 long identity = Binder.clearCallingIdentity(); 2219 try { 2220 mGeofenceManager.removeFence(geofence, intent); 2221 } finally { 2222 Binder.restoreCallingIdentity(identity); 2223 } 2224 } 2225 2226 @Override registerGnssStatusCallback(IGnssStatusListener listener, String packageName, String featureId)2227 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName, 2228 String featureId) { 2229 return mGnssManagerService != null && mGnssManagerService.registerGnssStatusCallback( 2230 listener, packageName, featureId); 2231 } 2232 2233 @Override unregisterGnssStatusCallback(IGnssStatusListener listener)2234 public void unregisterGnssStatusCallback(IGnssStatusListener listener) { 2235 if (mGnssManagerService != null) mGnssManagerService.unregisterGnssStatusCallback(listener); 2236 } 2237 2238 @Override addGnssMeasurementsListener(@ullable GnssRequest request, IGnssMeasurementsListener listener, String packageName, String featureId)2239 public boolean addGnssMeasurementsListener(@Nullable GnssRequest request, 2240 IGnssMeasurementsListener listener, String packageName, String featureId) { 2241 return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener( 2242 request, listener, packageName, featureId); 2243 } 2244 2245 @Override removeGnssMeasurementsListener(IGnssMeasurementsListener listener)2246 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { 2247 if (mGnssManagerService != null) { 2248 mGnssManagerService.removeGnssMeasurementsListener( 2249 listener); 2250 } 2251 } 2252 2253 @Override injectGnssMeasurementCorrections( GnssMeasurementCorrections measurementCorrections, String packageName)2254 public void injectGnssMeasurementCorrections( 2255 GnssMeasurementCorrections measurementCorrections, String packageName) { 2256 if (mGnssManagerService != null) { 2257 mGnssManagerService.injectGnssMeasurementCorrections(measurementCorrections, 2258 packageName); 2259 } 2260 } 2261 2262 @Override getGnssCapabilities()2263 public long getGnssCapabilities() { 2264 return mGnssManagerService == null ? GnssCapabilities.INVALID_CAPABILITIES 2265 : mGnssManagerService.getGnssCapabilities(); 2266 } 2267 2268 @Override addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, String featureId)2269 public boolean addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, 2270 String packageName, String featureId) { 2271 2272 return mGnssManagerService != null && mGnssManagerService.addGnssAntennaInfoListener( 2273 listener, packageName, featureId); 2274 } 2275 2276 @Override removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener)2277 public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) { 2278 if (mGnssManagerService != null) { 2279 mGnssManagerService.removeGnssAntennaInfoListener(listener); 2280 } 2281 } 2282 2283 @Override addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, String packageName, String featureId)2284 public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, 2285 String packageName, String featureId) { 2286 return mGnssManagerService != null && mGnssManagerService.addGnssNavigationMessageListener( 2287 listener, packageName, featureId); 2288 } 2289 2290 @Override removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)2291 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { 2292 if (mGnssManagerService != null) { 2293 mGnssManagerService.removeGnssNavigationMessageListener( 2294 listener); 2295 } 2296 } 2297 2298 @Override sendExtraCommand(String provider, String command, Bundle extras)2299 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 2300 CallerIdentity.enforceCallingOrSelfLocationPermission(mContext); 2301 mContext.enforceCallingOrSelfPermission( 2302 Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS, null); 2303 2304 LocationProviderManager manager = getLocationProviderManager( 2305 Objects.requireNonNull(provider)); 2306 if (manager != null) { 2307 manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), 2308 Objects.requireNonNull(command), extras); 2309 } 2310 2311 mLocationUsageLogger.logLocationApiUsage( 2312 LocationStatsEnums.USAGE_STARTED, 2313 LocationStatsEnums.API_SEND_EXTRA_COMMAND, 2314 provider); 2315 2316 mLocationUsageLogger.logLocationApiUsage( 2317 LocationStatsEnums.USAGE_ENDED, 2318 LocationStatsEnums.API_SEND_EXTRA_COMMAND, 2319 provider); 2320 2321 return true; 2322 } 2323 2324 @Override getProviderProperties(String providerName)2325 public ProviderProperties getProviderProperties(String providerName) { 2326 LocationProviderManager manager = getLocationProviderManager(providerName); 2327 if (manager == null) { 2328 return null; 2329 } 2330 return manager.getProperties(); 2331 } 2332 2333 @Override isProviderPackage(String packageName)2334 public boolean isProviderPackage(String packageName) { 2335 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null); 2336 return mLocalService.isProviderPackage(packageName); 2337 } 2338 2339 @Override getProviderPackages(String providerName)2340 public List<String> getProviderPackages(String providerName) { 2341 mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_DEVICE_CONFIG, null); 2342 LocationProviderManager manager = getLocationProviderManager(providerName); 2343 return manager == null ? Collections.emptyList() : new ArrayList<>(manager.getPackages()); 2344 } 2345 2346 @Override setExtraLocationControllerPackage(String packageName)2347 public void setExtraLocationControllerPackage(String packageName) { 2348 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, 2349 Manifest.permission.LOCATION_HARDWARE + " permission required"); 2350 synchronized (mLock) { 2351 mExtraLocationControllerPackage = packageName; 2352 } 2353 } 2354 2355 @Override getExtraLocationControllerPackage()2356 public String getExtraLocationControllerPackage() { 2357 synchronized (mLock) { 2358 return mExtraLocationControllerPackage; 2359 } 2360 } 2361 2362 @Override setExtraLocationControllerPackageEnabled(boolean enabled)2363 public void setExtraLocationControllerPackageEnabled(boolean enabled) { 2364 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, 2365 Manifest.permission.LOCATION_HARDWARE + " permission required"); 2366 synchronized (mLock) { 2367 mExtraLocationControllerPackageEnabled = enabled; 2368 } 2369 } 2370 2371 @Override isExtraLocationControllerPackageEnabled()2372 public boolean isExtraLocationControllerPackageEnabled() { 2373 synchronized (mLock) { 2374 return mExtraLocationControllerPackageEnabled 2375 && (mExtraLocationControllerPackage != null); 2376 } 2377 } 2378 2379 @Override setLocationEnabledForUser(boolean enabled, int userId)2380 public void setLocationEnabledForUser(boolean enabled, int userId) { 2381 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 2382 userId, false, false, "setLocationEnabledForUser", null); 2383 2384 mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS, null); 2385 2386 LocationManager.invalidateLocalLocationEnabledCaches(); 2387 mSettingsHelper.setLocationEnabled(enabled, userId); 2388 } 2389 2390 @Override isLocationEnabledForUser(int userId)2391 public boolean isLocationEnabledForUser(int userId) { 2392 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 2393 userId, false, false, "isLocationEnabledForUser", null); 2394 return mSettingsHelper.isLocationEnabled(userId); 2395 } 2396 2397 @Override isProviderEnabledForUser(String provider, int userId)2398 public boolean isProviderEnabledForUser(String provider, int userId) { 2399 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 2400 userId, false, false, "isProviderEnabledForUser", null); 2401 2402 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, 2403 // so we discourage its use 2404 if (FUSED_PROVIDER.equals(provider)) return false; 2405 2406 return mLocalService.isProviderEnabledForUser(provider, userId); 2407 } 2408 2409 @GuardedBy("mLock") shouldBroadcastSafeLocked( Location loc, Location lastLoc, UpdateRecord record, long now)2410 private static boolean shouldBroadcastSafeLocked( 2411 Location loc, Location lastLoc, UpdateRecord record, long now) { 2412 // Always broadcast the first update 2413 if (lastLoc == null) { 2414 return true; 2415 } 2416 2417 // Check whether sufficient time has passed 2418 long minTime = record.mRealRequest.getFastestInterval(); 2419 long deltaMs = NANOSECONDS.toMillis( 2420 loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()); 2421 if (deltaMs < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 2422 return false; 2423 } 2424 2425 // Check whether sufficient distance has been traveled 2426 double minDistance = record.mRealRequest.getSmallestDisplacement(); 2427 if (minDistance > 0.0) { 2428 if (loc.distanceTo(lastLoc) <= minDistance) { 2429 return false; 2430 } 2431 } 2432 2433 // Check whether sufficient number of udpates is left 2434 if (record.mRealRequest.getNumUpdates() <= 0) { 2435 return false; 2436 } 2437 2438 // Check whether the expiry date has passed 2439 return record.mExpirationRealtimeMs >= now; 2440 } 2441 2442 @GuardedBy("mLock") handleLocationChangedLocked(LocationProviderManager manager, Location fineLocation, Location coarseLocation)2443 private void handleLocationChangedLocked(LocationProviderManager manager, Location fineLocation, 2444 Location coarseLocation) { 2445 if (!mProviderManagers.contains(manager)) { 2446 Log.w(TAG, "received location from unknown provider: " + manager.getName()); 2447 return; 2448 } 2449 2450 // notify passive provider 2451 if (manager != mPassiveManager) { 2452 mPassiveManager.updateLocation(fineLocation); 2453 } 2454 2455 long now = SystemClock.elapsedRealtime(); 2456 2457 ArrayList<UpdateRecord> records = mRecordsByProvider.get(manager.getName()); 2458 if (records == null || records.size() == 0) return; 2459 2460 ArrayList<Receiver> deadReceivers = null; 2461 ArrayList<UpdateRecord> deadUpdateRecords = null; 2462 2463 // Broadcast location to all listeners 2464 for (UpdateRecord r : records) { 2465 Receiver receiver = r.mReceiver; 2466 CallerIdentity identity = receiver.mCallerIdentity; 2467 boolean receiverDead = false; 2468 2469 2470 if (!manager.isEnabled(identity.userId) && !isSettingsExempt(r)) { 2471 continue; 2472 } 2473 2474 if (!mUserInfoHelper.isCurrentUserId(identity.userId) 2475 && !isProviderPackage(identity.packageName)) { 2476 continue; 2477 } 2478 2479 if (mSettingsHelper.isLocationPackageBlacklisted(identity.userId, 2480 identity.packageName)) { 2481 continue; 2482 } 2483 2484 Location location; 2485 switch (identity.permissionLevel) { 2486 case PERMISSION_COARSE: 2487 location = coarseLocation; 2488 break; 2489 case PERMISSION_FINE: 2490 location = fineLocation; 2491 break; 2492 default: 2493 throw new AssertionError(); 2494 } 2495 2496 if (shouldBroadcastSafeLocked(location, r.mLastFixBroadcast, r, now)) { 2497 r.mLastFixBroadcast = location; 2498 2499 // appops check should always be right before delivery 2500 if (!mAppOpsHelper.noteLocationAccess(receiver.mCallerIdentity)) { 2501 continue; 2502 } 2503 2504 if (!receiver.callLocationChangedLocked(location)) { 2505 receiverDead = true; 2506 } 2507 r.mRealRequest.decrementNumUpdates(); 2508 } 2509 2510 // track expired records 2511 if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) { 2512 // notify the client it can remove this listener 2513 r.mReceiver.callRemovedLocked(); 2514 if (deadUpdateRecords == null) { 2515 deadUpdateRecords = new ArrayList<>(); 2516 } 2517 deadUpdateRecords.add(r); 2518 } 2519 // track dead receivers 2520 if (receiverDead) { 2521 if (deadReceivers == null) { 2522 deadReceivers = new ArrayList<>(); 2523 } 2524 if (!deadReceivers.contains(receiver)) { 2525 deadReceivers.add(receiver); 2526 } 2527 } 2528 } 2529 2530 // remove dead records and receivers outside the loop 2531 if (deadReceivers != null) { 2532 for (Receiver receiver : deadReceivers) { 2533 removeUpdatesLocked(receiver); 2534 } 2535 } 2536 if (deadUpdateRecords != null) { 2537 for (UpdateRecord r : deadUpdateRecords) { 2538 r.disposeLocked(true); 2539 } 2540 applyRequirementsLocked(manager); 2541 } 2542 } 2543 2544 // Geocoder 2545 2546 @Override geocoderIsPresent()2547 public boolean geocoderIsPresent() { 2548 return mGeocodeProvider != null; 2549 } 2550 2551 @Override getFromLocation(double latitude, double longitude, int maxResults, GeocoderParams params, List<Address> addrs)2552 public String getFromLocation(double latitude, double longitude, int maxResults, 2553 GeocoderParams params, List<Address> addrs) { 2554 if (mGeocodeProvider != null) { 2555 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 2556 params, addrs); 2557 } 2558 return null; 2559 } 2560 2561 @Override getFromLocationName(String locationName, double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude, int maxResults, GeocoderParams params, List<Address> addrs)2562 public String getFromLocationName(String locationName, 2563 double lowerLeftLatitude, double lowerLeftLongitude, 2564 double upperRightLatitude, double upperRightLongitude, int maxResults, 2565 GeocoderParams params, List<Address> addrs) { 2566 2567 if (mGeocodeProvider != null) { 2568 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 2569 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 2570 maxResults, params, addrs); 2571 } 2572 return null; 2573 } 2574 2575 // Mock Providers 2576 2577 @Override addTestProvider(String provider, ProviderProperties properties, String packageName, String featureId)2578 public void addTestProvider(String provider, ProviderProperties properties, 2579 String packageName, String featureId) { 2580 // unsafe is ok because app ops will verify the package name 2581 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId); 2582 if (!mAppOpsHelper.noteMockLocationAccess(identity)) { 2583 return; 2584 } 2585 2586 synchronized (mLock) { 2587 LocationProviderManager manager = getLocationProviderManager(provider); 2588 if (manager == null) { 2589 manager = new LocationProviderManager(provider); 2590 mProviderManagers.add(manager); 2591 } 2592 2593 manager.setMockProvider(new MockProvider(properties)); 2594 } 2595 } 2596 2597 @Override removeTestProvider(String provider, String packageName, String featureId)2598 public void removeTestProvider(String provider, String packageName, String featureId) { 2599 // unsafe is ok because app ops will verify the package name 2600 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId); 2601 if (!mAppOpsHelper.noteMockLocationAccess(identity)) { 2602 return; 2603 } 2604 2605 synchronized (mLock) { 2606 LocationProviderManager manager = getLocationProviderManager(provider); 2607 if (manager == null) { 2608 return; 2609 } 2610 2611 manager.setMockProvider(null); 2612 if (!manager.hasProvider()) { 2613 mProviderManagers.remove(manager); 2614 } 2615 } 2616 } 2617 2618 @Override setTestProviderLocation(String provider, Location location, String packageName, String featureId)2619 public void setTestProviderLocation(String provider, Location location, String packageName, 2620 String featureId) { 2621 // unsafe is ok because app ops will verify the package name 2622 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId); 2623 if (!mAppOpsHelper.noteMockLocationAccess(identity)) { 2624 return; 2625 } 2626 2627 Preconditions.checkArgument(location.isComplete(), 2628 "incomplete location object, missing timestamp or accuracy?"); 2629 2630 LocationProviderManager manager = getLocationProviderManager(provider); 2631 if (manager == null) { 2632 throw new IllegalArgumentException("provider doesn't exist: " + provider); 2633 } 2634 2635 manager.setMockProviderLocation(location); 2636 } 2637 2638 @Override setTestProviderEnabled(String provider, boolean enabled, String packageName, String featureId)2639 public void setTestProviderEnabled(String provider, boolean enabled, String packageName, 2640 String featureId) { 2641 // unsafe is ok because app ops will verify the package name 2642 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(mContext, packageName, featureId); 2643 if (!mAppOpsHelper.noteMockLocationAccess(identity)) { 2644 return; 2645 } 2646 2647 LocationProviderManager manager = getLocationProviderManager(provider); 2648 if (manager == null) { 2649 throw new IllegalArgumentException("provider doesn't exist: " + provider); 2650 } 2651 2652 manager.setMockProviderAllowed(enabled); 2653 } 2654 2655 @Override 2656 @NonNull getTestProviderCurrentRequests(String provider)2657 public List<LocationRequest> getTestProviderCurrentRequests(String provider) { 2658 LocationProviderManager manager = getLocationProviderManager(provider); 2659 if (manager == null) { 2660 throw new IllegalArgumentException("provider doesn't exist: " + provider); 2661 } 2662 2663 return manager.getMockProviderRequests(); 2664 } 2665 2666 @Override handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, ParcelFileDescriptor err, String[] args)2667 public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, 2668 ParcelFileDescriptor err, String[] args) { 2669 return new LocationShellCommand(this).exec( 2670 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), 2671 args); 2672 } 2673 2674 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2675 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2676 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) { 2677 return; 2678 } 2679 2680 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 2681 2682 synchronized (mLock) { 2683 if (mGnssManagerService != null && args.length > 0 && args[0].equals("--gnssmetrics")) { 2684 mGnssManagerService.dump(fd, pw, args); 2685 return; 2686 } 2687 2688 ipw.println("Location Manager State:"); 2689 ipw.increaseIndent(); 2690 ipw.print("Current System Time: " 2691 + TimeUtils.logTimeOfDay(System.currentTimeMillis())); 2692 ipw.println(", Current Elapsed Time: " 2693 + TimeUtils.formatDuration(SystemClock.elapsedRealtime())); 2694 2695 ipw.println("User Info:"); 2696 ipw.increaseIndent(); 2697 mUserInfoHelper.dump(fd, ipw, args); 2698 ipw.decreaseIndent(); 2699 2700 ipw.println("Location Settings:"); 2701 ipw.increaseIndent(); 2702 mSettingsHelper.dump(fd, ipw, args); 2703 ipw.decreaseIndent(); 2704 2705 ipw.println("Battery Saver Location Mode: " 2706 + locationPowerSaveModeToString(mBatterySaverMode)); 2707 2708 ipw.println("Location Listeners:"); 2709 ipw.increaseIndent(); 2710 for (Receiver receiver : mReceivers.values()) { 2711 ipw.println(receiver); 2712 } 2713 ipw.decreaseIndent(); 2714 2715 ipw.println("Active Records by Provider:"); 2716 ipw.increaseIndent(); 2717 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2718 ipw.println(entry.getKey() + ":"); 2719 ipw.increaseIndent(); 2720 for (UpdateRecord record : entry.getValue()) { 2721 ipw.println(record); 2722 } 2723 ipw.decreaseIndent(); 2724 } 2725 ipw.decreaseIndent(); 2726 2727 ipw.println("Historical Records by Provider:"); 2728 ipw.increaseIndent(); 2729 TreeMap<PackageProviderKey, PackageStatistics> sorted = new TreeMap<>( 2730 mRequestStatistics.statistics); 2731 for (Map.Entry<PackageProviderKey, PackageStatistics> entry 2732 : sorted.entrySet()) { 2733 ipw.println(entry.getKey() + ": " + entry.getValue()); 2734 } 2735 ipw.decreaseIndent(); 2736 2737 mRequestStatistics.history.dump(ipw); 2738 2739 if (mGeofenceManager != null) { 2740 ipw.println("Geofences:"); 2741 ipw.increaseIndent(); 2742 mGeofenceManager.dump(ipw); 2743 ipw.decreaseIndent(); 2744 } 2745 2746 if (mExtraLocationControllerPackage != null) { 2747 ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage 2748 + (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]")); 2749 } 2750 } 2751 2752 ipw.println("Location Providers:"); 2753 ipw.increaseIndent(); 2754 for (LocationProviderManager manager : mProviderManagers) { 2755 manager.dump(fd, ipw, args); 2756 } 2757 ipw.decreaseIndent(); 2758 2759 synchronized (mLock) { 2760 if (mGnssManagerService != null) { 2761 ipw.println("GNSS:"); 2762 ipw.increaseIndent(); 2763 mGnssManagerService.dump(fd, ipw, args); 2764 ipw.decreaseIndent(); 2765 } 2766 } 2767 } 2768 2769 private class LocalService extends LocationManagerInternal { 2770 2771 @Override isProviderEnabledForUser(@onNull String provider, int userId)2772 public boolean isProviderEnabledForUser(@NonNull String provider, int userId) { 2773 synchronized (mLock) { 2774 LocationProviderManager manager = getLocationProviderManager(provider); 2775 if (manager == null) { 2776 return false; 2777 } 2778 2779 return manager.isEnabled(userId); 2780 } 2781 } 2782 2783 @Override isProviderPackage(String packageName)2784 public boolean isProviderPackage(String packageName) { 2785 for (LocationProviderManager manager : mProviderManagers) { 2786 if (manager.getPackages().contains(packageName)) { 2787 return true; 2788 } 2789 } 2790 return false; 2791 } 2792 2793 @Override sendNiResponse(int notifId, int userResponse)2794 public void sendNiResponse(int notifId, int userResponse) { 2795 if (mGnssManagerService != null) { 2796 mGnssManagerService.sendNiResponse(notifId, userResponse); 2797 } 2798 } 2799 } 2800 } 2801