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