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