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