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.provider; 18 19 import static android.app.compat.CompatChanges.isChangeEnabled; 20 import static android.location.LocationManager.DELIVER_HISTORICAL_LOCATIONS; 21 import static android.location.LocationManager.GPS_PROVIDER; 22 import static android.location.LocationManager.KEY_FLUSH_COMPLETE; 23 import static android.location.LocationManager.KEY_LOCATIONS; 24 import static android.location.LocationManager.KEY_LOCATION_CHANGED; 25 import static android.location.LocationManager.KEY_PROVIDER_ENABLED; 26 import static android.location.LocationManager.PASSIVE_PROVIDER; 27 import static android.os.IPowerManager.LOCATION_MODE_NO_CHANGE; 28 import static android.os.PowerExemptionManager.REASON_LOCATION_PROVIDER; 29 import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; 30 import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF; 31 import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY; 32 import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF; 33 import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF; 34 35 import static com.android.server.location.LocationManagerService.D; 36 import static com.android.server.location.LocationManagerService.TAG; 37 import static com.android.server.location.LocationPermissions.PERMISSION_COARSE; 38 import static com.android.server.location.LocationPermissions.PERMISSION_FINE; 39 import static com.android.server.location.LocationPermissions.PERMISSION_NONE; 40 import static com.android.server.location.eventlog.LocationEventLog.EVENT_LOG; 41 42 import static java.lang.Math.max; 43 import static java.lang.Math.min; 44 45 import android.annotation.IntDef; 46 import android.annotation.Nullable; 47 import android.app.AlarmManager.OnAlarmListener; 48 import android.app.BroadcastOptions; 49 import android.app.PendingIntent; 50 import android.content.Context; 51 import android.content.Intent; 52 import android.location.ILocationCallback; 53 import android.location.ILocationListener; 54 import android.location.LastLocationRequest; 55 import android.location.Location; 56 import android.location.LocationManager; 57 import android.location.LocationManagerInternal; 58 import android.location.LocationManagerInternal.ProviderEnabledListener; 59 import android.location.LocationRequest; 60 import android.location.LocationResult; 61 import android.location.provider.IProviderRequestListener; 62 import android.location.provider.ProviderProperties; 63 import android.location.provider.ProviderRequest; 64 import android.location.util.identity.CallerIdentity; 65 import android.os.Binder; 66 import android.os.Build; 67 import android.os.Bundle; 68 import android.os.CancellationSignal; 69 import android.os.IBinder; 70 import android.os.ICancellationSignal; 71 import android.os.IRemoteCallback; 72 import android.os.PowerManager; 73 import android.os.PowerManager.LocationPowerSaveMode; 74 import android.os.Process; 75 import android.os.RemoteException; 76 import android.os.SystemClock; 77 import android.os.UserHandle; 78 import android.os.WorkSource; 79 import android.stats.location.LocationStatsEnums; 80 import android.text.TextUtils; 81 import android.util.ArraySet; 82 import android.util.EventLog; 83 import android.util.IndentingPrintWriter; 84 import android.util.Log; 85 import android.util.SparseArray; 86 import android.util.SparseBooleanArray; 87 import android.util.TimeUtils; 88 89 import com.android.internal.annotations.GuardedBy; 90 import com.android.internal.util.Preconditions; 91 import com.android.server.FgThread; 92 import com.android.server.LocalServices; 93 import com.android.server.location.LocationPermissions; 94 import com.android.server.location.LocationPermissions.PermissionLevel; 95 import com.android.server.location.fudger.LocationFudger; 96 import com.android.server.location.injector.AlarmHelper; 97 import com.android.server.location.injector.AppForegroundHelper; 98 import com.android.server.location.injector.AppForegroundHelper.AppForegroundListener; 99 import com.android.server.location.injector.AppOpsHelper; 100 import com.android.server.location.injector.Injector; 101 import com.android.server.location.injector.LocationAttributionHelper; 102 import com.android.server.location.injector.LocationPermissionsHelper; 103 import com.android.server.location.injector.LocationPermissionsHelper.LocationPermissionsListener; 104 import com.android.server.location.injector.LocationPowerSaveModeHelper; 105 import com.android.server.location.injector.LocationPowerSaveModeHelper.LocationPowerSaveModeChangedListener; 106 import com.android.server.location.injector.LocationUsageLogger; 107 import com.android.server.location.injector.ScreenInteractiveHelper; 108 import com.android.server.location.injector.ScreenInteractiveHelper.ScreenInteractiveChangedListener; 109 import com.android.server.location.injector.SettingsHelper; 110 import com.android.server.location.injector.SettingsHelper.GlobalSettingChangedListener; 111 import com.android.server.location.injector.SettingsHelper.UserSettingChangedListener; 112 import com.android.server.location.injector.UserInfoHelper; 113 import com.android.server.location.injector.UserInfoHelper.UserListener; 114 import com.android.server.location.listeners.ListenerMultiplexer; 115 import com.android.server.location.listeners.RemoteListenerRegistration; 116 import com.android.server.location.settings.LocationSettings; 117 import com.android.server.location.settings.LocationUserSettings; 118 119 import java.io.FileDescriptor; 120 import java.lang.annotation.Retention; 121 import java.lang.annotation.RetentionPolicy; 122 import java.util.ArrayList; 123 import java.util.Collection; 124 import java.util.Objects; 125 import java.util.concurrent.CopyOnWriteArrayList; 126 import java.util.function.Predicate; 127 128 /** 129 * Manages all aspects of a single location provider. 130 */ 131 public class LocationProviderManager extends 132 ListenerMultiplexer<Object, LocationProviderManager.LocationTransport, 133 LocationProviderManager.Registration, ProviderRequest> implements 134 AbstractLocationProvider.Listener { 135 136 private static final String WAKELOCK_TAG = "*location*"; 137 private static final long WAKELOCK_TIMEOUT_MS = 30 * 1000; 138 139 // duration PI location clients are put on the allowlist to start a fg service 140 private static final long TEMPORARY_APP_ALLOWLIST_DURATION_MS = 10 * 1000; 141 142 // fastest interval at which clients may receive coarse locations 143 private static final long MIN_COARSE_INTERVAL_MS = 10 * 60 * 1000; 144 145 // max interval to be considered "high power" request 146 private static final long MAX_HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000; 147 148 // max age of a location before it is no longer considered "current" 149 private static final long MAX_CURRENT_LOCATION_AGE_MS = 30 * 1000; 150 151 // max timeout allowed for getting the current location 152 private static final long MAX_GET_CURRENT_LOCATION_TIMEOUT_MS = 30 * 1000; 153 154 // max jitter allowed for min update interval as a percentage of the interval 155 private static final float FASTEST_INTERVAL_JITTER_PERCENTAGE = .10f; 156 157 // max absolute jitter allowed for min update interval evaluation 158 private static final int MAX_FASTEST_INTERVAL_JITTER_MS = 30 * 1000; 159 160 // minimum amount of request delay in order to respect the delay, below this value the request 161 // will just be scheduled immediately 162 private static final long MIN_REQUEST_DELAY_MS = 30 * 1000; 163 164 @Retention(RetentionPolicy.SOURCE) 165 @IntDef({STATE_STARTED, STATE_STOPPING, STATE_STOPPED}) 166 private @interface State {} 167 168 private static final int STATE_STARTED = 0; 169 private static final int STATE_STOPPING = 1; 170 private static final int STATE_STOPPED = 2; 171 172 public interface StateChangedListener { onStateChanged(String provider, AbstractLocationProvider.State oldState, AbstractLocationProvider.State newState)173 void onStateChanged(String provider, AbstractLocationProvider.State oldState, 174 AbstractLocationProvider.State newState); 175 } 176 177 protected interface LocationTransport { 178 deliverOnLocationChanged(LocationResult locationResult, @Nullable Runnable onCompleteCallback)179 void deliverOnLocationChanged(LocationResult locationResult, 180 @Nullable Runnable onCompleteCallback) throws Exception; deliverOnFlushComplete(int requestCode)181 void deliverOnFlushComplete(int requestCode) throws Exception; 182 } 183 184 protected interface ProviderTransport { 185 deliverOnProviderEnabledChanged(String provider, boolean enabled)186 void deliverOnProviderEnabledChanged(String provider, boolean enabled) throws Exception; 187 } 188 189 protected static final class LocationListenerTransport implements LocationTransport, 190 ProviderTransport { 191 192 private final ILocationListener mListener; 193 LocationListenerTransport(ILocationListener listener)194 protected LocationListenerTransport(ILocationListener listener) { 195 mListener = Objects.requireNonNull(listener); 196 } 197 198 @Override deliverOnLocationChanged(LocationResult locationResult, @Nullable Runnable onCompleteCallback)199 public void deliverOnLocationChanged(LocationResult locationResult, 200 @Nullable Runnable onCompleteCallback) throws RemoteException { 201 mListener.onLocationChanged(locationResult.asList(), 202 SingleUseCallback.wrap(onCompleteCallback)); 203 } 204 205 @Override deliverOnFlushComplete(int requestCode)206 public void deliverOnFlushComplete(int requestCode) throws RemoteException { 207 mListener.onFlushComplete(requestCode); 208 } 209 210 @Override deliverOnProviderEnabledChanged(String provider, boolean enabled)211 public void deliverOnProviderEnabledChanged(String provider, boolean enabled) 212 throws RemoteException { 213 mListener.onProviderEnabledChanged(provider, enabled); 214 } 215 } 216 217 protected static final class LocationPendingIntentTransport implements LocationTransport, 218 ProviderTransport { 219 220 private final Context mContext; 221 private final PendingIntent mPendingIntent; 222 LocationPendingIntentTransport(Context context, PendingIntent pendingIntent)223 public LocationPendingIntentTransport(Context context, PendingIntent pendingIntent) { 224 mContext = context; 225 mPendingIntent = pendingIntent; 226 } 227 228 @Override deliverOnLocationChanged(LocationResult locationResult, @Nullable Runnable onCompleteCallback)229 public void deliverOnLocationChanged(LocationResult locationResult, 230 @Nullable Runnable onCompleteCallback) 231 throws PendingIntent.CanceledException { 232 BroadcastOptions options = BroadcastOptions.makeBasic(); 233 options.setDontSendToRestrictedApps(true); 234 // allows apps to start a fg service in response to a location PI 235 options.setTemporaryAppAllowlist(TEMPORARY_APP_ALLOWLIST_DURATION_MS, 236 TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, 237 REASON_LOCATION_PROVIDER, 238 ""); 239 240 Intent intent = new Intent().putExtra(KEY_LOCATION_CHANGED, 241 locationResult.getLastLocation()); 242 if (locationResult.size() > 1) { 243 intent.putExtra(KEY_LOCATIONS, locationResult.asList().toArray(new Location[0])); 244 } 245 246 mPendingIntent.send( 247 mContext, 248 0, 249 intent, 250 onCompleteCallback != null ? (pI, i, rC, rD, rE) -> onCompleteCallback.run() 251 : null, 252 null, 253 null, 254 options.toBundle()); 255 } 256 257 @Override deliverOnFlushComplete(int requestCode)258 public void deliverOnFlushComplete(int requestCode) throws PendingIntent.CanceledException { 259 BroadcastOptions options = BroadcastOptions.makeBasic(); 260 options.setDontSendToRestrictedApps(true); 261 262 mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_FLUSH_COMPLETE, requestCode), 263 null, null, null, options.toBundle()); 264 } 265 266 @Override deliverOnProviderEnabledChanged(String provider, boolean enabled)267 public void deliverOnProviderEnabledChanged(String provider, boolean enabled) 268 throws PendingIntent.CanceledException { 269 BroadcastOptions options = BroadcastOptions.makeBasic(); 270 options.setDontSendToRestrictedApps(true); 271 272 mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_PROVIDER_ENABLED, enabled), 273 null, null, null, options.toBundle()); 274 } 275 } 276 277 protected static final class GetCurrentLocationTransport implements LocationTransport { 278 279 private final ILocationCallback mCallback; 280 GetCurrentLocationTransport(ILocationCallback callback)281 protected GetCurrentLocationTransport(ILocationCallback callback) { 282 mCallback = Objects.requireNonNull(callback); 283 } 284 285 @Override deliverOnLocationChanged(@ullable LocationResult locationResult, @Nullable Runnable onCompleteCallback)286 public void deliverOnLocationChanged(@Nullable LocationResult locationResult, 287 @Nullable Runnable onCompleteCallback) 288 throws RemoteException { 289 // ILocationCallback doesn't currently support completion callbacks 290 Preconditions.checkState(onCompleteCallback == null); 291 if (locationResult != null) { 292 mCallback.onLocation(locationResult.getLastLocation()); 293 } else { 294 mCallback.onLocation(null); 295 } 296 } 297 298 @Override deliverOnFlushComplete(int requestCode)299 public void deliverOnFlushComplete(int requestCode) {} 300 } 301 302 protected abstract class Registration extends RemoteListenerRegistration<LocationRequest, 303 LocationTransport> { 304 305 private final @PermissionLevel int mPermissionLevel; 306 307 // we cache these values because checking/calculating on the fly is more expensive 308 private boolean mPermitted; 309 private boolean mForeground; 310 private LocationRequest mProviderLocationRequest; 311 private boolean mIsUsingHighPower; 312 313 private @Nullable Location mLastLocation = null; 314 Registration(LocationRequest request, CallerIdentity identity, LocationTransport transport, @PermissionLevel int permissionLevel)315 protected Registration(LocationRequest request, CallerIdentity identity, 316 LocationTransport transport, @PermissionLevel int permissionLevel) { 317 super(Objects.requireNonNull(request), identity, transport); 318 319 Preconditions.checkArgument(identity.getListenerId() != null); 320 Preconditions.checkArgument(permissionLevel > PERMISSION_NONE); 321 Preconditions.checkArgument(!request.getWorkSource().isEmpty()); 322 323 mPermissionLevel = permissionLevel; 324 mProviderLocationRequest = request; 325 } 326 327 @GuardedBy("mLock") 328 @Override onRemovableListenerRegister()329 protected final void onRemovableListenerRegister() { 330 if (Build.IS_DEBUGGABLE) { 331 Preconditions.checkState(Thread.holdsLock(mLock)); 332 } 333 334 if (D) { 335 Log.d(TAG, mName + " provider added registration from " + getIdentity() + " -> " 336 + getRequest()); 337 } 338 339 EVENT_LOG.logProviderClientRegistered(mName, getIdentity(), super.getRequest()); 340 341 // initialization order is important as there are ordering dependencies 342 mPermitted = mLocationPermissionsHelper.hasLocationPermissions(mPermissionLevel, 343 getIdentity()); 344 mForeground = mAppForegroundHelper.isAppForeground(getIdentity().getUid()); 345 mProviderLocationRequest = calculateProviderLocationRequest(); 346 mIsUsingHighPower = isUsingHighPower(); 347 348 onProviderListenerRegister(); 349 350 if (mForeground) { 351 EVENT_LOG.logProviderClientForeground(mName, getIdentity()); 352 } 353 } 354 355 @GuardedBy("mLock") 356 @Override onRemovableListenerUnregister()357 protected final void onRemovableListenerUnregister() { 358 if (Build.IS_DEBUGGABLE) { 359 Preconditions.checkState(Thread.holdsLock(mLock)); 360 } 361 362 onProviderListenerUnregister(); 363 364 EVENT_LOG.logProviderClientUnregistered(mName, getIdentity()); 365 366 if (D) { 367 Log.d(TAG, mName + " provider removed registration from " + getIdentity()); 368 } 369 } 370 371 /** 372 * Subclasses may override this instead of {@link #onRemovableListenerRegister()}. 373 */ 374 @GuardedBy("mLock") onProviderListenerRegister()375 protected void onProviderListenerRegister() {} 376 377 /** 378 * Subclasses may override this instead of {@link #onRemovableListenerUnregister()}. 379 */ 380 @GuardedBy("mLock") onProviderListenerUnregister()381 protected void onProviderListenerUnregister() {} 382 383 @Override onActive()384 protected final void onActive() { 385 if (Build.IS_DEBUGGABLE) { 386 Preconditions.checkState(Thread.holdsLock(mLock)); 387 } 388 389 EVENT_LOG.logProviderClientActive(mName, getIdentity()); 390 391 if (!getRequest().isHiddenFromAppOps()) { 392 mLocationAttributionHelper.reportLocationStart(getIdentity(), getName(), getKey()); 393 } 394 onHighPowerUsageChanged(); 395 396 onProviderListenerActive(); 397 } 398 399 @Override onInactive()400 protected final void onInactive() { 401 if (Build.IS_DEBUGGABLE) { 402 Preconditions.checkState(Thread.holdsLock(mLock)); 403 } 404 405 onHighPowerUsageChanged(); 406 if (!getRequest().isHiddenFromAppOps()) { 407 mLocationAttributionHelper.reportLocationStop(getIdentity(), getName(), getKey()); 408 } 409 410 onProviderListenerInactive(); 411 412 EVENT_LOG.logProviderClientInactive(mName, getIdentity()); 413 } 414 415 /** 416 * Subclasses may override this instead of {@link #onActive()}. 417 */ 418 @GuardedBy("mLock") onProviderListenerActive()419 protected void onProviderListenerActive() {} 420 421 /** 422 * Subclasses may override this instead of {@link #onInactive()} ()}. 423 */ 424 @GuardedBy("mLock") onProviderListenerInactive()425 protected void onProviderListenerInactive() {} 426 427 @Override getRequest()428 public final LocationRequest getRequest() { 429 return mProviderLocationRequest; 430 } 431 432 @GuardedBy("mLock") setLastDeliveredLocation(@ullable Location location)433 final void setLastDeliveredLocation(@Nullable Location location) { 434 mLastLocation = location; 435 } 436 437 @GuardedBy("mLock") getLastDeliveredLocation()438 public final Location getLastDeliveredLocation() { 439 return mLastLocation; 440 } 441 getPermissionLevel()442 public @PermissionLevel int getPermissionLevel() { 443 return mPermissionLevel; 444 } 445 isForeground()446 public final boolean isForeground() { 447 return mForeground; 448 } 449 isPermitted()450 public final boolean isPermitted() { 451 return mPermitted; 452 } 453 flush(int requestCode)454 public final void flush(int requestCode) { 455 // when the flush callback is invoked, we are guaranteed that locations have been 456 // queued on our executor, so by running the listener callback on the same executor it 457 // should be guaranteed that those locations will be delivered before the flush callback 458 mProvider.getController().flush(() -> executeOperation( 459 listener -> listener.deliverOnFlushComplete(requestCode))); 460 } 461 462 @Override getOwner()463 protected final LocationProviderManager getOwner() { 464 return LocationProviderManager.this; 465 } 466 467 @GuardedBy("mLock") onProviderPropertiesChanged()468 final boolean onProviderPropertiesChanged() { 469 onHighPowerUsageChanged(); 470 return false; 471 } 472 473 @GuardedBy("mLock") onHighPowerUsageChanged()474 private void onHighPowerUsageChanged() { 475 boolean isUsingHighPower = isUsingHighPower(); 476 if (isUsingHighPower != mIsUsingHighPower) { 477 mIsUsingHighPower = isUsingHighPower; 478 479 if (!getRequest().isHiddenFromAppOps()) { 480 if (mIsUsingHighPower) { 481 mLocationAttributionHelper.reportHighPowerLocationStart( 482 getIdentity(), getName(), getKey()); 483 } else { 484 mLocationAttributionHelper.reportHighPowerLocationStop( 485 getIdentity(), getName(), getKey()); 486 } 487 } 488 } 489 } 490 491 @GuardedBy("mLock") isUsingHighPower()492 private boolean isUsingHighPower() { 493 if (Build.IS_DEBUGGABLE) { 494 Preconditions.checkState(Thread.holdsLock(mLock)); 495 } 496 497 ProviderProperties properties = getProperties(); 498 if (properties == null) { 499 return false; 500 } 501 502 return isActive() 503 && getRequest().getIntervalMillis() < MAX_HIGH_POWER_INTERVAL_MS 504 && properties.getPowerUsage() == ProviderProperties.POWER_USAGE_HIGH; 505 } 506 507 @GuardedBy("mLock") onLocationPermissionsChanged(String packageName)508 final boolean onLocationPermissionsChanged(String packageName) { 509 if (getIdentity().getPackageName().equals(packageName)) { 510 return onLocationPermissionsChanged(); 511 } 512 513 return false; 514 } 515 516 @GuardedBy("mLock") onLocationPermissionsChanged(int uid)517 final boolean onLocationPermissionsChanged(int uid) { 518 if (getIdentity().getUid() == uid) { 519 return onLocationPermissionsChanged(); 520 } 521 522 return false; 523 } 524 525 @GuardedBy("mLock") onLocationPermissionsChanged()526 private boolean onLocationPermissionsChanged() { 527 if (Build.IS_DEBUGGABLE) { 528 Preconditions.checkState(Thread.holdsLock(mLock)); 529 } 530 531 boolean permitted = mLocationPermissionsHelper.hasLocationPermissions(mPermissionLevel, 532 getIdentity()); 533 if (permitted != mPermitted) { 534 if (D) { 535 Log.v(TAG, mName + " provider package " + getIdentity().getPackageName() 536 + " permitted = " + permitted); 537 } 538 539 mPermitted = permitted; 540 541 if (mPermitted) { 542 EVENT_LOG.logProviderClientPermitted(mName, getIdentity()); 543 } else { 544 EVENT_LOG.logProviderClientUnpermitted(mName, getIdentity()); 545 } 546 547 return true; 548 } 549 550 return false; 551 } 552 553 @GuardedBy("mLock") onAdasGnssLocationEnabledChanged(int userId)554 final boolean onAdasGnssLocationEnabledChanged(int userId) { 555 if (Build.IS_DEBUGGABLE) { 556 Preconditions.checkState(Thread.holdsLock(mLock)); 557 } 558 559 if (getIdentity().getUserId() == userId) { 560 return onProviderLocationRequestChanged(); 561 } 562 563 return false; 564 } 565 566 @GuardedBy("mLock") onForegroundChanged(int uid, boolean foreground)567 final boolean onForegroundChanged(int uid, boolean foreground) { 568 if (Build.IS_DEBUGGABLE) { 569 Preconditions.checkState(Thread.holdsLock(mLock)); 570 } 571 572 if (getIdentity().getUid() == uid && foreground != mForeground) { 573 if (D) { 574 Log.v(TAG, mName + " provider uid " + uid + " foreground = " + foreground); 575 } 576 577 mForeground = foreground; 578 579 if (mForeground) { 580 EVENT_LOG.logProviderClientForeground(mName, getIdentity()); 581 } else { 582 EVENT_LOG.logProviderClientBackground(mName, getIdentity()); 583 } 584 585 // note that onProviderLocationRequestChanged() is always called 586 return onProviderLocationRequestChanged() 587 || mLocationPowerSaveModeHelper.getLocationPowerSaveMode() 588 == LOCATION_MODE_FOREGROUND_ONLY; 589 } 590 591 return false; 592 } 593 594 @GuardedBy("mLock") onProviderLocationRequestChanged()595 final boolean onProviderLocationRequestChanged() { 596 if (Build.IS_DEBUGGABLE) { 597 Preconditions.checkState(Thread.holdsLock(mLock)); 598 } 599 600 LocationRequest newRequest = calculateProviderLocationRequest(); 601 if (mProviderLocationRequest.equals(newRequest)) { 602 return false; 603 } 604 605 LocationRequest oldRequest = mProviderLocationRequest; 606 mProviderLocationRequest = newRequest; 607 onHighPowerUsageChanged(); 608 updateService(); 609 610 // if bypass state has changed then the active state may have changed 611 return oldRequest.isBypass() != newRequest.isBypass(); 612 } 613 calculateProviderLocationRequest()614 private LocationRequest calculateProviderLocationRequest() { 615 LocationRequest baseRequest = super.getRequest(); 616 LocationRequest.Builder builder = new LocationRequest.Builder(baseRequest); 617 618 if (mPermissionLevel < PERMISSION_FINE) { 619 builder.setQuality(LocationRequest.QUALITY_LOW_POWER); 620 if (baseRequest.getIntervalMillis() < MIN_COARSE_INTERVAL_MS) { 621 builder.setIntervalMillis(MIN_COARSE_INTERVAL_MS); 622 } 623 if (baseRequest.getMinUpdateIntervalMillis() < MIN_COARSE_INTERVAL_MS) { 624 builder.setMinUpdateIntervalMillis(MIN_COARSE_INTERVAL_MS); 625 } 626 } 627 628 boolean locationSettingsIgnored = baseRequest.isLocationSettingsIgnored(); 629 if (locationSettingsIgnored) { 630 // if we are not currently allowed use location settings ignored, disable it 631 if (!mSettingsHelper.getIgnoreSettingsAllowlist().contains( 632 getIdentity().getPackageName(), getIdentity().getAttributionTag()) 633 && !mLocationManagerInternal.isProvider(null, getIdentity())) { 634 locationSettingsIgnored = false; 635 } 636 637 builder.setLocationSettingsIgnored(locationSettingsIgnored); 638 } 639 640 boolean adasGnssBypass = baseRequest.isAdasGnssBypass(); 641 if (adasGnssBypass) { 642 // if we are not currently allowed use adas gnss bypass, disable it 643 if (!GPS_PROVIDER.equals(mName)) { 644 Log.e(TAG, "adas gnss bypass request received in non-gps provider"); 645 adasGnssBypass = false; 646 } else if (!mLocationSettings.getUserSettings( 647 getIdentity().getUserId()).isAdasGnssLocationEnabled()) { 648 adasGnssBypass = false; 649 } 650 651 builder.setAdasGnssBypass(adasGnssBypass); 652 } 653 654 if (!locationSettingsIgnored && !isThrottlingExempt()) { 655 // throttle in the background 656 if (!mForeground) { 657 builder.setIntervalMillis(max(baseRequest.getIntervalMillis(), 658 mSettingsHelper.getBackgroundThrottleIntervalMs())); 659 } 660 } 661 662 return builder.build(); 663 } 664 isThrottlingExempt()665 private boolean isThrottlingExempt() { 666 if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains( 667 getIdentity().getPackageName())) { 668 return true; 669 } 670 671 return mLocationManagerInternal.isProvider(null, getIdentity()); 672 } 673 674 @GuardedBy("mLock") acceptLocationChange( LocationResult fineLocationResult)675 abstract @Nullable ListenerOperation<LocationTransport> acceptLocationChange( 676 LocationResult fineLocationResult); 677 678 @Override toString()679 public String toString() { 680 StringBuilder builder = new StringBuilder(); 681 builder.append(getIdentity()); 682 683 ArraySet<String> flags = new ArraySet<>(2); 684 if (!isForeground()) { 685 flags.add("bg"); 686 } 687 if (!isPermitted()) { 688 flags.add("na"); 689 } 690 if (!flags.isEmpty()) { 691 builder.append(" ").append(flags); 692 } 693 694 if (mPermissionLevel == PERMISSION_COARSE) { 695 builder.append(" (COARSE)"); 696 } 697 698 builder.append(" ").append(getRequest()); 699 return builder.toString(); 700 } 701 } 702 703 protected abstract class LocationRegistration extends Registration implements 704 OnAlarmListener, ProviderEnabledListener { 705 706 final PowerManager.WakeLock mWakeLock; 707 708 private volatile ProviderTransport mProviderTransport; 709 private int mNumLocationsDelivered = 0; 710 private long mExpirationRealtimeMs = Long.MAX_VALUE; 711 LocationRegistration( LocationRequest request, CallerIdentity identity, TTransport transport, @PermissionLevel int permissionLevel)712 protected <TTransport extends LocationTransport & ProviderTransport> LocationRegistration( 713 LocationRequest request, CallerIdentity identity, TTransport transport, 714 @PermissionLevel int permissionLevel) { 715 super(request, identity, transport, permissionLevel); 716 mProviderTransport = transport; 717 mWakeLock = Objects.requireNonNull(mContext.getSystemService(PowerManager.class)) 718 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG); 719 mWakeLock.setReferenceCounted(true); 720 mWakeLock.setWorkSource(request.getWorkSource()); 721 } 722 723 @Override onListenerUnregister()724 protected void onListenerUnregister() { 725 mProviderTransport = null; 726 } 727 728 @GuardedBy("mLock") 729 @Override onProviderListenerRegister()730 protected final void onProviderListenerRegister() { 731 long registerTimeMs = SystemClock.elapsedRealtime(); 732 mExpirationRealtimeMs = getRequest().getExpirationRealtimeMs(registerTimeMs); 733 734 // add alarm for expiration 735 if (mExpirationRealtimeMs <= registerTimeMs) { 736 onAlarm(); 737 } else if (mExpirationRealtimeMs < Long.MAX_VALUE) { 738 // Set WorkSource to null in order to ensure the alarm wakes up the device even when 739 // it is idle. Do this when the cost of waking up the device is less than the power 740 // cost of not performing the actions set off by the alarm, such as unregistering a 741 // location request. 742 mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this, 743 null); 744 } 745 746 // start listening for provider enabled/disabled events 747 addEnabledListener(this); 748 749 onLocationListenerRegister(); 750 751 // if the provider is currently disabled, let the client know immediately 752 int userId = getIdentity().getUserId(); 753 if (!isEnabled(userId)) { 754 onProviderEnabledChanged(mName, userId, false); 755 } 756 } 757 758 @GuardedBy("mLock") 759 @Override onProviderListenerUnregister()760 protected final void onProviderListenerUnregister() { 761 // stop listening for provider enabled/disabled events 762 removeEnabledListener(this); 763 764 // remove alarm for expiration 765 if (mExpirationRealtimeMs < Long.MAX_VALUE) { 766 mAlarmHelper.cancel(this); 767 } 768 769 onLocationListenerUnregister(); 770 } 771 772 /** 773 * Subclasses may override this instead of {@link #onRemovableListenerRegister()}. 774 */ 775 @GuardedBy("mLock") onLocationListenerRegister()776 protected void onLocationListenerRegister() {} 777 778 /** 779 * Subclasses may override this instead of {@link #onRemovableListenerUnregister()}. 780 */ 781 @GuardedBy("mLock") onLocationListenerUnregister()782 protected void onLocationListenerUnregister() {} 783 784 @GuardedBy("mLock") 785 @Override onProviderListenerActive()786 protected final void onProviderListenerActive() { 787 // a new registration may not get a location immediately, the provider request may be 788 // delayed. therefore we deliver a historical location if available. since delivering an 789 // older location could be considered a breaking change for some applications, we only 790 // do so for apps targeting S+. 791 if (isChangeEnabled(DELIVER_HISTORICAL_LOCATIONS, getIdentity().getUid())) { 792 long maxLocationAgeMs = getRequest().getIntervalMillis(); 793 Location lastDeliveredLocation = getLastDeliveredLocation(); 794 if (lastDeliveredLocation != null) { 795 // ensure that location is fresher than the last delivered location 796 maxLocationAgeMs = min(maxLocationAgeMs, 797 lastDeliveredLocation.getElapsedRealtimeAgeMillis() - 1); 798 } 799 800 // requests are never delayed less than MIN_REQUEST_DELAY_MS, so it only makes sense 801 // to deliver historical locations to clients with a last location older than that 802 if (maxLocationAgeMs > MIN_REQUEST_DELAY_MS) { 803 Location lastLocation = getLastLocationUnsafe( 804 getIdentity().getUserId(), 805 getPermissionLevel(), 806 getRequest().isBypass(), 807 maxLocationAgeMs); 808 if (lastLocation != null) { 809 executeOperation(acceptLocationChange(LocationResult.wrap(lastLocation))); 810 } 811 } 812 } 813 } 814 815 @Override onAlarm()816 public void onAlarm() { 817 if (D) { 818 Log.d(TAG, mName + " provider registration " + getIdentity() 819 + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs)); 820 } 821 822 synchronized (mLock) { 823 // no need to remove alarm after it's fired 824 mExpirationRealtimeMs = Long.MAX_VALUE; 825 remove(); 826 } 827 } 828 829 @GuardedBy("mLock") 830 @Override acceptLocationChange( LocationResult fineLocationResult)831 @Nullable ListenerOperation<LocationTransport> acceptLocationChange( 832 LocationResult fineLocationResult) { 833 if (Build.IS_DEBUGGABLE) { 834 Preconditions.checkState(Thread.holdsLock(mLock)); 835 } 836 837 // check expiration time - alarm is not guaranteed to go off at the right time, 838 // especially for short intervals 839 if (SystemClock.elapsedRealtime() >= mExpirationRealtimeMs) { 840 if (D) { 841 Log.d(TAG, mName + " provider registration " + getIdentity() 842 + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs)); 843 } 844 remove(); 845 return null; 846 } 847 848 LocationResult permittedLocationResult = Objects.requireNonNull( 849 getPermittedLocationResult(fineLocationResult, getPermissionLevel())); 850 851 LocationResult locationResult = permittedLocationResult.filter( 852 new Predicate<Location>() { 853 private Location mPreviousLocation = getLastDeliveredLocation(); 854 855 @Override 856 public boolean test(Location location) { 857 if (mPreviousLocation != null) { 858 // check fastest interval 859 long deltaMs = location.getElapsedRealtimeMillis() 860 - mPreviousLocation.getElapsedRealtimeMillis(); 861 long maxJitterMs = min((long) (FASTEST_INTERVAL_JITTER_PERCENTAGE 862 * getRequest().getIntervalMillis()), 863 MAX_FASTEST_INTERVAL_JITTER_MS); 864 if (deltaMs 865 < getRequest().getMinUpdateIntervalMillis() - maxJitterMs) { 866 return false; 867 } 868 869 // check smallest displacement 870 double smallestDisplacementM = 871 getRequest().getMinUpdateDistanceMeters(); 872 if (smallestDisplacementM > 0.0 && location.distanceTo( 873 mPreviousLocation) 874 <= smallestDisplacementM) { 875 return false; 876 } 877 } 878 879 mPreviousLocation = location; 880 return true; 881 } 882 }); 883 884 if (locationResult == null) { 885 return null; 886 } 887 888 // note app ops 889 if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(getPermissionLevel()), 890 getIdentity())) { 891 if (D) { 892 Log.w(TAG, "noteOp denied for " + getIdentity()); 893 } 894 return null; 895 } 896 897 // deliver location 898 return new ListenerOperation<LocationTransport>() { 899 900 private boolean mUseWakeLock; 901 902 @Override 903 public void onPreExecute() { 904 mUseWakeLock = false; 905 final int size = locationResult.size(); 906 for (int i = 0; i < size; ++i) { 907 if (!locationResult.get(i).isMock()) { 908 mUseWakeLock = true; 909 break; 910 } 911 } 912 913 // update last delivered location 914 setLastDeliveredLocation(locationResult.getLastLocation()); 915 916 // don't acquire a wakelock for mock locations to prevent abuse 917 if (mUseWakeLock) { 918 mWakeLock.acquire(WAKELOCK_TIMEOUT_MS); 919 } 920 } 921 922 @Override 923 public void operate(LocationTransport listener) throws Exception { 924 // if delivering to the same process, make a copy of the location first (since 925 // location is mutable) 926 LocationResult deliverLocationResult; 927 if (getIdentity().getPid() == Process.myPid()) { 928 deliverLocationResult = locationResult.deepCopy(); 929 } else { 930 deliverLocationResult = locationResult; 931 } 932 933 listener.deliverOnLocationChanged(deliverLocationResult, 934 mUseWakeLock ? mWakeLock::release : null); 935 EVENT_LOG.logProviderDeliveredLocations(mName, locationResult.size(), 936 getIdentity()); 937 } 938 939 @Override 940 public void onPostExecute(boolean success) { 941 if (!success && mUseWakeLock) { 942 mWakeLock.release(); 943 } 944 945 if (success) { 946 // check num updates - if successful then this function will always be run 947 // from the same thread, and no additional synchronization is necessary 948 boolean remove = ++mNumLocationsDelivered >= getRequest().getMaxUpdates(); 949 if (remove) { 950 if (D) { 951 Log.d(TAG, mName + " provider registration " + getIdentity() 952 + " finished after " + mNumLocationsDelivered + " updates"); 953 } 954 955 synchronized (mLock) { 956 remove(); 957 } 958 } 959 } 960 } 961 }; 962 } 963 964 @Override onProviderEnabledChanged(String provider, int userId, boolean enabled)965 public void onProviderEnabledChanged(String provider, int userId, boolean enabled) { 966 Preconditions.checkState(mName.equals(provider)); 967 968 if (userId != getIdentity().getUserId()) { 969 return; 970 } 971 972 // we choose not to hold a wakelock for provider enabled changed events 973 executeSafely(getExecutor(), () -> mProviderTransport, 974 listener -> listener.deliverOnProviderEnabledChanged(mName, enabled), 975 this::onProviderOperationFailure); 976 } 977 onProviderOperationFailure( ListenerOperation<ProviderTransport> operation, Exception exception)978 protected abstract void onProviderOperationFailure( 979 ListenerOperation<ProviderTransport> operation, Exception exception); 980 } 981 982 protected final class LocationListenerRegistration extends LocationRegistration implements 983 IBinder.DeathRecipient { 984 LocationListenerRegistration(LocationRequest request, CallerIdentity identity, LocationListenerTransport transport, @PermissionLevel int permissionLevel)985 protected LocationListenerRegistration(LocationRequest request, CallerIdentity identity, 986 LocationListenerTransport transport, @PermissionLevel int permissionLevel) { 987 super(request, identity, transport, permissionLevel); 988 } 989 990 @GuardedBy("mLock") 991 @Override onLocationListenerRegister()992 protected void onLocationListenerRegister() { 993 try { 994 ((IBinder) getKey()).linkToDeath(this, 0); 995 } catch (RemoteException e) { 996 remove(); 997 } 998 } 999 1000 @GuardedBy("mLock") 1001 @Override onLocationListenerUnregister()1002 protected void onLocationListenerUnregister() { 1003 ((IBinder) getKey()).unlinkToDeath(this, 0); 1004 } 1005 1006 @Override onProviderOperationFailure(ListenerOperation<ProviderTransport> operation, Exception exception)1007 protected void onProviderOperationFailure(ListenerOperation<ProviderTransport> operation, 1008 Exception exception) { 1009 onTransportFailure(exception); 1010 } 1011 1012 @Override onOperationFailure(ListenerOperation<LocationTransport> operation, Exception exception)1013 public void onOperationFailure(ListenerOperation<LocationTransport> operation, 1014 Exception exception) { 1015 onTransportFailure(exception); 1016 } 1017 onTransportFailure(Exception e)1018 private void onTransportFailure(Exception e) { 1019 if (e instanceof RemoteException) { 1020 Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e); 1021 synchronized (mLock) { 1022 remove(); 1023 } 1024 } else { 1025 throw new AssertionError(e); 1026 } 1027 } 1028 1029 @Override binderDied()1030 public void binderDied() { 1031 try { 1032 if (D) { 1033 Log.d(TAG, mName + " provider registration " + getIdentity() + " died"); 1034 } 1035 1036 synchronized (mLock) { 1037 remove(); 1038 } 1039 } catch (RuntimeException e) { 1040 // the caller may swallow runtime exceptions, so we rethrow as assertion errors to 1041 // ensure the crash is seen 1042 throw new AssertionError(e); 1043 } 1044 } 1045 } 1046 1047 protected final class LocationPendingIntentRegistration extends LocationRegistration implements 1048 PendingIntent.CancelListener { 1049 LocationPendingIntentRegistration(LocationRequest request, CallerIdentity identity, LocationPendingIntentTransport transport, @PermissionLevel int permissionLevel)1050 protected LocationPendingIntentRegistration(LocationRequest request, 1051 CallerIdentity identity, LocationPendingIntentTransport transport, 1052 @PermissionLevel int permissionLevel) { 1053 super(request, identity, transport, permissionLevel); 1054 } 1055 1056 @GuardedBy("mLock") 1057 @Override onLocationListenerRegister()1058 protected void onLocationListenerRegister() { 1059 ((PendingIntent) getKey()).registerCancelListener(this); 1060 } 1061 1062 @GuardedBy("mLock") 1063 @Override onLocationListenerUnregister()1064 protected void onLocationListenerUnregister() { 1065 ((PendingIntent) getKey()).unregisterCancelListener(this); 1066 } 1067 1068 @Override onProviderOperationFailure(ListenerOperation<ProviderTransport> operation, Exception exception)1069 protected void onProviderOperationFailure(ListenerOperation<ProviderTransport> operation, 1070 Exception exception) { 1071 onTransportFailure(exception); 1072 } 1073 1074 @Override onOperationFailure(ListenerOperation<LocationTransport> operation, Exception exception)1075 public void onOperationFailure(ListenerOperation<LocationTransport> operation, 1076 Exception exception) { 1077 onTransportFailure(exception); 1078 } 1079 onTransportFailure(Exception e)1080 private void onTransportFailure(Exception e) { 1081 if (e instanceof RemoteException) { 1082 Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e); 1083 synchronized (mLock) { 1084 remove(); 1085 } 1086 } else { 1087 throw new AssertionError(e); 1088 } 1089 } 1090 1091 @Override onCancelled(PendingIntent intent)1092 public void onCancelled(PendingIntent intent) { 1093 if (D) { 1094 Log.d(TAG, mName + " provider registration " + getIdentity() + " cancelled"); 1095 } 1096 1097 synchronized (mLock) { 1098 remove(); 1099 } 1100 } 1101 } 1102 1103 protected final class GetCurrentLocationListenerRegistration extends Registration implements 1104 IBinder.DeathRecipient, OnAlarmListener { 1105 1106 private long mExpirationRealtimeMs = Long.MAX_VALUE; 1107 GetCurrentLocationListenerRegistration(LocationRequest request, CallerIdentity identity, LocationTransport transport, int permissionLevel)1108 protected GetCurrentLocationListenerRegistration(LocationRequest request, 1109 CallerIdentity identity, LocationTransport transport, int permissionLevel) { 1110 super(request, identity, transport, permissionLevel); 1111 } 1112 1113 @GuardedBy("mLock") 1114 @Override onProviderListenerRegister()1115 protected void onProviderListenerRegister() { 1116 try { 1117 ((IBinder) getKey()).linkToDeath(this, 0); 1118 } catch (RemoteException e) { 1119 remove(); 1120 } 1121 1122 long registerTimeMs = SystemClock.elapsedRealtime(); 1123 mExpirationRealtimeMs = getRequest().getExpirationRealtimeMs(registerTimeMs); 1124 1125 // add alarm for expiration 1126 if (mExpirationRealtimeMs <= registerTimeMs) { 1127 onAlarm(); 1128 } else if (mExpirationRealtimeMs < Long.MAX_VALUE) { 1129 // Set WorkSource to null in order to ensure the alarm wakes up the device even when 1130 // it is idle. Do this when the cost of waking up the device is less than the power 1131 // cost of not performing the actions set off by the alarm, such as unregistering a 1132 // location request. 1133 mAlarmHelper.setDelayedAlarm(mExpirationRealtimeMs - registerTimeMs, this, 1134 null); 1135 } 1136 } 1137 1138 @GuardedBy("mLock") 1139 @Override onProviderListenerUnregister()1140 protected void onProviderListenerUnregister() { 1141 // remove alarm for expiration 1142 if (mExpirationRealtimeMs < Long.MAX_VALUE) { 1143 mAlarmHelper.cancel(this); 1144 } 1145 1146 ((IBinder) getKey()).unlinkToDeath(this, 0); 1147 } 1148 1149 @GuardedBy("mLock") 1150 @Override onProviderListenerActive()1151 protected void onProviderListenerActive() { 1152 Location lastLocation = getLastLocationUnsafe( 1153 getIdentity().getUserId(), 1154 getPermissionLevel(), 1155 getRequest().isBypass(), 1156 MAX_CURRENT_LOCATION_AGE_MS); 1157 if (lastLocation != null) { 1158 executeOperation(acceptLocationChange(LocationResult.wrap(lastLocation))); 1159 } 1160 } 1161 1162 @GuardedBy("mLock") 1163 @Override onProviderListenerInactive()1164 protected void onProviderListenerInactive() { 1165 // if we go inactive for any reason, fail immediately 1166 executeOperation(acceptLocationChange(null)); 1167 } 1168 deliverNull()1169 void deliverNull() { 1170 synchronized (mLock) { 1171 executeOperation(acceptLocationChange(null)); 1172 } 1173 } 1174 1175 @Override onAlarm()1176 public void onAlarm() { 1177 if (D) { 1178 Log.d(TAG, mName + " provider registration " + getIdentity() 1179 + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs)); 1180 } 1181 1182 synchronized (mLock) { 1183 // no need to remove alarm after it's fired 1184 mExpirationRealtimeMs = Long.MAX_VALUE; 1185 executeOperation(acceptLocationChange(null)); 1186 } 1187 } 1188 1189 @GuardedBy("mLock") 1190 @Override acceptLocationChange( @ullable LocationResult fineLocationResult)1191 @Nullable ListenerOperation<LocationTransport> acceptLocationChange( 1192 @Nullable LocationResult fineLocationResult) { 1193 if (Build.IS_DEBUGGABLE) { 1194 Preconditions.checkState(Thread.holdsLock(mLock)); 1195 } 1196 1197 // check expiration time - alarm is not guaranteed to go off at the right time, 1198 // especially for short intervals 1199 if (SystemClock.elapsedRealtime() >= mExpirationRealtimeMs) { 1200 if (D) { 1201 Log.d(TAG, mName + " provider registration " + getIdentity() 1202 + " expired at " + TimeUtils.formatRealtime(mExpirationRealtimeMs)); 1203 } 1204 fineLocationResult = null; 1205 } 1206 1207 // lastly - note app ops 1208 if (fineLocationResult != null && !mAppOpsHelper.noteOpNoThrow( 1209 LocationPermissions.asAppOp(getPermissionLevel()), getIdentity())) { 1210 if (D) { 1211 Log.w(TAG, "noteOp denied for " + getIdentity()); 1212 } 1213 fineLocationResult = null; 1214 } 1215 1216 if (fineLocationResult != null) { 1217 fineLocationResult = fineLocationResult.asLastLocationResult(); 1218 } 1219 1220 LocationResult locationResult = getPermittedLocationResult(fineLocationResult, 1221 getPermissionLevel()); 1222 1223 // deliver location 1224 return new ListenerOperation<LocationTransport>() { 1225 @Override 1226 public void operate(LocationTransport listener) throws Exception { 1227 // if delivering to the same process, make a copy of the location first (since 1228 // location is mutable) 1229 LocationResult deliverLocationResult; 1230 if (getIdentity().getPid() == Process.myPid() && locationResult != null) { 1231 deliverLocationResult = locationResult.deepCopy(); 1232 } else { 1233 deliverLocationResult = locationResult; 1234 } 1235 1236 // we currently don't hold a wakelock for getCurrentLocation deliveries 1237 listener.deliverOnLocationChanged(deliverLocationResult, null); 1238 EVENT_LOG.logProviderDeliveredLocations(mName, 1239 locationResult != null ? locationResult.size() : 0, getIdentity()); 1240 } 1241 1242 @Override 1243 public void onPostExecute(boolean success) { 1244 // on failure we're automatically removed anyways, no need to attempt removal 1245 // again 1246 if (success) { 1247 synchronized (mLock) { 1248 remove(); 1249 } 1250 } 1251 } 1252 }; 1253 } 1254 1255 @Override 1256 public void onOperationFailure(ListenerOperation<LocationTransport> operation, 1257 Exception e) { 1258 if (e instanceof RemoteException) { 1259 Log.w(TAG, mName + " provider registration " + getIdentity() + " removed", e); 1260 synchronized (mLock) { 1261 remove(); 1262 } 1263 } else { 1264 throw new AssertionError(e); 1265 } 1266 } 1267 1268 @Override 1269 public void binderDied() { 1270 try { 1271 if (D) { 1272 Log.d(TAG, mName + " provider registration " + getIdentity() + " died"); 1273 } 1274 1275 synchronized (mLock) { 1276 remove(); 1277 } 1278 } catch (RuntimeException e) { 1279 // the caller may swallow runtime exceptions, so we rethrow as assertion errors to 1280 // ensure the crash is seen 1281 throw new AssertionError(e); 1282 } 1283 } 1284 } 1285 1286 protected final Object mLock = new Object(); 1287 1288 protected final String mName; 1289 private final @Nullable PassiveLocationProviderManager mPassiveManager; 1290 1291 protected final Context mContext; 1292 1293 @GuardedBy("mLock") 1294 private @State int mState; 1295 1296 // maps of user id to value 1297 @GuardedBy("mLock") 1298 private final SparseBooleanArray mEnabled; // null or not present means unknown 1299 @GuardedBy("mLock") 1300 private final SparseArray<LastLocation> mLastLocations; 1301 1302 @GuardedBy("mLock") 1303 private final ArrayList<ProviderEnabledListener> mEnabledListeners; 1304 1305 private final CopyOnWriteArrayList<IProviderRequestListener> mProviderRequestListeners; 1306 1307 protected final LocationManagerInternal mLocationManagerInternal; 1308 protected final LocationSettings mLocationSettings; 1309 protected final SettingsHelper mSettingsHelper; 1310 protected final UserInfoHelper mUserHelper; 1311 protected final AlarmHelper mAlarmHelper; 1312 protected final AppOpsHelper mAppOpsHelper; 1313 protected final LocationPermissionsHelper mLocationPermissionsHelper; 1314 protected final AppForegroundHelper mAppForegroundHelper; 1315 protected final LocationPowerSaveModeHelper mLocationPowerSaveModeHelper; 1316 protected final ScreenInteractiveHelper mScreenInteractiveHelper; 1317 protected final LocationAttributionHelper mLocationAttributionHelper; 1318 protected final LocationUsageLogger mLocationUsageLogger; 1319 protected final LocationFudger mLocationFudger; 1320 1321 private final UserListener mUserChangedListener = this::onUserChanged; 1322 private final LocationSettings.LocationUserSettingsListener mLocationUserSettingsListener = 1323 this::onLocationUserSettingsChanged; 1324 private final UserSettingChangedListener mLocationEnabledChangedListener = 1325 this::onLocationEnabledChanged; 1326 private final GlobalSettingChangedListener mBackgroundThrottlePackageWhitelistChangedListener = 1327 this::onBackgroundThrottlePackageWhitelistChanged; 1328 private final UserSettingChangedListener mLocationPackageBlacklistChangedListener = 1329 this::onLocationPackageBlacklistChanged; 1330 private final LocationPermissionsListener mLocationPermissionsListener = 1331 new LocationPermissionsListener() { 1332 @Override 1333 public void onLocationPermissionsChanged(String packageName) { 1334 LocationProviderManager.this.onLocationPermissionsChanged(packageName); 1335 } 1336 1337 @Override 1338 public void onLocationPermissionsChanged(int uid) { 1339 LocationProviderManager.this.onLocationPermissionsChanged(uid); 1340 } 1341 }; 1342 private final AppForegroundListener mAppForegroundChangedListener = 1343 this::onAppForegroundChanged; 1344 private final GlobalSettingChangedListener mBackgroundThrottleIntervalChangedListener = 1345 this::onBackgroundThrottleIntervalChanged; 1346 private final GlobalSettingChangedListener mIgnoreSettingsPackageWhitelistChangedListener = 1347 this::onIgnoreSettingsWhitelistChanged; 1348 private final LocationPowerSaveModeChangedListener mLocationPowerSaveModeChangedListener = 1349 this::onLocationPowerSaveModeChanged; 1350 private final ScreenInteractiveChangedListener mScreenInteractiveChangedListener = 1351 this::onScreenInteractiveChanged; 1352 1353 // acquiring mLock makes operations on mProvider atomic, but is otherwise unnecessary 1354 protected final MockableLocationProvider mProvider; 1355 1356 @GuardedBy("mLock") 1357 private @Nullable OnAlarmListener mDelayedRegister; 1358 1359 @GuardedBy("mLock") 1360 private @Nullable StateChangedListener mStateChangedListener; 1361 1362 public LocationProviderManager(Context context, Injector injector, 1363 String name, @Nullable PassiveLocationProviderManager passiveManager) { 1364 mContext = context; 1365 mName = Objects.requireNonNull(name); 1366 mPassiveManager = passiveManager; 1367 mState = STATE_STOPPED; 1368 mEnabled = new SparseBooleanArray(2); 1369 mLastLocations = new SparseArray<>(2); 1370 1371 mEnabledListeners = new ArrayList<>(); 1372 mProviderRequestListeners = new CopyOnWriteArrayList<>(); 1373 1374 mLocationManagerInternal = Objects.requireNonNull( 1375 LocalServices.getService(LocationManagerInternal.class)); 1376 mLocationSettings = injector.getLocationSettings(); 1377 mSettingsHelper = injector.getSettingsHelper(); 1378 mUserHelper = injector.getUserInfoHelper(); 1379 mAlarmHelper = injector.getAlarmHelper(); 1380 mAppOpsHelper = injector.getAppOpsHelper(); 1381 mLocationPermissionsHelper = injector.getLocationPermissionsHelper(); 1382 mAppForegroundHelper = injector.getAppForegroundHelper(); 1383 mLocationPowerSaveModeHelper = injector.getLocationPowerSaveModeHelper(); 1384 mScreenInteractiveHelper = injector.getScreenInteractiveHelper(); 1385 mLocationAttributionHelper = injector.getLocationAttributionHelper(); 1386 mLocationUsageLogger = injector.getLocationUsageLogger(); 1387 mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM()); 1388 1389 mProvider = new MockableLocationProvider(mLock); 1390 1391 // set listener last, since this lets our reference escape 1392 mProvider.getController().setListener(this); 1393 } 1394 1395 @Override 1396 public String getTag() { 1397 return TAG; 1398 } 1399 1400 public void startManager(@Nullable StateChangedListener listener) { 1401 synchronized (mLock) { 1402 Preconditions.checkState(mState == STATE_STOPPED); 1403 mState = STATE_STARTED; 1404 mStateChangedListener = listener; 1405 1406 mUserHelper.addListener(mUserChangedListener); 1407 mLocationSettings.registerLocationUserSettingsListener(mLocationUserSettingsListener); 1408 mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener); 1409 1410 final long identity = Binder.clearCallingIdentity(); 1411 try { 1412 mProvider.getController().start(); 1413 onUserStarted(UserHandle.USER_ALL); 1414 } finally { 1415 Binder.restoreCallingIdentity(identity); 1416 } 1417 } 1418 } 1419 1420 public void stopManager() { 1421 synchronized (mLock) { 1422 Preconditions.checkState(mState == STATE_STARTED); 1423 mState = STATE_STOPPING; 1424 1425 final long identity = Binder.clearCallingIdentity(); 1426 try { 1427 onEnabledChanged(UserHandle.USER_ALL); 1428 removeRegistrationIf(key -> true); 1429 mProvider.getController().stop(); 1430 } finally { 1431 Binder.restoreCallingIdentity(identity); 1432 } 1433 1434 mUserHelper.removeListener(mUserChangedListener); 1435 mLocationSettings.unregisterLocationUserSettingsListener(mLocationUserSettingsListener); 1436 mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener); 1437 1438 // if external entities are registering listeners it's their responsibility to 1439 // unregister them before stopManager() is called 1440 Preconditions.checkState(mEnabledListeners.isEmpty()); 1441 mProviderRequestListeners.clear(); 1442 1443 mEnabled.clear(); 1444 mLastLocations.clear(); 1445 mStateChangedListener = null; 1446 mState = STATE_STOPPED; 1447 } 1448 } 1449 1450 public String getName() { 1451 return mName; 1452 } 1453 1454 public AbstractLocationProvider.State getState() { 1455 return mProvider.getState(); 1456 } 1457 1458 public @Nullable CallerIdentity getIdentity() { 1459 return mProvider.getState().identity; 1460 } 1461 1462 public @Nullable ProviderProperties getProperties() { 1463 return mProvider.getState().properties; 1464 } 1465 1466 public boolean hasProvider() { 1467 return mProvider.getProvider() != null; 1468 } 1469 1470 public boolean isEnabled(int userId) { 1471 if (userId == UserHandle.USER_NULL) { 1472 return false; 1473 } else if (userId == UserHandle.USER_CURRENT) { 1474 return isEnabled(mUserHelper.getCurrentUserId()); 1475 } 1476 1477 Preconditions.checkArgument(userId >= 0); 1478 1479 synchronized (mLock) { 1480 int index = mEnabled.indexOfKey(userId); 1481 if (index < 0) { 1482 // this generally shouldn't occur, but might be possible due to race conditions 1483 // on when we are notified of new users 1484 Log.w(TAG, mName + " provider saw user " + userId + " unexpectedly"); 1485 onEnabledChanged(userId); 1486 index = mEnabled.indexOfKey(userId); 1487 } 1488 1489 return mEnabled.valueAt(index); 1490 } 1491 } 1492 1493 public void addEnabledListener(ProviderEnabledListener listener) { 1494 synchronized (mLock) { 1495 Preconditions.checkState(mState != STATE_STOPPED); 1496 mEnabledListeners.add(listener); 1497 } 1498 } 1499 1500 public void removeEnabledListener(ProviderEnabledListener listener) { 1501 synchronized (mLock) { 1502 Preconditions.checkState(mState != STATE_STOPPED); 1503 mEnabledListeners.remove(listener); 1504 } 1505 } 1506 1507 /** Add a {@link IProviderRequestListener}. */ 1508 public void addProviderRequestListener(IProviderRequestListener listener) { 1509 mProviderRequestListeners.add(listener); 1510 } 1511 1512 /** Remove a {@link IProviderRequestListener}. */ 1513 public void removeProviderRequestListener(IProviderRequestListener listener) { 1514 mProviderRequestListeners.remove(listener); 1515 } 1516 1517 public void setRealProvider(@Nullable AbstractLocationProvider provider) { 1518 synchronized (mLock) { 1519 Preconditions.checkState(mState != STATE_STOPPED); 1520 1521 final long identity = Binder.clearCallingIdentity(); 1522 try { 1523 mProvider.setRealProvider(provider); 1524 } finally { 1525 Binder.restoreCallingIdentity(identity); 1526 } 1527 } 1528 } 1529 1530 public void setMockProvider(@Nullable MockLocationProvider provider) { 1531 synchronized (mLock) { 1532 Preconditions.checkState(mState != STATE_STOPPED); 1533 1534 EVENT_LOG.logProviderMocked(mName, provider != null); 1535 1536 final long identity = Binder.clearCallingIdentity(); 1537 try { 1538 mProvider.setMockProvider(provider); 1539 } finally { 1540 Binder.restoreCallingIdentity(identity); 1541 } 1542 1543 // when removing a mock provider, also clear any mock last locations and reset the 1544 // location fudger. the mock provider could have been used to infer the current 1545 // location fudger offsets. 1546 if (provider == null) { 1547 final int lastLocationSize = mLastLocations.size(); 1548 for (int i = 0; i < lastLocationSize; i++) { 1549 mLastLocations.valueAt(i).clearMock(); 1550 } 1551 1552 mLocationFudger.resetOffsets(); 1553 } 1554 } 1555 } 1556 1557 public void setMockProviderAllowed(boolean enabled) { 1558 synchronized (mLock) { 1559 if (!mProvider.isMock()) { 1560 throw new IllegalArgumentException(mName + " provider is not a test provider"); 1561 } 1562 1563 final long identity = Binder.clearCallingIdentity(); 1564 try { 1565 mProvider.setMockProviderAllowed(enabled); 1566 } finally { 1567 Binder.restoreCallingIdentity(identity); 1568 } 1569 } 1570 } 1571 1572 public void setMockProviderLocation(Location location) { 1573 synchronized (mLock) { 1574 if (!mProvider.isMock()) { 1575 throw new IllegalArgumentException(mName + " provider is not a test provider"); 1576 } 1577 1578 String locationProvider = location.getProvider(); 1579 if (!TextUtils.isEmpty(locationProvider) && !mName.equals(locationProvider)) { 1580 // The location has an explicit provider that is different from the mock 1581 // provider name. The caller may be trying to fool us via b/33091107. 1582 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(), 1583 mName + "!=" + locationProvider); 1584 } 1585 1586 final long identity = Binder.clearCallingIdentity(); 1587 try { 1588 mProvider.setMockProviderLocation(location); 1589 } finally { 1590 Binder.restoreCallingIdentity(identity); 1591 } 1592 } 1593 } 1594 1595 public @Nullable Location getLastLocation(LastLocationRequest request, 1596 CallerIdentity identity, @PermissionLevel int permissionLevel) { 1597 if (!isActive(request.isBypass(), identity)) { 1598 return null; 1599 } 1600 1601 // lastly - note app ops 1602 if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(permissionLevel), 1603 identity)) { 1604 return null; 1605 } 1606 1607 Location location = getPermittedLocation( 1608 getLastLocationUnsafe( 1609 identity.getUserId(), 1610 permissionLevel, 1611 request.isBypass(), 1612 Long.MAX_VALUE), 1613 permissionLevel); 1614 1615 if (location != null && identity.getPid() == Process.myPid()) { 1616 // if delivering to the same process, make a copy of the location first (since 1617 // location is mutable) 1618 location = new Location(location); 1619 } 1620 1621 return location; 1622 } 1623 1624 /** 1625 * This function does not perform any permissions or safety checks, by calling it you are 1626 * committing to performing all applicable checks yourself. This always returns a "fine" 1627 * location, even if the permissionLevel is coarse. You are responsible for coarsening the 1628 * location if necessary. 1629 */ 1630 public @Nullable Location getLastLocationUnsafe(int userId, 1631 @PermissionLevel int permissionLevel, boolean isBypass, 1632 long maximumAgeMs) { 1633 if (userId == UserHandle.USER_ALL) { 1634 // find the most recent location across all users 1635 Location lastLocation = null; 1636 final int[] runningUserIds = mUserHelper.getRunningUserIds(); 1637 for (int i = 0; i < runningUserIds.length; i++) { 1638 Location next = getLastLocationUnsafe(runningUserIds[i], permissionLevel, 1639 isBypass, maximumAgeMs); 1640 if (lastLocation == null || (next != null && next.getElapsedRealtimeNanos() 1641 > lastLocation.getElapsedRealtimeNanos())) { 1642 lastLocation = next; 1643 } 1644 } 1645 return lastLocation; 1646 } else if (userId == UserHandle.USER_CURRENT) { 1647 return getLastLocationUnsafe(mUserHelper.getCurrentUserId(), permissionLevel, 1648 isBypass, maximumAgeMs); 1649 } 1650 1651 Preconditions.checkArgument(userId >= 0); 1652 1653 Location location; 1654 synchronized (mLock) { 1655 Preconditions.checkState(mState != STATE_STOPPED); 1656 LastLocation lastLocation = mLastLocations.get(userId); 1657 if (lastLocation == null) { 1658 location = null; 1659 } else { 1660 location = lastLocation.get(permissionLevel, isBypass); 1661 } 1662 } 1663 1664 if (location == null) { 1665 return null; 1666 } 1667 1668 if (location.getElapsedRealtimeAgeMillis() > maximumAgeMs) { 1669 return null; 1670 } 1671 1672 return location; 1673 } 1674 1675 public void injectLastLocation(Location location, int userId) { 1676 synchronized (mLock) { 1677 Preconditions.checkState(mState != STATE_STOPPED); 1678 if (getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE) == null) { 1679 setLastLocation(location, userId); 1680 } 1681 } 1682 } 1683 1684 private void setLastLocation(Location location, int userId) { 1685 if (userId == UserHandle.USER_ALL) { 1686 final int[] runningUserIds = mUserHelper.getRunningUserIds(); 1687 for (int i = 0; i < runningUserIds.length; i++) { 1688 setLastLocation(location, runningUserIds[i]); 1689 } 1690 return; 1691 } else if (userId == UserHandle.USER_CURRENT) { 1692 setLastLocation(location, mUserHelper.getCurrentUserId()); 1693 return; 1694 } 1695 1696 Preconditions.checkArgument(userId >= 0); 1697 1698 synchronized (mLock) { 1699 LastLocation lastLocation = mLastLocations.get(userId); 1700 if (lastLocation == null) { 1701 lastLocation = new LastLocation(); 1702 mLastLocations.put(userId, lastLocation); 1703 } 1704 1705 if (isEnabled(userId)) { 1706 lastLocation.set(location); 1707 } 1708 lastLocation.setBypass(location); 1709 } 1710 } 1711 1712 public @Nullable ICancellationSignal getCurrentLocation(LocationRequest request, 1713 CallerIdentity identity, int permissionLevel, ILocationCallback callback) { 1714 if (request.getDurationMillis() > MAX_GET_CURRENT_LOCATION_TIMEOUT_MS) { 1715 request = new LocationRequest.Builder(request) 1716 .setDurationMillis(MAX_GET_CURRENT_LOCATION_TIMEOUT_MS) 1717 .build(); 1718 } 1719 1720 GetCurrentLocationListenerRegistration registration = 1721 new GetCurrentLocationListenerRegistration( 1722 request, 1723 identity, 1724 new GetCurrentLocationTransport(callback), 1725 permissionLevel); 1726 1727 synchronized (mLock) { 1728 Preconditions.checkState(mState != STATE_STOPPED); 1729 final long ident = Binder.clearCallingIdentity(); 1730 try { 1731 putRegistration(callback.asBinder(), registration); 1732 if (!registration.isActive()) { 1733 // if the registration never activated, fail it immediately 1734 registration.deliverNull(); 1735 } 1736 } finally { 1737 Binder.restoreCallingIdentity(ident); 1738 } 1739 } 1740 1741 ICancellationSignal cancelTransport = CancellationSignal.createTransport(); 1742 CancellationSignal.fromTransport(cancelTransport) 1743 .setOnCancelListener(SingleUseCallback.wrap( 1744 () -> { 1745 synchronized (mLock) { 1746 removeRegistration(callback.asBinder(), registration); 1747 } 1748 })); 1749 return cancelTransport; 1750 } 1751 1752 public void sendExtraCommand(int uid, int pid, String command, Bundle extras) { 1753 final long identity = Binder.clearCallingIdentity(); 1754 try { 1755 mProvider.getController().sendExtraCommand(uid, pid, command, extras); 1756 } finally { 1757 Binder.restoreCallingIdentity(identity); 1758 } 1759 } 1760 1761 public void registerLocationRequest(LocationRequest request, CallerIdentity identity, 1762 @PermissionLevel int permissionLevel, ILocationListener listener) { 1763 LocationListenerRegistration registration = new LocationListenerRegistration( 1764 request, 1765 identity, 1766 new LocationListenerTransport(listener), 1767 permissionLevel); 1768 1769 synchronized (mLock) { 1770 Preconditions.checkState(mState != STATE_STOPPED); 1771 final long ident = Binder.clearCallingIdentity(); 1772 try { 1773 putRegistration(listener.asBinder(), registration); 1774 } finally { 1775 Binder.restoreCallingIdentity(ident); 1776 } 1777 } 1778 } 1779 1780 public void registerLocationRequest(LocationRequest request, CallerIdentity callerIdentity, 1781 @PermissionLevel int permissionLevel, PendingIntent pendingIntent) { 1782 LocationPendingIntentRegistration registration = new LocationPendingIntentRegistration( 1783 request, 1784 callerIdentity, 1785 new LocationPendingIntentTransport(mContext, pendingIntent), 1786 permissionLevel); 1787 1788 synchronized (mLock) { 1789 Preconditions.checkState(mState != STATE_STOPPED); 1790 final long identity = Binder.clearCallingIdentity(); 1791 try { 1792 putRegistration(pendingIntent, registration); 1793 } finally { 1794 Binder.restoreCallingIdentity(identity); 1795 } 1796 } 1797 } 1798 1799 public void flush(ILocationListener listener, int requestCode) { 1800 synchronized (mLock) { 1801 final long identity = Binder.clearCallingIdentity(); 1802 try { 1803 boolean flushed = updateRegistration(listener.asBinder(), registration -> { 1804 registration.flush(requestCode); 1805 return false; 1806 }); 1807 if (!flushed) { 1808 throw new IllegalArgumentException("unregistered listener cannot be flushed"); 1809 } 1810 } finally { 1811 Binder.restoreCallingIdentity(identity); 1812 } 1813 } 1814 } 1815 1816 public void flush(PendingIntent pendingIntent, int requestCode) { 1817 synchronized (mLock) { 1818 final long identity = Binder.clearCallingIdentity(); 1819 try { 1820 boolean flushed = updateRegistration(pendingIntent, registration -> { 1821 registration.flush(requestCode); 1822 return false; 1823 }); 1824 if (!flushed) { 1825 throw new IllegalArgumentException( 1826 "unregistered pending intent cannot be flushed"); 1827 } 1828 } finally { 1829 Binder.restoreCallingIdentity(identity); 1830 } 1831 } 1832 } 1833 1834 public void unregisterLocationRequest(ILocationListener listener) { 1835 synchronized (mLock) { 1836 Preconditions.checkState(mState != STATE_STOPPED); 1837 final long identity = Binder.clearCallingIdentity(); 1838 try { 1839 removeRegistration(listener.asBinder()); 1840 } finally { 1841 Binder.restoreCallingIdentity(identity); 1842 } 1843 } 1844 } 1845 1846 public void unregisterLocationRequest(PendingIntent pendingIntent) { 1847 synchronized (mLock) { 1848 Preconditions.checkState(mState != STATE_STOPPED); 1849 final long identity = Binder.clearCallingIdentity(); 1850 try { 1851 removeRegistration(pendingIntent); 1852 } finally { 1853 Binder.restoreCallingIdentity(identity); 1854 } 1855 } 1856 } 1857 1858 @GuardedBy("mLock") 1859 @Override 1860 protected void onRegister() { 1861 if (Build.IS_DEBUGGABLE) { 1862 Preconditions.checkState(Thread.holdsLock(mLock)); 1863 } 1864 1865 mSettingsHelper.addOnBackgroundThrottleIntervalChangedListener( 1866 mBackgroundThrottleIntervalChangedListener); 1867 mSettingsHelper.addOnBackgroundThrottlePackageWhitelistChangedListener( 1868 mBackgroundThrottlePackageWhitelistChangedListener); 1869 mSettingsHelper.addOnLocationPackageBlacklistChangedListener( 1870 mLocationPackageBlacklistChangedListener); 1871 mSettingsHelper.addIgnoreSettingsAllowlistChangedListener( 1872 mIgnoreSettingsPackageWhitelistChangedListener); 1873 mLocationPermissionsHelper.addListener(mLocationPermissionsListener); 1874 mAppForegroundHelper.addListener(mAppForegroundChangedListener); 1875 mLocationPowerSaveModeHelper.addListener(mLocationPowerSaveModeChangedListener); 1876 mScreenInteractiveHelper.addListener(mScreenInteractiveChangedListener); 1877 } 1878 1879 @GuardedBy("mLock") 1880 @Override 1881 protected void onUnregister() { 1882 if (Build.IS_DEBUGGABLE) { 1883 Preconditions.checkState(Thread.holdsLock(mLock)); 1884 } 1885 1886 mSettingsHelper.removeOnBackgroundThrottleIntervalChangedListener( 1887 mBackgroundThrottleIntervalChangedListener); 1888 mSettingsHelper.removeOnBackgroundThrottlePackageWhitelistChangedListener( 1889 mBackgroundThrottlePackageWhitelistChangedListener); 1890 mSettingsHelper.removeOnLocationPackageBlacklistChangedListener( 1891 mLocationPackageBlacklistChangedListener); 1892 mSettingsHelper.removeIgnoreSettingsAllowlistChangedListener( 1893 mIgnoreSettingsPackageWhitelistChangedListener); 1894 mLocationPermissionsHelper.removeListener(mLocationPermissionsListener); 1895 mAppForegroundHelper.removeListener(mAppForegroundChangedListener); 1896 mLocationPowerSaveModeHelper.removeListener(mLocationPowerSaveModeChangedListener); 1897 mScreenInteractiveHelper.removeListener(mScreenInteractiveChangedListener); 1898 } 1899 1900 @GuardedBy("mLock") 1901 @Override 1902 protected void onRegistrationAdded(Object key, Registration registration) { 1903 if (Build.IS_DEBUGGABLE) { 1904 Preconditions.checkState(Thread.holdsLock(mLock)); 1905 } 1906 1907 mLocationUsageLogger.logLocationApiUsage( 1908 LocationStatsEnums.USAGE_STARTED, 1909 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES, 1910 registration.getIdentity().getPackageName(), 1911 registration.getIdentity().getAttributionTag(), 1912 mName, 1913 registration.getRequest(), 1914 key instanceof PendingIntent, 1915 /* geofence= */ key instanceof IBinder, 1916 null, registration.isForeground()); 1917 } 1918 1919 @GuardedBy("mLock") 1920 @Override 1921 protected void onRegistrationReplaced(Object key, Registration oldRegistration, 1922 Registration newRegistration) { 1923 // by saving the last delivered location state we are able to potentially delay the 1924 // resulting provider request longer and save additional power 1925 newRegistration.setLastDeliveredLocation(oldRegistration.getLastDeliveredLocation()); 1926 super.onRegistrationReplaced(key, oldRegistration, newRegistration); 1927 } 1928 1929 @GuardedBy("mLock") 1930 @Override 1931 protected void onRegistrationRemoved(Object key, Registration registration) { 1932 if (Build.IS_DEBUGGABLE) { 1933 Preconditions.checkState(Thread.holdsLock(mLock)); 1934 } 1935 1936 mLocationUsageLogger.logLocationApiUsage( 1937 LocationStatsEnums.USAGE_ENDED, 1938 LocationStatsEnums.API_REQUEST_LOCATION_UPDATES, 1939 registration.getIdentity().getPackageName(), 1940 registration.getIdentity().getAttributionTag(), 1941 mName, 1942 registration.getRequest(), 1943 key instanceof PendingIntent, 1944 /* geofence= */ key instanceof IBinder, 1945 null, registration.isForeground()); 1946 } 1947 1948 @GuardedBy("mLock") 1949 @Override 1950 protected boolean registerWithService(ProviderRequest request, 1951 Collection<Registration> registrations) { 1952 return reregisterWithService(ProviderRequest.EMPTY_REQUEST, request, registrations); 1953 } 1954 1955 @GuardedBy("mLock") 1956 @Override 1957 protected boolean reregisterWithService(ProviderRequest oldRequest, 1958 ProviderRequest newRequest, Collection<Registration> registrations) { 1959 if (Build.IS_DEBUGGABLE) { 1960 Preconditions.checkState(Thread.holdsLock(mLock)); 1961 } 1962 1963 if (mDelayedRegister != null) { 1964 mAlarmHelper.cancel(mDelayedRegister); 1965 mDelayedRegister = null; 1966 } 1967 1968 // calculate how long the new request should be delayed before sending it off to the 1969 // provider, under the assumption that once we send the request off, the provider will 1970 // immediately attempt to deliver a new location satisfying that request. 1971 long delayMs; 1972 if (!oldRequest.isBypass() && newRequest.isBypass()) { 1973 delayMs = 0; 1974 } else if (newRequest.getIntervalMillis() > oldRequest.getIntervalMillis()) { 1975 // if the interval has increased, tell the provider immediately, so it can save power 1976 // (even though technically this could burn extra power in the short term by producing 1977 // an extra location - the provider itself is free to detect an increasing interval and 1978 // delay its own location) 1979 delayMs = 0; 1980 } else { 1981 delayMs = calculateRequestDelayMillis(newRequest.getIntervalMillis(), registrations); 1982 } 1983 1984 // the delay should never exceed the new interval 1985 Preconditions.checkState(delayMs >= 0 && delayMs <= newRequest.getIntervalMillis()); 1986 1987 if (delayMs < MIN_REQUEST_DELAY_MS) { 1988 setProviderRequest(newRequest); 1989 } else { 1990 if (D) { 1991 Log.d(TAG, mName + " provider delaying request update " + newRequest + " by " 1992 + TimeUtils.formatDuration(delayMs)); 1993 } 1994 1995 mDelayedRegister = new OnAlarmListener() { 1996 @Override 1997 public void onAlarm() { 1998 synchronized (mLock) { 1999 if (mDelayedRegister == this) { 2000 setProviderRequest(newRequest); 2001 mDelayedRegister = null; 2002 } 2003 } 2004 } 2005 }; 2006 // Set WorkSource to null in order to ensure the alarm wakes up the device even when it 2007 // is idle. Do this when the cost of waking up the device is less than the power cost of 2008 // not performing the actions set off by the alarm, such as unregistering a location 2009 // request. 2010 mAlarmHelper.setDelayedAlarm(delayMs, mDelayedRegister, null); 2011 } 2012 2013 return true; 2014 } 2015 2016 @GuardedBy("mLock") 2017 @Override 2018 protected void unregisterWithService() { 2019 if (Build.IS_DEBUGGABLE) { 2020 Preconditions.checkState(Thread.holdsLock(mLock)); 2021 } 2022 2023 setProviderRequest(ProviderRequest.EMPTY_REQUEST); 2024 } 2025 2026 @GuardedBy("mLock") 2027 void setProviderRequest(ProviderRequest request) { 2028 EVENT_LOG.logProviderUpdateRequest(mName, request); 2029 mProvider.getController().setRequest(request); 2030 2031 FgThread.getHandler().post(() -> { 2032 for (IProviderRequestListener listener : mProviderRequestListeners) { 2033 try { 2034 listener.onProviderRequestChanged(mName, request); 2035 } catch (RemoteException e) { 2036 mProviderRequestListeners.remove(listener); 2037 } 2038 } 2039 }); 2040 } 2041 2042 @GuardedBy("mLock") 2043 @Override 2044 protected boolean isActive(Registration registration) { 2045 if (Build.IS_DEBUGGABLE) { 2046 Preconditions.checkState(Thread.holdsLock(mLock)); 2047 } 2048 2049 if (!registration.isPermitted()) { 2050 return false; 2051 } 2052 2053 boolean isBypass = registration.getRequest().isBypass(); 2054 if (!isActive(isBypass, registration.getIdentity())) { 2055 return false; 2056 } 2057 2058 if (!isBypass) { 2059 switch (mLocationPowerSaveModeHelper.getLocationPowerSaveMode()) { 2060 case LOCATION_MODE_FOREGROUND_ONLY: 2061 if (!registration.isForeground()) { 2062 return false; 2063 } 2064 break; 2065 case LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF: 2066 if (!GPS_PROVIDER.equals(mName)) { 2067 break; 2068 } 2069 // fall through 2070 case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF: 2071 // fall through 2072 case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF: 2073 if (!mScreenInteractiveHelper.isInteractive()) { 2074 return false; 2075 } 2076 break; 2077 case LOCATION_MODE_NO_CHANGE: 2078 // fall through 2079 default: 2080 break; 2081 } 2082 } 2083 2084 return true; 2085 } 2086 2087 private boolean isActive(boolean isBypass, CallerIdentity identity) { 2088 if (identity.isSystemServer()) { 2089 if (!isBypass) { 2090 if (!isEnabled(mUserHelper.getCurrentUserId())) { 2091 return false; 2092 } 2093 } 2094 } else { 2095 if (!isBypass) { 2096 if (!isEnabled(identity.getUserId())) { 2097 return false; 2098 } 2099 if (!mUserHelper.isCurrentUserId(identity.getUserId())) { 2100 return false; 2101 } 2102 } 2103 if (mSettingsHelper.isLocationPackageBlacklisted(identity.getUserId(), 2104 identity.getPackageName())) { 2105 return false; 2106 } 2107 } 2108 2109 return true; 2110 } 2111 2112 @GuardedBy("mLock") 2113 @Override 2114 protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) { 2115 if (Build.IS_DEBUGGABLE) { 2116 Preconditions.checkState(Thread.holdsLock(mLock)); 2117 } 2118 2119 long intervalMs = ProviderRequest.INTERVAL_DISABLED; 2120 int quality = LocationRequest.QUALITY_LOW_POWER; 2121 long maxUpdateDelayMs = Long.MAX_VALUE; 2122 boolean adasGnssBypass = false; 2123 boolean locationSettingsIgnored = false; 2124 boolean lowPower = true; 2125 2126 for (Registration registration : registrations) { 2127 LocationRequest request = registration.getRequest(); 2128 2129 // passive requests do not contribute to the provider request, and passive requests 2130 // must handle the batching parameters of non-passive requests 2131 if (request.getIntervalMillis() == LocationRequest.PASSIVE_INTERVAL) { 2132 continue; 2133 } 2134 2135 intervalMs = min(request.getIntervalMillis(), intervalMs); 2136 quality = min(request.getQuality(), quality); 2137 maxUpdateDelayMs = min(request.getMaxUpdateDelayMillis(), maxUpdateDelayMs); 2138 adasGnssBypass |= request.isAdasGnssBypass(); 2139 locationSettingsIgnored |= request.isLocationSettingsIgnored(); 2140 lowPower &= request.isLowPower(); 2141 } 2142 2143 if (intervalMs == ProviderRequest.INTERVAL_DISABLED) { 2144 return ProviderRequest.EMPTY_REQUEST; 2145 } 2146 2147 if (maxUpdateDelayMs / 2 < intervalMs) { 2148 // reduces churn if only the batching parameter has changed 2149 maxUpdateDelayMs = 0; 2150 } 2151 2152 // calculate who to blame for power in a somewhat arbitrary fashion. we pick a threshold 2153 // interval slightly higher that the minimum interval, and spread the blame across all 2154 // contributing registrations under that threshold (since worksource does not allow us to 2155 // represent differing power blame ratios). 2156 long thresholdIntervalMs; 2157 try { 2158 thresholdIntervalMs = Math.multiplyExact(Math.addExact(intervalMs, 1000) / 2, 3); 2159 } catch (ArithmeticException e) { 2160 // check for and handle overflow by setting to one below the passive interval so passive 2161 // requests are automatically skipped 2162 thresholdIntervalMs = LocationRequest.PASSIVE_INTERVAL - 1; 2163 } 2164 2165 WorkSource workSource = new WorkSource(); 2166 for (Registration registration : registrations) { 2167 if (registration.getRequest().getIntervalMillis() <= thresholdIntervalMs) { 2168 workSource.add(registration.getRequest().getWorkSource()); 2169 } 2170 } 2171 2172 return new ProviderRequest.Builder() 2173 .setIntervalMillis(intervalMs) 2174 .setQuality(quality) 2175 .setMaxUpdateDelayMillis(maxUpdateDelayMs) 2176 .setAdasGnssBypass(adasGnssBypass) 2177 .setLocationSettingsIgnored(locationSettingsIgnored) 2178 .setLowPower(lowPower) 2179 .setWorkSource(workSource) 2180 .build(); 2181 } 2182 2183 @GuardedBy("mLock") 2184 protected long calculateRequestDelayMillis(long newIntervalMs, 2185 Collection<Registration> registrations) { 2186 // calculate the minimum delay across all registrations, ensuring that it is not more than 2187 // the requested interval 2188 long delayMs = newIntervalMs; 2189 for (Registration registration : registrations) { 2190 if (delayMs == 0) { 2191 break; 2192 } 2193 2194 LocationRequest locationRequest = registration.getRequest(); 2195 Location last = registration.getLastDeliveredLocation(); 2196 2197 if (last == null && !locationRequest.isLocationSettingsIgnored()) { 2198 // if this request has never gotten any location and it's not ignoring location 2199 // settings, then we pretend that this request has gotten the last applicable cached 2200 // location for our calculations instead. this prevents spammy add/remove behavior 2201 last = getLastLocationUnsafe( 2202 registration.getIdentity().getUserId(), 2203 registration.getPermissionLevel(), 2204 false, 2205 locationRequest.getIntervalMillis()); 2206 } 2207 2208 long registrationDelayMs; 2209 if (last == null) { 2210 // if this request has never gotten any location then there's no delay 2211 registrationDelayMs = 0; 2212 } else { 2213 // otherwise the delay is the amount of time until the next location is expected 2214 registrationDelayMs = max(0, 2215 locationRequest.getIntervalMillis() - last.getElapsedRealtimeAgeMillis()); 2216 } 2217 2218 delayMs = min(delayMs, registrationDelayMs); 2219 } 2220 2221 return delayMs; 2222 } 2223 2224 private void onUserChanged(int userId, int change) { 2225 synchronized (mLock) { 2226 if (mState == STATE_STOPPED) { 2227 return; 2228 } 2229 2230 switch (change) { 2231 case UserListener.CURRENT_USER_CHANGED: 2232 updateRegistrations( 2233 registration -> registration.getIdentity().getUserId() == userId); 2234 break; 2235 case UserListener.USER_STARTED: 2236 onUserStarted(userId); 2237 break; 2238 case UserListener.USER_STOPPED: 2239 onUserStopped(userId); 2240 break; 2241 } 2242 } 2243 } 2244 2245 private void onLocationUserSettingsChanged(int userId, LocationUserSettings oldSettings, 2246 LocationUserSettings newSettings) { 2247 if (oldSettings.isAdasGnssLocationEnabled() != newSettings.isAdasGnssLocationEnabled()) { 2248 synchronized (mLock) { 2249 updateRegistrations( 2250 registration -> registration.onAdasGnssLocationEnabledChanged(userId)); 2251 } 2252 } 2253 } 2254 2255 private void onLocationEnabledChanged(int userId) { 2256 synchronized (mLock) { 2257 if (mState == STATE_STOPPED) { 2258 return; 2259 } 2260 2261 onEnabledChanged(userId); 2262 } 2263 } 2264 2265 private void onScreenInteractiveChanged(boolean screenInteractive) { 2266 synchronized (mLock) { 2267 switch (mLocationPowerSaveModeHelper.getLocationPowerSaveMode()) { 2268 case LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF: 2269 if (!GPS_PROVIDER.equals(mName)) { 2270 break; 2271 } 2272 // fall through 2273 case LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF: 2274 // fall through 2275 case LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF: 2276 updateRegistrations(registration -> true); 2277 break; 2278 default: 2279 break; 2280 } 2281 } 2282 } 2283 2284 private void onBackgroundThrottlePackageWhitelistChanged() { 2285 synchronized (mLock) { 2286 updateRegistrations(Registration::onProviderLocationRequestChanged); 2287 } 2288 } 2289 2290 private void onBackgroundThrottleIntervalChanged() { 2291 synchronized (mLock) { 2292 updateRegistrations(Registration::onProviderLocationRequestChanged); 2293 } 2294 } 2295 2296 private void onLocationPowerSaveModeChanged(@LocationPowerSaveMode int locationPowerSaveMode) { 2297 synchronized (mLock) { 2298 // this is rare, just assume everything has changed to keep it simple 2299 updateRegistrations(registration -> true); 2300 } 2301 } 2302 2303 private void onAppForegroundChanged(int uid, boolean foreground) { 2304 synchronized (mLock) { 2305 updateRegistrations(registration -> registration.onForegroundChanged(uid, foreground)); 2306 } 2307 } 2308 2309 private void onIgnoreSettingsWhitelistChanged() { 2310 synchronized (mLock) { 2311 updateRegistrations(Registration::onProviderLocationRequestChanged); 2312 } 2313 } 2314 2315 private void onLocationPackageBlacklistChanged(int userId) { 2316 synchronized (mLock) { 2317 updateRegistrations(registration -> registration.getIdentity().getUserId() == userId); 2318 } 2319 } 2320 2321 private void onLocationPermissionsChanged(String packageName) { 2322 synchronized (mLock) { 2323 updateRegistrations( 2324 registration -> registration.onLocationPermissionsChanged(packageName)); 2325 } 2326 } 2327 2328 private void onLocationPermissionsChanged(int uid) { 2329 synchronized (mLock) { 2330 updateRegistrations(registration -> registration.onLocationPermissionsChanged(uid)); 2331 } 2332 } 2333 2334 @GuardedBy("mLock") 2335 @Override 2336 public void onStateChanged( 2337 AbstractLocationProvider.State oldState, AbstractLocationProvider.State newState) { 2338 if (Build.IS_DEBUGGABLE) { 2339 Preconditions.checkState(Thread.holdsLock(mLock)); 2340 } 2341 2342 if (oldState.allowed != newState.allowed) { 2343 onEnabledChanged(UserHandle.USER_ALL); 2344 } 2345 2346 if (!Objects.equals(oldState.properties, newState.properties)) { 2347 updateRegistrations(Registration::onProviderPropertiesChanged); 2348 } 2349 2350 if (mStateChangedListener != null) { 2351 StateChangedListener listener = mStateChangedListener; 2352 FgThread.getExecutor().execute( 2353 () -> listener.onStateChanged(mName, oldState, newState)); 2354 } 2355 } 2356 2357 @GuardedBy("mLock") 2358 @Override 2359 public void onReportLocation(LocationResult locationResult) { 2360 if (Build.IS_DEBUGGABLE) { 2361 Preconditions.checkState(Thread.holdsLock(mLock)); 2362 } 2363 2364 LocationResult filtered; 2365 if (mPassiveManager != null) { 2366 filtered = locationResult.filter(location -> { 2367 if (!location.isMock()) { 2368 if (location.getLatitude() == 0 && location.getLongitude() == 0) { 2369 Log.w(TAG, "blocking 0,0 location from " + mName + " provider"); 2370 return false; 2371 } 2372 } 2373 2374 if (!location.isComplete()) { 2375 Log.w(TAG, "blocking incomplete location from " + mName + " provider"); 2376 return false; 2377 } 2378 2379 return true; 2380 }); 2381 2382 if (filtered == null) { 2383 return; 2384 } 2385 2386 // don't log location received for passive provider because it's spammy 2387 EVENT_LOG.logProviderReceivedLocations(mName, filtered.size()); 2388 } else { 2389 // passive provider should get already filtered results as input 2390 filtered = locationResult; 2391 } 2392 2393 // update last location 2394 setLastLocation(filtered.getLastLocation(), UserHandle.USER_ALL); 2395 2396 // attempt listener delivery 2397 deliverToListeners(registration -> { 2398 return registration.acceptLocationChange(filtered); 2399 }); 2400 2401 // notify passive provider 2402 if (mPassiveManager != null) { 2403 mPassiveManager.updateLocation(filtered); 2404 } 2405 } 2406 2407 @GuardedBy("mLock") 2408 private void onUserStarted(int userId) { 2409 if (Build.IS_DEBUGGABLE) { 2410 Preconditions.checkState(Thread.holdsLock(mLock)); 2411 } 2412 2413 if (userId == UserHandle.USER_NULL) { 2414 return; 2415 } 2416 2417 if (userId == UserHandle.USER_ALL) { 2418 // clear the user's prior enabled state to prevent broadcast of enabled state change 2419 mEnabled.clear(); 2420 onEnabledChanged(UserHandle.USER_ALL); 2421 } else { 2422 Preconditions.checkArgument(userId >= 0); 2423 2424 // clear the user's prior enabled state to prevent broadcast of enabled state change 2425 mEnabled.delete(userId); 2426 onEnabledChanged(userId); 2427 } 2428 } 2429 2430 @GuardedBy("mLock") 2431 private void onUserStopped(int userId) { 2432 if (Build.IS_DEBUGGABLE) { 2433 Preconditions.checkState(Thread.holdsLock(mLock)); 2434 } 2435 2436 if (userId == UserHandle.USER_NULL) { 2437 return; 2438 } 2439 2440 if (userId == UserHandle.USER_ALL) { 2441 mEnabled.clear(); 2442 mLastLocations.clear(); 2443 } else { 2444 Preconditions.checkArgument(userId >= 0); 2445 mEnabled.delete(userId); 2446 mLastLocations.remove(userId); 2447 } 2448 } 2449 2450 @GuardedBy("mLock") 2451 private void onEnabledChanged(int userId) { 2452 if (Build.IS_DEBUGGABLE) { 2453 Preconditions.checkState(Thread.holdsLock(mLock)); 2454 } 2455 2456 if (userId == UserHandle.USER_NULL) { 2457 // used during initialization - ignore since many lower level operations (checking 2458 // settings for instance) do not support the null user 2459 return; 2460 } else if (userId == UserHandle.USER_ALL) { 2461 final int[] runningUserIds = mUserHelper.getRunningUserIds(); 2462 for (int i = 0; i < runningUserIds.length; i++) { 2463 onEnabledChanged(runningUserIds[i]); 2464 } 2465 return; 2466 } 2467 2468 Preconditions.checkArgument(userId >= 0); 2469 2470 boolean enabled = mState == STATE_STARTED 2471 && mProvider.getState().allowed 2472 && mSettingsHelper.isLocationEnabled(userId); 2473 2474 int index = mEnabled.indexOfKey(userId); 2475 Boolean wasEnabled = index < 0 ? null : mEnabled.valueAt(index); 2476 if (wasEnabled != null && wasEnabled == enabled) { 2477 return; 2478 } 2479 2480 mEnabled.put(userId, enabled); 2481 2482 // don't log unknown -> false transitions for brevity 2483 if (wasEnabled != null || enabled) { 2484 if (D) { 2485 Log.d(TAG, "[u" + userId + "] " + mName + " provider enabled = " + enabled); 2486 } 2487 EVENT_LOG.logProviderEnabled(mName, userId, enabled); 2488 } 2489 2490 // clear last locations if we become disabled 2491 if (!enabled) { 2492 LastLocation lastLocation = mLastLocations.get(userId); 2493 if (lastLocation != null) { 2494 lastLocation.clearLocations(); 2495 } 2496 } 2497 2498 // do not send change notifications if we just saw this user for the first time 2499 if (wasEnabled != null) { 2500 // passive provider never get public updates for legacy reasons 2501 if (!PASSIVE_PROVIDER.equals(mName)) { 2502 Intent intent = new Intent(LocationManager.PROVIDERS_CHANGED_ACTION) 2503 .putExtra(LocationManager.EXTRA_PROVIDER_NAME, mName) 2504 .putExtra(LocationManager.EXTRA_PROVIDER_ENABLED, enabled) 2505 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) 2506 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 2507 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); 2508 } 2509 2510 // send updates to internal listeners - since we expect listener changes to be more 2511 // frequent than enabled changes, we use copy-on-read instead of copy-on-write 2512 if (!mEnabledListeners.isEmpty()) { 2513 ProviderEnabledListener[] listeners = mEnabledListeners.toArray( 2514 new ProviderEnabledListener[0]); 2515 FgThread.getHandler().post(() -> { 2516 for (int i = 0; i < listeners.length; i++) { 2517 listeners[i].onProviderEnabledChanged(mName, userId, enabled); 2518 } 2519 }); 2520 } 2521 } 2522 2523 // update active state of affected registrations 2524 updateRegistrations(registration -> registration.getIdentity().getUserId() == userId); 2525 } 2526 2527 @Nullable Location getPermittedLocation(@Nullable Location fineLocation, 2528 @PermissionLevel int permissionLevel) { 2529 switch (permissionLevel) { 2530 case PERMISSION_FINE: 2531 return fineLocation; 2532 case PERMISSION_COARSE: 2533 return fineLocation != null ? mLocationFudger.createCoarse(fineLocation) : null; 2534 default: 2535 // shouldn't be possible to have a client added without location permissions 2536 throw new AssertionError(); 2537 } 2538 } 2539 2540 @Nullable LocationResult getPermittedLocationResult( 2541 @Nullable LocationResult fineLocationResult, @PermissionLevel int permissionLevel) { 2542 switch (permissionLevel) { 2543 case PERMISSION_FINE: 2544 return fineLocationResult; 2545 case PERMISSION_COARSE: 2546 return fineLocationResult != null ? mLocationFudger.createCoarse(fineLocationResult) 2547 : null; 2548 default: 2549 // shouldn't be possible to have a client added without location permissions 2550 throw new AssertionError(); 2551 } 2552 } 2553 2554 public void dump(FileDescriptor fd, IndentingPrintWriter ipw, String[] args) { 2555 synchronized (mLock) { 2556 ipw.print(mName); 2557 ipw.print(" provider"); 2558 if (mProvider.isMock()) { 2559 ipw.print(" [mock]"); 2560 } 2561 ipw.println(":"); 2562 ipw.increaseIndent(); 2563 2564 super.dump(fd, ipw, args); 2565 2566 int[] userIds = mUserHelper.getRunningUserIds(); 2567 for (int userId : userIds) { 2568 if (userIds.length != 1) { 2569 ipw.print("user "); 2570 ipw.print(userId); 2571 ipw.println(":"); 2572 ipw.increaseIndent(); 2573 } 2574 ipw.print("last location="); 2575 ipw.println(getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE)); 2576 ipw.print("enabled="); 2577 ipw.println(isEnabled(userId)); 2578 if (userIds.length != 1) { 2579 ipw.decreaseIndent(); 2580 } 2581 } 2582 } 2583 2584 mProvider.dump(fd, ipw, args); 2585 2586 ipw.decreaseIndent(); 2587 } 2588 2589 @Override 2590 protected String getServiceState() { 2591 return mProvider.getCurrentRequest().toString(); 2592 } 2593 2594 private static class LastLocation { 2595 2596 private @Nullable Location mFineLocation; 2597 private @Nullable Location mCoarseLocation; 2598 private @Nullable Location mFineBypassLocation; 2599 private @Nullable Location mCoarseBypassLocation; 2600 2601 LastLocation() {} 2602 2603 public void clearMock() { 2604 if (mFineLocation != null && mFineLocation.isMock()) { 2605 mFineLocation = null; 2606 } 2607 if (mCoarseLocation != null && mCoarseLocation.isMock()) { 2608 mCoarseLocation = null; 2609 } 2610 if (mFineBypassLocation != null && mFineBypassLocation.isMock()) { 2611 mFineBypassLocation = null; 2612 } 2613 if (mCoarseBypassLocation != null && mCoarseBypassLocation.isMock()) { 2614 mCoarseBypassLocation = null; 2615 } 2616 } 2617 2618 public void clearLocations() { 2619 mFineLocation = null; 2620 mCoarseLocation = null; 2621 } 2622 2623 public @Nullable Location get(@PermissionLevel int permissionLevel, 2624 boolean isBypass) { 2625 switch (permissionLevel) { 2626 case PERMISSION_FINE: 2627 if (isBypass) { 2628 return mFineBypassLocation; 2629 } else { 2630 return mFineLocation; 2631 } 2632 case PERMISSION_COARSE: 2633 if (isBypass) { 2634 return mCoarseBypassLocation; 2635 } else { 2636 return mCoarseLocation; 2637 } 2638 default: 2639 // shouldn't be possible to have a client added without location permissions 2640 throw new AssertionError(); 2641 } 2642 } 2643 2644 public void set(Location location) { 2645 mFineLocation = calculateNextFine(mFineLocation, location); 2646 mCoarseLocation = calculateNextCoarse(mCoarseLocation, location); 2647 } 2648 2649 public void setBypass(Location location) { 2650 mFineBypassLocation = calculateNextFine(mFineBypassLocation, location); 2651 mCoarseBypassLocation = calculateNextCoarse(mCoarseBypassLocation, location); 2652 } 2653 2654 private Location calculateNextFine(@Nullable Location oldFine, Location newFine) { 2655 if (oldFine == null) { 2656 return newFine; 2657 } 2658 2659 // update last fine interval only if more recent 2660 if (newFine.getElapsedRealtimeNanos() > oldFine.getElapsedRealtimeNanos()) { 2661 return newFine; 2662 } else { 2663 return oldFine; 2664 } 2665 } 2666 2667 private Location calculateNextCoarse(@Nullable Location oldCoarse, Location newCoarse) { 2668 if (oldCoarse == null) { 2669 return newCoarse; 2670 } 2671 2672 // update last coarse interval only if enough time has passed 2673 if (newCoarse.getElapsedRealtimeMillis() - MIN_COARSE_INTERVAL_MS 2674 > oldCoarse.getElapsedRealtimeMillis()) { 2675 return newCoarse; 2676 } else { 2677 return oldCoarse; 2678 } 2679 } 2680 } 2681 2682 private static class SingleUseCallback extends IRemoteCallback.Stub implements Runnable, 2683 CancellationSignal.OnCancelListener { 2684 2685 public static @Nullable SingleUseCallback wrap(@Nullable Runnable callback) { 2686 return callback == null ? null : new SingleUseCallback(callback); 2687 } 2688 2689 @GuardedBy("this") 2690 private @Nullable Runnable mCallback; 2691 2692 private SingleUseCallback(Runnable callback) { 2693 mCallback = Objects.requireNonNull(callback); 2694 } 2695 2696 @Override 2697 public void sendResult(Bundle data) { 2698 run(); 2699 } 2700 2701 @Override 2702 public void onCancel() { 2703 run(); 2704 } 2705 2706 @Override 2707 public void run() { 2708 Runnable callback; 2709 synchronized (this) { 2710 callback = mCallback; 2711 mCallback = null; 2712 } 2713 2714 // prevent this callback from being run more than once - otherwise this could provide an 2715 // attack vector for a malicious app to break assumptions on how many times a callback 2716 // may be invoked, and thus crash system server. 2717 if (callback == null) { 2718 return; 2719 } 2720 2721 final long identity = Binder.clearCallingIdentity(); 2722 try { 2723 callback.run(); 2724 } catch (RuntimeException e) { 2725 // since this is within a oneway binder transaction there is nowhere 2726 // for exceptions to go - move onto another thread to crash system 2727 // server so we find out about it 2728 FgThread.getExecutor().execute(() -> { 2729 throw new AssertionError(e); 2730 }); 2731 throw e; 2732 } finally { 2733 Binder.restoreCallingIdentity(identity); 2734 } 2735 } 2736 } 2737 } 2738