1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.location; 18 19 import static android.Manifest.permission.ACCESS_FINE_LOCATION; 20 import static android.app.compat.CompatChanges.isChangeEnabled; 21 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; 22 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; 23 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 24 import static android.location.LocationManager.BLOCK_PENDING_INTENT_SYSTEM_API_USAGE; 25 import static android.location.LocationManager.FUSED_PROVIDER; 26 import static android.location.LocationManager.GPS_PROVIDER; 27 import static android.location.LocationManager.NETWORK_PROVIDER; 28 import static android.location.LocationRequest.LOW_POWER_EXCEPTIONS; 29 import static android.location.provider.LocationProviderBase.ACTION_FUSED_PROVIDER; 30 import static android.location.provider.LocationProviderBase.ACTION_NETWORK_PROVIDER; 31 32 import static com.android.server.location.LocationPermissions.PERMISSION_COARSE; 33 import static com.android.server.location.LocationPermissions.PERMISSION_FINE; 34 import static com.android.server.location.eventlog.LocationEventLog.EVENT_LOG; 35 36 import static java.util.concurrent.TimeUnit.NANOSECONDS; 37 38 import android.Manifest; 39 import android.Manifest.permission; 40 import android.annotation.NonNull; 41 import android.annotation.Nullable; 42 import android.app.ActivityManager; 43 import android.app.AppOpsManager; 44 import android.app.PendingIntent; 45 import android.app.compat.CompatChanges; 46 import android.content.Context; 47 import android.content.Intent; 48 import android.content.pm.PackageManager; 49 import android.location.Criteria; 50 import android.location.GeocoderParams; 51 import android.location.Geofence; 52 import android.location.GnssAntennaInfo; 53 import android.location.GnssCapabilities; 54 import android.location.GnssMeasurementCorrections; 55 import android.location.GnssMeasurementRequest; 56 import android.location.IGeocodeListener; 57 import android.location.IGnssAntennaInfoListener; 58 import android.location.IGnssMeasurementsListener; 59 import android.location.IGnssNavigationMessageListener; 60 import android.location.IGnssNmeaListener; 61 import android.location.IGnssStatusListener; 62 import android.location.ILocationCallback; 63 import android.location.ILocationListener; 64 import android.location.ILocationManager; 65 import android.location.LastLocationRequest; 66 import android.location.Location; 67 import android.location.LocationManager; 68 import android.location.LocationManagerInternal; 69 import android.location.LocationManagerInternal.LocationPackageTagsListener; 70 import android.location.LocationProvider; 71 import android.location.LocationRequest; 72 import android.location.LocationTime; 73 import android.location.provider.IProviderRequestListener; 74 import android.location.provider.ProviderProperties; 75 import android.location.util.identity.CallerIdentity; 76 import android.os.Binder; 77 import android.os.Build; 78 import android.os.Bundle; 79 import android.os.ICancellationSignal; 80 import android.os.PackageTagsList; 81 import android.os.ParcelFileDescriptor; 82 import android.os.Process; 83 import android.os.RemoteException; 84 import android.os.UserHandle; 85 import android.os.WorkSource; 86 import android.os.WorkSource.WorkChain; 87 import android.provider.Settings; 88 import android.stats.location.LocationStatsEnums; 89 import android.util.ArrayMap; 90 import android.util.ArraySet; 91 import android.util.IndentingPrintWriter; 92 import android.util.Log; 93 94 import com.android.internal.annotations.GuardedBy; 95 import com.android.internal.util.ArrayUtils; 96 import com.android.internal.util.DumpUtils; 97 import com.android.internal.util.Preconditions; 98 import com.android.server.FgThread; 99 import com.android.server.LocalServices; 100 import com.android.server.SystemService; 101 import com.android.server.location.eventlog.LocationEventLog; 102 import com.android.server.location.geofence.GeofenceManager; 103 import com.android.server.location.geofence.GeofenceProxy; 104 import com.android.server.location.gnss.GnssConfiguration; 105 import com.android.server.location.gnss.GnssManagerService; 106 import com.android.server.location.gnss.hal.GnssNative; 107 import com.android.server.location.injector.AlarmHelper; 108 import com.android.server.location.injector.AppForegroundHelper; 109 import com.android.server.location.injector.AppOpsHelper; 110 import com.android.server.location.injector.DeviceIdleHelper; 111 import com.android.server.location.injector.DeviceStationaryHelper; 112 import com.android.server.location.injector.EmergencyHelper; 113 import com.android.server.location.injector.Injector; 114 import com.android.server.location.injector.LocationAttributionHelper; 115 import com.android.server.location.injector.LocationPermissionsHelper; 116 import com.android.server.location.injector.LocationPowerSaveModeHelper; 117 import com.android.server.location.injector.LocationUsageLogger; 118 import com.android.server.location.injector.ScreenInteractiveHelper; 119 import com.android.server.location.injector.SettingsHelper; 120 import com.android.server.location.injector.SystemAlarmHelper; 121 import com.android.server.location.injector.SystemAppForegroundHelper; 122 import com.android.server.location.injector.SystemAppOpsHelper; 123 import com.android.server.location.injector.SystemDeviceIdleHelper; 124 import com.android.server.location.injector.SystemDeviceStationaryHelper; 125 import com.android.server.location.injector.SystemEmergencyHelper; 126 import com.android.server.location.injector.SystemLocationPermissionsHelper; 127 import com.android.server.location.injector.SystemLocationPowerSaveModeHelper; 128 import com.android.server.location.injector.SystemScreenInteractiveHelper; 129 import com.android.server.location.injector.SystemSettingsHelper; 130 import com.android.server.location.injector.SystemUserInfoHelper; 131 import com.android.server.location.injector.UserInfoHelper; 132 import com.android.server.location.provider.AbstractLocationProvider; 133 import com.android.server.location.provider.LocationProviderManager; 134 import com.android.server.location.provider.MockLocationProvider; 135 import com.android.server.location.provider.PassiveLocationProvider; 136 import com.android.server.location.provider.PassiveLocationProviderManager; 137 import com.android.server.location.provider.StationaryThrottlingLocationProvider; 138 import com.android.server.location.provider.proxy.ProxyLocationProvider; 139 import com.android.server.location.settings.LocationSettings; 140 import com.android.server.location.settings.LocationUserSettings; 141 import com.android.server.pm.permission.LegacyPermissionManagerInternal; 142 143 import java.io.FileDescriptor; 144 import java.io.PrintWriter; 145 import java.util.ArrayList; 146 import java.util.Collections; 147 import java.util.List; 148 import java.util.Objects; 149 import java.util.concurrent.CopyOnWriteArrayList; 150 151 /** 152 * The service class that manages LocationProviders and issues location 153 * updates and alerts. 154 */ 155 public class LocationManagerService extends ILocationManager.Stub implements 156 LocationProviderManager.StateChangedListener { 157 158 /** 159 * Controls lifecycle of LocationManagerService. 160 */ 161 public static class Lifecycle extends SystemService { 162 163 private final LifecycleUserInfoHelper mUserInfoHelper; 164 private final SystemInjector mSystemInjector; 165 private final LocationManagerService mService; 166 Lifecycle(Context context)167 public Lifecycle(Context context) { 168 super(context); 169 mUserInfoHelper = new LifecycleUserInfoHelper(context); 170 mSystemInjector = new SystemInjector(context, mUserInfoHelper); 171 mService = new LocationManagerService(context, mSystemInjector); 172 } 173 174 @Override onStart()175 public void onStart() { 176 publishBinderService(Context.LOCATION_SERVICE, mService); 177 178 // client caching behavior is only enabled after seeing the first invalidate 179 LocationManager.invalidateLocalLocationEnabledCaches(); 180 // disable caching for our own process 181 LocationManager.disableLocalLocationEnabledCaches(); 182 } 183 184 @Override onBootPhase(int phase)185 public void onBootPhase(int phase) { 186 if (phase == PHASE_SYSTEM_SERVICES_READY) { 187 // the location service must be functioning after this boot phase 188 mSystemInjector.onSystemReady(); 189 mService.onSystemReady(); 190 } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { 191 // some providers rely on third party code, so we wait to initialize 192 // providers until third party code is allowed to run 193 mService.onSystemThirdPartyAppsCanStart(); 194 } 195 } 196 197 @Override onUserStarting(TargetUser user)198 public void onUserStarting(TargetUser user) { 199 mUserInfoHelper.onUserStarted(user.getUserIdentifier()); 200 } 201 202 @Override onUserSwitching(TargetUser from, TargetUser to)203 public void onUserSwitching(TargetUser from, TargetUser to) { 204 mUserInfoHelper.onCurrentUserChanged(from.getUserIdentifier(), 205 to.getUserIdentifier()); 206 } 207 208 @Override onUserStopped(TargetUser user)209 public void onUserStopped(TargetUser user) { 210 mUserInfoHelper.onUserStopped(user.getUserIdentifier()); 211 } 212 213 private static class LifecycleUserInfoHelper extends SystemUserInfoHelper { 214 LifecycleUserInfoHelper(Context context)215 LifecycleUserInfoHelper(Context context) { 216 super(context); 217 } 218 onUserStarted(int userId)219 void onUserStarted(int userId) { 220 dispatchOnUserStarted(userId); 221 } 222 onUserStopped(int userId)223 void onUserStopped(int userId) { 224 dispatchOnUserStopped(userId); 225 } 226 onCurrentUserChanged(int fromUserId, int toUserId)227 void onCurrentUserChanged(int fromUserId, int toUserId) { 228 dispatchOnCurrentUserChanged(fromUserId, toUserId); 229 } 230 } 231 } 232 233 public static final String TAG = "LocationManagerService"; 234 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); 235 236 private static final String ATTRIBUTION_TAG = "LocationService"; 237 238 final Object mLock = new Object(); 239 240 private final Context mContext; 241 private final Injector mInjector; 242 private final LocalService mLocalService; 243 244 private final GeofenceManager mGeofenceManager; 245 private volatile @Nullable GnssManagerService mGnssManagerService = null; 246 private GeocoderProxy mGeocodeProvider; 247 248 private final Object mDeprecatedGnssBatchingLock = new Object(); 249 @GuardedBy("mDeprecatedGnssBatchingLock") 250 private @Nullable ILocationListener mDeprecatedGnssBatchingListener; 251 252 @GuardedBy("mLock") 253 private String mExtraLocationControllerPackage; 254 @GuardedBy("mLock") 255 private boolean mExtraLocationControllerPackageEnabled; 256 257 // location provider managers 258 259 private final PassiveLocationProviderManager mPassiveManager; 260 261 // @GuardedBy("mProviderManagers") 262 // hold lock for writes, no lock necessary for simple reads 263 final CopyOnWriteArrayList<LocationProviderManager> mProviderManagers = 264 new CopyOnWriteArrayList<>(); 265 266 @GuardedBy("mLock") 267 @Nullable LocationPackageTagsListener mLocationTagsChangedListener; 268 LocationManagerService(Context context, Injector injector)269 LocationManagerService(Context context, Injector injector) { 270 mContext = context.createAttributionContext(ATTRIBUTION_TAG); 271 mInjector = injector; 272 mLocalService = new LocalService(); 273 LocalServices.addService(LocationManagerInternal.class, mLocalService); 274 275 mGeofenceManager = new GeofenceManager(mContext, injector); 276 277 mInjector.getLocationSettings().registerLocationUserSettingsListener( 278 this::onLocationUserSettingsChanged); 279 mInjector.getSettingsHelper().addOnLocationEnabledChangedListener( 280 this::onLocationModeChanged); 281 mInjector.getSettingsHelper().addIgnoreSettingsAllowlistChangedListener( 282 () -> refreshAppOpsRestrictions(UserHandle.USER_ALL)); 283 mInjector.getUserInfoHelper().addListener((userId, change) -> { 284 if (change == UserInfoHelper.UserListener.USER_STARTED) { 285 refreshAppOpsRestrictions(userId); 286 } 287 }); 288 289 // set up passive provider first since it will be required for all other location providers, 290 // which are loaded later once the system is ready. 291 mPassiveManager = new PassiveLocationProviderManager(mContext, injector); 292 addLocationProviderManager(mPassiveManager, new PassiveLocationProvider(mContext)); 293 294 // TODO: load the gps provider here as well, which will require refactoring 295 296 // Let the package manager query which are the default location 297 // providers as they get certain permissions granted by default. 298 LegacyPermissionManagerInternal permissionManagerInternal = LocalServices.getService( 299 LegacyPermissionManagerInternal.class); 300 permissionManagerInternal.setLocationPackagesProvider( 301 userId -> mContext.getResources().getStringArray( 302 com.android.internal.R.array.config_locationProviderPackageNames)); 303 permissionManagerInternal.setLocationExtraPackagesProvider( 304 userId -> mContext.getResources().getStringArray( 305 com.android.internal.R.array.config_locationExtraPackageNames)); 306 } 307 308 @Nullable getLocationProviderManager(String providerName)309 LocationProviderManager getLocationProviderManager(String providerName) { 310 if (providerName == null) { 311 return null; 312 } 313 314 for (LocationProviderManager manager : mProviderManagers) { 315 if (providerName.equals(manager.getName())) { 316 return manager; 317 } 318 } 319 320 return null; 321 } 322 getOrAddLocationProviderManager(String providerName)323 private LocationProviderManager getOrAddLocationProviderManager(String providerName) { 324 synchronized (mProviderManagers) { 325 for (LocationProviderManager manager : mProviderManagers) { 326 if (providerName.equals(manager.getName())) { 327 return manager; 328 } 329 } 330 331 LocationProviderManager manager = new LocationProviderManager(mContext, mInjector, 332 providerName, mPassiveManager); 333 addLocationProviderManager(manager, null); 334 return manager; 335 } 336 } 337 addLocationProviderManager(LocationProviderManager manager, @Nullable AbstractLocationProvider realProvider)338 private void addLocationProviderManager(LocationProviderManager manager, 339 @Nullable AbstractLocationProvider realProvider) { 340 synchronized (mProviderManagers) { 341 Preconditions.checkState(getLocationProviderManager(manager.getName()) == null); 342 343 manager.startManager(this); 344 345 if (realProvider != null) { 346 // custom logic wrapping all non-passive providers 347 if (manager != mPassiveManager) { 348 boolean enableStationaryThrottling = Settings.Global.getInt( 349 mContext.getContentResolver(), 350 Settings.Global.LOCATION_ENABLE_STATIONARY_THROTTLE, 1) != 0; 351 if (enableStationaryThrottling) { 352 realProvider = new StationaryThrottlingLocationProvider(manager.getName(), 353 mInjector, realProvider); 354 } 355 } 356 manager.setRealProvider(realProvider); 357 } 358 mProviderManagers.add(manager); 359 } 360 } 361 removeLocationProviderManager(LocationProviderManager manager)362 private void removeLocationProviderManager(LocationProviderManager manager) { 363 synchronized (mProviderManagers) { 364 boolean removed = mProviderManagers.remove(manager); 365 Preconditions.checkArgument(removed); 366 manager.setMockProvider(null); 367 manager.setRealProvider(null); 368 manager.stopManager(); 369 } 370 } 371 onSystemReady()372 void onSystemReady() { 373 if (Build.IS_DEBUGGABLE) { 374 // on debug builds, watch for location noteOps while location is off. there are some 375 // scenarios (emergency location) where this is expected, but generally this should 376 // rarely occur, and may indicate bugs. dump occurrences to logs for further evaluation 377 AppOpsManager appOps = Objects.requireNonNull( 378 mContext.getSystemService(AppOpsManager.class)); 379 appOps.startWatchingNoted( 380 new int[]{AppOpsManager.OP_FINE_LOCATION, AppOpsManager.OP_COARSE_LOCATION}, 381 (code, uid, packageName, attributionTag, flags, result) -> { 382 if (!isLocationEnabledForUser(UserHandle.getUserId(uid))) { 383 Log.w(TAG, "location noteOp with location off - " 384 + CallerIdentity.forTest(uid, 0, packageName, attributionTag)); 385 } 386 }); 387 } 388 } 389 onSystemThirdPartyAppsCanStart()390 void onSystemThirdPartyAppsCanStart() { 391 // network provider should always be initialized before the gps provider since the gps 392 // provider has unfortunate hard dependencies on the network provider 393 ProxyLocationProvider networkProvider = ProxyLocationProvider.create( 394 mContext, 395 NETWORK_PROVIDER, 396 ACTION_NETWORK_PROVIDER, 397 com.android.internal.R.bool.config_enableNetworkLocationOverlay, 398 com.android.internal.R.string.config_networkLocationProviderPackageName); 399 if (networkProvider != null) { 400 LocationProviderManager networkManager = new LocationProviderManager(mContext, 401 mInjector, NETWORK_PROVIDER, mPassiveManager); 402 addLocationProviderManager(networkManager, networkProvider); 403 } else { 404 Log.w(TAG, "no network location provider found"); 405 } 406 407 // ensure that a fused provider exists which will work in direct boot 408 Preconditions.checkState(!mContext.getPackageManager().queryIntentServicesAsUser( 409 new Intent(ACTION_FUSED_PROVIDER), 410 MATCH_DIRECT_BOOT_AWARE | MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM).isEmpty(), 411 "Unable to find a direct boot aware fused location provider"); 412 413 ProxyLocationProvider fusedProvider = ProxyLocationProvider.create( 414 mContext, 415 FUSED_PROVIDER, 416 ACTION_FUSED_PROVIDER, 417 com.android.internal.R.bool.config_enableFusedLocationOverlay, 418 com.android.internal.R.string.config_fusedLocationProviderPackageName); 419 if (fusedProvider != null) { 420 LocationProviderManager fusedManager = new LocationProviderManager(mContext, mInjector, 421 FUSED_PROVIDER, mPassiveManager); 422 addLocationProviderManager(fusedManager, fusedProvider); 423 } else { 424 Log.wtf(TAG, "no fused location provider found"); 425 } 426 427 // initialize gnss last because it has no awareness of boot phases and blindly assumes that 428 // all other location providers are loaded at initialization 429 if (GnssNative.isSupported()) { 430 GnssConfiguration gnssConfiguration = new GnssConfiguration(mContext); 431 GnssNative gnssNative = GnssNative.create(mInjector, gnssConfiguration); 432 mGnssManagerService = new GnssManagerService(mContext, mInjector, gnssNative); 433 mGnssManagerService.onSystemReady(); 434 435 LocationProviderManager gnssManager = new LocationProviderManager(mContext, mInjector, 436 GPS_PROVIDER, mPassiveManager); 437 addLocationProviderManager(gnssManager, mGnssManagerService.getGnssLocationProvider()); 438 } 439 440 // bind to geocoder provider 441 mGeocodeProvider = GeocoderProxy.createAndRegister(mContext); 442 if (mGeocodeProvider == null) { 443 Log.e(TAG, "no geocoder provider found"); 444 } 445 446 // bind to hardware activity recognition 447 HardwareActivityRecognitionProxy hardwareActivityRecognitionProxy = 448 HardwareActivityRecognitionProxy.createAndRegister(mContext); 449 if (hardwareActivityRecognitionProxy == null) { 450 Log.e(TAG, "unable to bind ActivityRecognitionProxy"); 451 } 452 453 // bind to gnss geofence proxy 454 if (mGnssManagerService != null) { 455 GeofenceProxy provider = GeofenceProxy.createAndBind(mContext, 456 mGnssManagerService.getGnssGeofenceProxy()); 457 if (provider == null) { 458 Log.e(TAG, "unable to bind to GeofenceProxy"); 459 } 460 } 461 462 // create any predefined test providers 463 String[] testProviderStrings = mContext.getResources().getStringArray( 464 com.android.internal.R.array.config_testLocationProviders); 465 for (String testProviderString : testProviderStrings) { 466 String[] fragments = testProviderString.split(","); 467 String name = fragments[0].trim(); 468 ProviderProperties properties = new ProviderProperties.Builder() 469 .setHasNetworkRequirement(Boolean.parseBoolean(fragments[1])) 470 .setHasSatelliteRequirement(Boolean.parseBoolean(fragments[2])) 471 .setHasCellRequirement(Boolean.parseBoolean(fragments[3])) 472 .setHasMonetaryCost(Boolean.parseBoolean(fragments[4])) 473 .setHasAltitudeSupport(Boolean.parseBoolean(fragments[5])) 474 .setHasSpeedSupport(Boolean.parseBoolean(fragments[6])) 475 .setHasBearingSupport(Boolean.parseBoolean(fragments[7])) 476 .setPowerUsage(Integer.parseInt(fragments[8])) 477 .setAccuracy(Integer.parseInt(fragments[9])) 478 .build(); 479 final LocationProviderManager manager = getOrAddLocationProviderManager(name); 480 manager.setMockProvider(new MockLocationProvider(properties, 481 CallerIdentity.fromContext(mContext), Collections.emptySet())); 482 } 483 } 484 onLocationUserSettingsChanged(int userId, LocationUserSettings oldSettings, LocationUserSettings newSettings)485 private void onLocationUserSettingsChanged(int userId, LocationUserSettings oldSettings, 486 LocationUserSettings newSettings) { 487 if (oldSettings.isAdasGnssLocationEnabled() != newSettings.isAdasGnssLocationEnabled()) { 488 boolean enabled = newSettings.isAdasGnssLocationEnabled(); 489 490 if (D) { 491 Log.d(TAG, "[u" + userId + "] adas gnss location enabled = " + enabled); 492 } 493 494 EVENT_LOG.logAdasLocationEnabled(userId, enabled); 495 496 Intent intent = new Intent(LocationManager.ACTION_ADAS_GNSS_ENABLED_CHANGED) 497 .putExtra(LocationManager.EXTRA_ADAS_GNSS_ENABLED, enabled) 498 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) 499 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 500 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); 501 } 502 } 503 onLocationModeChanged(int userId)504 private void onLocationModeChanged(int userId) { 505 boolean enabled = mInjector.getSettingsHelper().isLocationEnabled(userId); 506 LocationManager.invalidateLocalLocationEnabledCaches(); 507 508 if (D) { 509 Log.d(TAG, "[u" + userId + "] location enabled = " + enabled); 510 } 511 512 EVENT_LOG.logLocationEnabled(userId, enabled); 513 514 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION) 515 .putExtra(LocationManager.EXTRA_LOCATION_ENABLED, enabled) 516 .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY) 517 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 518 mContext.sendBroadcastAsUser(intent, UserHandle.of(userId)); 519 520 refreshAppOpsRestrictions(userId); 521 } 522 523 @Override getGnssYearOfHardware()524 public int getGnssYearOfHardware() { 525 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssYearOfHardware(); 526 } 527 528 @Override 529 @Nullable getGnssHardwareModelName()530 public String getGnssHardwareModelName() { 531 return mGnssManagerService == null ? "" : mGnssManagerService.getGnssHardwareModelName(); 532 } 533 534 @Override getGnssBatchSize()535 public int getGnssBatchSize() { 536 return mGnssManagerService == null ? 0 : mGnssManagerService.getGnssBatchSize(); 537 } 538 539 @Override startGnssBatch(long periodNanos, ILocationListener listener, String packageName, @Nullable String attributionTag, String listenerId)540 public void startGnssBatch(long periodNanos, ILocationListener listener, String packageName, 541 @Nullable String attributionTag, String listenerId) { 542 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null); 543 544 if (mGnssManagerService == null) { 545 return; 546 } 547 548 long intervalMs = NANOSECONDS.toMillis(periodNanos); 549 550 synchronized (mDeprecatedGnssBatchingLock) { 551 stopGnssBatch(); 552 553 registerLocationListener( 554 GPS_PROVIDER, 555 new LocationRequest.Builder(intervalMs) 556 .setMaxUpdateDelayMillis( 557 intervalMs * mGnssManagerService.getGnssBatchSize()) 558 .setHiddenFromAppOps(true) 559 .build(), 560 listener, 561 packageName, 562 attributionTag, 563 listenerId); 564 mDeprecatedGnssBatchingListener = listener; 565 } 566 } 567 568 @Override flushGnssBatch()569 public void flushGnssBatch() { 570 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null); 571 572 if (mGnssManagerService == null) { 573 return; 574 } 575 576 synchronized (mDeprecatedGnssBatchingLock) { 577 if (mDeprecatedGnssBatchingListener != null) { 578 requestListenerFlush(GPS_PROVIDER, mDeprecatedGnssBatchingListener, 0); 579 } 580 } 581 } 582 583 @Override stopGnssBatch()584 public void stopGnssBatch() { 585 mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null); 586 587 if (mGnssManagerService == null) { 588 return; 589 } 590 591 synchronized (mDeprecatedGnssBatchingLock) { 592 if (mDeprecatedGnssBatchingListener != null) { 593 ILocationListener listener = mDeprecatedGnssBatchingListener; 594 mDeprecatedGnssBatchingListener = null; 595 unregisterLocationListener(listener); 596 } 597 } 598 } 599 600 @Override hasProvider(String provider)601 public boolean hasProvider(String provider) { 602 return getLocationProviderManager(provider) != null; 603 } 604 605 @Override getAllProviders()606 public List<String> getAllProviders() { 607 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size()); 608 for (LocationProviderManager manager : mProviderManagers) { 609 providers.add(manager.getName()); 610 } 611 return providers; 612 } 613 614 @Override getProviders(Criteria criteria, boolean enabledOnly)615 public List<String> getProviders(Criteria criteria, boolean enabledOnly) { 616 if (!LocationPermissions.checkCallingOrSelfLocationPermission(mContext, 617 PERMISSION_COARSE)) { 618 return Collections.emptyList(); 619 } 620 621 synchronized (mLock) { 622 ArrayList<String> providers = new ArrayList<>(mProviderManagers.size()); 623 for (LocationProviderManager manager : mProviderManagers) { 624 String name = manager.getName(); 625 if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) { 626 continue; 627 } 628 if (criteria != null && !LocationProvider.propertiesMeetCriteria(name, 629 manager.getProperties(), criteria)) { 630 continue; 631 } 632 providers.add(name); 633 } 634 return providers; 635 } 636 } 637 638 @Override getBestProvider(Criteria criteria, boolean enabledOnly)639 public String getBestProvider(Criteria criteria, boolean enabledOnly) { 640 List<String> providers; 641 synchronized (mLock) { 642 providers = getProviders(criteria, enabledOnly); 643 if (providers.isEmpty()) { 644 providers = getProviders(null, enabledOnly); 645 } 646 } 647 648 if (!providers.isEmpty()) { 649 if (providers.contains(FUSED_PROVIDER)) { 650 return FUSED_PROVIDER; 651 } else if (providers.contains(GPS_PROVIDER)) { 652 return GPS_PROVIDER; 653 } else if (providers.contains(NETWORK_PROVIDER)) { 654 return NETWORK_PROVIDER; 655 } else { 656 return providers.get(0); 657 } 658 } 659 660 return null; 661 } 662 663 @Override getBackgroundThrottlingWhitelist()664 public String[] getBackgroundThrottlingWhitelist() { 665 return mInjector.getSettingsHelper().getBackgroundThrottlePackageWhitelist().toArray( 666 new String[0]); 667 } 668 669 @Override getIgnoreSettingsAllowlist()670 public PackageTagsList getIgnoreSettingsAllowlist() { 671 return mInjector.getSettingsHelper().getIgnoreSettingsAllowlist(); 672 } 673 674 @Nullable 675 @Override getCurrentLocation(String provider, LocationRequest request, ILocationCallback consumer, String packageName, @Nullable String attributionTag, String listenerId)676 public ICancellationSignal getCurrentLocation(String provider, LocationRequest request, 677 ILocationCallback consumer, String packageName, @Nullable String attributionTag, 678 String listenerId) { 679 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 680 listenerId); 681 int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), 682 identity.getPid()); 683 LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel, 684 PERMISSION_COARSE); 685 686 // clients in the system process must have an attribution tag set 687 Preconditions.checkState(identity.getPid() != Process.myPid() || attributionTag != null); 688 689 request = validateLocationRequest(provider, request, identity); 690 691 LocationProviderManager manager = getLocationProviderManager(provider); 692 Preconditions.checkArgument(manager != null, 693 "provider \"" + provider + "\" does not exist"); 694 695 return manager.getCurrentLocation(request, identity, permissionLevel, consumer); 696 } 697 698 @Override registerLocationListener(String provider, LocationRequest request, ILocationListener listener, String packageName, @Nullable String attributionTag, String listenerId)699 public void registerLocationListener(String provider, LocationRequest request, 700 ILocationListener listener, String packageName, @Nullable String attributionTag, 701 String listenerId) { 702 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 703 listenerId); 704 int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), 705 identity.getPid()); 706 LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel, 707 PERMISSION_COARSE); 708 709 // clients in the system process should have an attribution tag set 710 if (identity.getPid() == Process.myPid() && attributionTag == null) { 711 Log.w(TAG, "system location request with no attribution tag", 712 new IllegalArgumentException()); 713 } 714 715 request = validateLocationRequest(provider, request, identity); 716 717 LocationProviderManager manager = getLocationProviderManager(provider); 718 Preconditions.checkArgument(manager != null, 719 "provider \"" + provider + "\" does not exist"); 720 721 manager.registerLocationRequest(request, identity, permissionLevel, listener); 722 } 723 724 @Override registerLocationPendingIntent(String provider, LocationRequest request, PendingIntent pendingIntent, String packageName, @Nullable String attributionTag)725 public void registerLocationPendingIntent(String provider, LocationRequest request, 726 PendingIntent pendingIntent, String packageName, @Nullable String attributionTag) { 727 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag, 728 AppOpsManager.toReceiverId(pendingIntent)); 729 int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), 730 identity.getPid()); 731 LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel, 732 PERMISSION_COARSE); 733 734 // clients in the system process must have an attribution tag set 735 Preconditions.checkArgument(identity.getPid() != Process.myPid() || attributionTag != null); 736 737 // pending intents requests may not use system apis because we do not keep track if clients 738 // lose the relevant permissions, and thus should not get the benefit of those apis. its 739 // simplest to ensure these apis are simply never set for pending intent requests. the same 740 // does not apply for listener requests since those will have the process (including the 741 // listener) killed on permission removal 742 if (isChangeEnabled(BLOCK_PENDING_INTENT_SYSTEM_API_USAGE, identity.getUid())) { 743 boolean usesSystemApi = request.isLowPower() 744 || request.isHiddenFromAppOps() 745 || request.isLocationSettingsIgnored() 746 || !request.getWorkSource().isEmpty(); 747 if (usesSystemApi) { 748 throw new SecurityException( 749 "PendingIntent location requests may not use system APIs: " + request); 750 } 751 } 752 753 request = validateLocationRequest(provider, request, identity); 754 755 LocationProviderManager manager = getLocationProviderManager(provider); 756 Preconditions.checkArgument(manager != null, 757 "provider \"" + provider + "\" does not exist"); 758 759 manager.registerLocationRequest(request, identity, permissionLevel, pendingIntent); 760 } 761 validateLocationRequest(String provider, LocationRequest request, CallerIdentity identity)762 private LocationRequest validateLocationRequest(String provider, LocationRequest request, 763 CallerIdentity identity) { 764 // validate unsanitized request 765 if (!request.getWorkSource().isEmpty()) { 766 mContext.enforceCallingOrSelfPermission( 767 permission.UPDATE_DEVICE_STATS, 768 "setting a work source requires " + permission.UPDATE_DEVICE_STATS); 769 } 770 771 // sanitize request 772 LocationRequest.Builder sanitized = new LocationRequest.Builder(request); 773 774 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) 775 && GPS_PROVIDER.equals(provider) 776 && ArrayUtils.contains(mContext.getResources().getStringArray( 777 com.android.internal.R.array.config_locationDriverAssistancePackageNames), 778 identity.getPackageName())) { 779 sanitized.setAdasGnssBypass(true); 780 } 781 782 if (!CompatChanges.isChangeEnabled(LOW_POWER_EXCEPTIONS, Binder.getCallingUid())) { 783 if (mContext.checkCallingPermission(permission.LOCATION_HARDWARE) 784 != PERMISSION_GRANTED) { 785 sanitized.setLowPower(false); 786 } 787 } 788 789 WorkSource workSource = new WorkSource(request.getWorkSource()); 790 if (workSource.size() > 0 && workSource.getPackageName(0) == null) { 791 Log.w(TAG, "received (and ignoring) illegal worksource with no package name"); 792 workSource.clear(); 793 } else { 794 List<WorkChain> workChains = workSource.getWorkChains(); 795 if (workChains != null && !workChains.isEmpty() 796 && workChains.get(0).getAttributionTag() == null) { 797 Log.w(TAG, 798 "received (and ignoring) illegal worksource with no attribution tag"); 799 workSource.clear(); 800 } 801 } 802 803 if (workSource.isEmpty()) { 804 identity.addToWorkSource(workSource); 805 } 806 sanitized.setWorkSource(workSource); 807 808 request = sanitized.build(); 809 810 // validate sanitized request 811 boolean isLocationProvider = mLocalService.isProvider(null, identity); 812 813 if (request.isLowPower() && CompatChanges.isChangeEnabled(LOW_POWER_EXCEPTIONS, 814 identity.getUid())) { 815 mContext.enforceCallingOrSelfPermission( 816 permission.LOCATION_HARDWARE, 817 "low power request requires " + permission.LOCATION_HARDWARE); 818 } 819 if (request.isHiddenFromAppOps()) { 820 mContext.enforceCallingOrSelfPermission( 821 permission.UPDATE_APP_OPS_STATS, 822 "hiding from app ops requires " + permission.UPDATE_APP_OPS_STATS); 823 } 824 if (request.isAdasGnssBypass()) { 825 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 826 throw new IllegalArgumentException( 827 "adas gnss bypass requests are only allowed on automotive devices"); 828 } 829 if (!GPS_PROVIDER.equals(provider)) { 830 throw new IllegalArgumentException( 831 "adas gnss bypass requests are only allowed on the \"gps\" provider"); 832 } 833 if (!ArrayUtils.contains(mContext.getResources().getStringArray( 834 com.android.internal.R.array.config_locationDriverAssistancePackageNames), 835 identity.getPackageName())) { 836 throw new SecurityException( 837 "only verified adas packages may use adas gnss bypass requests"); 838 } 839 if (!isLocationProvider) { 840 mContext.enforceCallingOrSelfPermission( 841 permission.WRITE_SECURE_SETTINGS, 842 "adas gnss bypass requires " + permission.WRITE_SECURE_SETTINGS); 843 } 844 } 845 if (request.isLocationSettingsIgnored()) { 846 if (!isLocationProvider) { 847 mContext.enforceCallingOrSelfPermission( 848 permission.WRITE_SECURE_SETTINGS, 849 "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS); 850 } 851 } 852 853 return request; 854 } 855 856 @Override requestListenerFlush(String provider, ILocationListener listener, int requestCode)857 public void requestListenerFlush(String provider, ILocationListener listener, int requestCode) { 858 LocationProviderManager manager = getLocationProviderManager(provider); 859 Preconditions.checkArgument(manager != null, 860 "provider \"" + provider + "\" does not exist"); 861 862 manager.flush(Objects.requireNonNull(listener), requestCode); 863 } 864 865 @Override requestPendingIntentFlush(String provider, PendingIntent pendingIntent, int requestCode)866 public void requestPendingIntentFlush(String provider, PendingIntent pendingIntent, 867 int requestCode) { 868 LocationProviderManager manager = getLocationProviderManager(provider); 869 Preconditions.checkArgument(manager != null, 870 "provider \"" + provider + "\" does not exist"); 871 872 manager.flush(Objects.requireNonNull(pendingIntent), requestCode); 873 } 874 875 @Override unregisterLocationListener(ILocationListener listener)876 public void unregisterLocationListener(ILocationListener listener) { 877 for (LocationProviderManager manager : mProviderManagers) { 878 manager.unregisterLocationRequest(listener); 879 } 880 } 881 882 @Override unregisterLocationPendingIntent(PendingIntent pendingIntent)883 public void unregisterLocationPendingIntent(PendingIntent pendingIntent) { 884 for (LocationProviderManager manager : mProviderManagers) { 885 manager.unregisterLocationRequest(pendingIntent); 886 } 887 } 888 889 @Override getLastLocation(String provider, LastLocationRequest request, String packageName, @Nullable String attributionTag)890 public Location getLastLocation(String provider, LastLocationRequest request, 891 String packageName, @Nullable String attributionTag) { 892 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag); 893 int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(), 894 identity.getPid()); 895 LocationPermissions.enforceLocationPermission(identity.getUid(), permissionLevel, 896 PERMISSION_COARSE); 897 898 // clients in the system process must have an attribution tag set 899 Preconditions.checkArgument(identity.getPid() != Process.myPid() || attributionTag != null); 900 901 request = validateLastLocationRequest(provider, request, identity); 902 903 LocationProviderManager manager = getLocationProviderManager(provider); 904 if (manager == null) { 905 return null; 906 } 907 908 return manager.getLastLocation(request, identity, permissionLevel); 909 } 910 validateLastLocationRequest(String provider, LastLocationRequest request, CallerIdentity identity)911 private LastLocationRequest validateLastLocationRequest(String provider, 912 LastLocationRequest request, 913 CallerIdentity identity) { 914 // sanitize request 915 LastLocationRequest.Builder sanitized = new LastLocationRequest.Builder(request); 916 917 if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) 918 && GPS_PROVIDER.equals(provider) 919 && ArrayUtils.contains(mContext.getResources().getStringArray( 920 com.android.internal.R.array.config_locationDriverAssistancePackageNames), 921 identity.getPackageName())) { 922 sanitized.setAdasGnssBypass(true); 923 } 924 925 request = sanitized.build(); 926 927 // validate request 928 boolean isLocationProvider = mLocalService.isProvider(null, identity); 929 930 if (request.isHiddenFromAppOps()) { 931 mContext.enforceCallingOrSelfPermission( 932 permission.UPDATE_APP_OPS_STATS, 933 "hiding from app ops requires " + permission.UPDATE_APP_OPS_STATS); 934 } 935 936 if (request.isAdasGnssBypass()) { 937 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) { 938 throw new IllegalArgumentException( 939 "adas gnss bypass requests are only allowed on automotive devices"); 940 } 941 if (!GPS_PROVIDER.equals(provider)) { 942 throw new IllegalArgumentException( 943 "adas gnss bypass requests are only allowed on the \"gps\" provider"); 944 } 945 if (!ArrayUtils.contains(mContext.getResources().getStringArray( 946 com.android.internal.R.array.config_locationDriverAssistancePackageNames), 947 identity.getPackageName())) { 948 throw new SecurityException( 949 "only verified adas packages may use adas gnss bypass requests"); 950 } 951 if (!isLocationProvider) { 952 mContext.enforceCallingOrSelfPermission( 953 permission.WRITE_SECURE_SETTINGS, 954 "adas gnss bypass requires " + permission.WRITE_SECURE_SETTINGS); 955 } 956 } 957 if (request.isLocationSettingsIgnored()) { 958 if (!isLocationProvider) { 959 mContext.enforceCallingOrSelfPermission( 960 permission.WRITE_SECURE_SETTINGS, 961 "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS); 962 } 963 } 964 965 return request; 966 } 967 968 @Override getGnssTimeMillis()969 public LocationTime getGnssTimeMillis() { 970 return mLocalService.getGnssTimeMillis(); 971 } 972 973 @Override injectLocation(Location location)974 public void injectLocation(Location location) { 975 mContext.enforceCallingPermission(permission.LOCATION_HARDWARE, null); 976 mContext.enforceCallingPermission(ACCESS_FINE_LOCATION, null); 977 978 Preconditions.checkArgument(location.isComplete()); 979 980 int userId = UserHandle.getCallingUserId(); 981 LocationProviderManager manager = getLocationProviderManager(location.getProvider()); 982 if (manager != null && manager.isEnabled(userId)) { 983 manager.injectLastLocation(Objects.requireNonNull(location), userId); 984 } 985 } 986 987 @Override requestGeofence(Geofence geofence, PendingIntent intent, String packageName, String attributionTag)988 public void requestGeofence(Geofence geofence, PendingIntent intent, String packageName, 989 String attributionTag) { 990 mGeofenceManager.addGeofence(geofence, intent, packageName, attributionTag); 991 } 992 993 @Override removeGeofence(PendingIntent pendingIntent)994 public void removeGeofence(PendingIntent pendingIntent) { 995 mGeofenceManager.removeGeofence(pendingIntent); 996 } 997 998 @Override registerGnssStatusCallback(IGnssStatusListener listener, String packageName, @Nullable String attributionTag, String listenerId)999 public void registerGnssStatusCallback(IGnssStatusListener listener, String packageName, 1000 @Nullable String attributionTag, String listenerId) { 1001 if (mGnssManagerService != null) { 1002 mGnssManagerService.registerGnssStatusCallback(listener, packageName, attributionTag, 1003 listenerId); 1004 } 1005 } 1006 1007 @Override unregisterGnssStatusCallback(IGnssStatusListener listener)1008 public void unregisterGnssStatusCallback(IGnssStatusListener listener) { 1009 if (mGnssManagerService != null) { 1010 mGnssManagerService.unregisterGnssStatusCallback(listener); 1011 } 1012 } 1013 1014 @Override registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName, @Nullable String attributionTag, String listenerId)1015 public void registerGnssNmeaCallback(IGnssNmeaListener listener, String packageName, 1016 @Nullable String attributionTag, String listenerId) { 1017 if (mGnssManagerService != null) { 1018 mGnssManagerService.registerGnssNmeaCallback(listener, packageName, attributionTag, 1019 listenerId); 1020 } 1021 } 1022 1023 @Override unregisterGnssNmeaCallback(IGnssNmeaListener listener)1024 public void unregisterGnssNmeaCallback(IGnssNmeaListener listener) { 1025 if (mGnssManagerService != null) { 1026 mGnssManagerService.unregisterGnssNmeaCallback(listener); 1027 } 1028 } 1029 1030 @Override addGnssMeasurementsListener(GnssMeasurementRequest request, IGnssMeasurementsListener listener, String packageName, @Nullable String attributionTag, String listenerId)1031 public void addGnssMeasurementsListener(GnssMeasurementRequest request, 1032 IGnssMeasurementsListener listener, String packageName, @Nullable String attributionTag, 1033 String listenerId) { 1034 if (mGnssManagerService != null) { 1035 mGnssManagerService.addGnssMeasurementsListener(request, listener, packageName, 1036 attributionTag, listenerId); 1037 } 1038 } 1039 1040 @Override removeGnssMeasurementsListener(IGnssMeasurementsListener listener)1041 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { 1042 if (mGnssManagerService != null) { 1043 mGnssManagerService.removeGnssMeasurementsListener( 1044 listener); 1045 } 1046 } 1047 1048 @Override addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, @Nullable String attributionTag, String listenerId)1049 public void addGnssAntennaInfoListener(IGnssAntennaInfoListener listener, String packageName, 1050 @Nullable String attributionTag, String listenerId) { 1051 if (mGnssManagerService != null) { 1052 mGnssManagerService.addGnssAntennaInfoListener(listener, packageName, attributionTag, 1053 listenerId); 1054 } 1055 } 1056 1057 @Override removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener)1058 public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) { 1059 if (mGnssManagerService != null) { 1060 mGnssManagerService.removeGnssAntennaInfoListener(listener); 1061 } 1062 } 1063 1064 @Override addProviderRequestListener(IProviderRequestListener listener)1065 public void addProviderRequestListener(IProviderRequestListener listener) { 1066 for (LocationProviderManager manager : mProviderManagers) { 1067 manager.addProviderRequestListener(listener); 1068 } 1069 } 1070 1071 @Override removeProviderRequestListener(IProviderRequestListener listener)1072 public void removeProviderRequestListener(IProviderRequestListener listener) { 1073 for (LocationProviderManager manager : mProviderManagers) { 1074 manager.removeProviderRequestListener(listener); 1075 } 1076 } 1077 1078 @Override injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections)1079 public void injectGnssMeasurementCorrections(GnssMeasurementCorrections corrections) { 1080 if (mGnssManagerService != null) { 1081 mGnssManagerService.injectGnssMeasurementCorrections(corrections); 1082 } 1083 } 1084 1085 @Override getGnssCapabilities()1086 public GnssCapabilities getGnssCapabilities() { 1087 return mGnssManagerService == null ? new GnssCapabilities.Builder().build() 1088 : mGnssManagerService.getGnssCapabilities(); 1089 } 1090 1091 @Override getGnssAntennaInfos()1092 public List<GnssAntennaInfo> getGnssAntennaInfos() { 1093 return mGnssManagerService == null ? null : mGnssManagerService.getGnssAntennaInfos(); 1094 } 1095 1096 @Override addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, String packageName, @Nullable String attributionTag, String listenerId)1097 public void addGnssNavigationMessageListener(IGnssNavigationMessageListener listener, 1098 String packageName, @Nullable String attributionTag, String listenerId) { 1099 if (mGnssManagerService != null) { 1100 mGnssManagerService.addGnssNavigationMessageListener(listener, packageName, 1101 attributionTag, listenerId); 1102 } 1103 } 1104 1105 @Override removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)1106 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { 1107 if (mGnssManagerService != null) { 1108 mGnssManagerService.removeGnssNavigationMessageListener( 1109 listener); 1110 } 1111 } 1112 1113 @Override sendExtraCommand(String provider, String command, Bundle extras)1114 public void sendExtraCommand(String provider, String command, Bundle extras) { 1115 LocationPermissions.enforceCallingOrSelfLocationPermission(mContext, PERMISSION_COARSE); 1116 mContext.enforceCallingOrSelfPermission( 1117 permission.ACCESS_LOCATION_EXTRA_COMMANDS, null); 1118 1119 LocationProviderManager manager = getLocationProviderManager( 1120 Objects.requireNonNull(provider)); 1121 if (manager != null) { 1122 manager.sendExtraCommand(Binder.getCallingUid(), Binder.getCallingPid(), 1123 Objects.requireNonNull(command), extras); 1124 } 1125 1126 mInjector.getLocationUsageLogger().logLocationApiUsage( 1127 LocationStatsEnums.USAGE_STARTED, 1128 LocationStatsEnums.API_SEND_EXTRA_COMMAND, 1129 provider); 1130 mInjector.getLocationUsageLogger().logLocationApiUsage( 1131 LocationStatsEnums.USAGE_ENDED, 1132 LocationStatsEnums.API_SEND_EXTRA_COMMAND, 1133 provider); 1134 } 1135 1136 @Override getProviderProperties(String provider)1137 public ProviderProperties getProviderProperties(String provider) { 1138 LocationProviderManager manager = getLocationProviderManager(provider); 1139 Preconditions.checkArgument(manager != null, 1140 "provider \"" + provider + "\" does not exist"); 1141 return manager.getProperties(); 1142 } 1143 1144 @Override isProviderPackage(@ullable String provider, String packageName, @Nullable String attributionTag)1145 public boolean isProviderPackage(@Nullable String provider, String packageName, 1146 @Nullable String attributionTag) { 1147 mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null); 1148 1149 for (LocationProviderManager manager : mProviderManagers) { 1150 if (provider != null && !provider.equals(manager.getName())) { 1151 continue; 1152 } 1153 CallerIdentity identity = manager.getIdentity(); 1154 if (identity == null) { 1155 continue; 1156 } 1157 if (identity.getPackageName().equals(packageName) && (attributionTag == null 1158 || Objects.equals(identity.getAttributionTag(), attributionTag))) { 1159 return true; 1160 } 1161 } 1162 1163 return false; 1164 } 1165 1166 @Override getProviderPackages(String provider)1167 public List<String> getProviderPackages(String provider) { 1168 mContext.enforceCallingOrSelfPermission(permission.READ_DEVICE_CONFIG, null); 1169 1170 LocationProviderManager manager = getLocationProviderManager(provider); 1171 if (manager == null) { 1172 return Collections.emptyList(); 1173 } 1174 1175 CallerIdentity identity = manager.getIdentity(); 1176 if (identity == null) { 1177 return Collections.emptyList(); 1178 } 1179 1180 return Collections.singletonList(identity.getPackageName()); 1181 } 1182 1183 @Override setExtraLocationControllerPackage(String packageName)1184 public void setExtraLocationControllerPackage(String packageName) { 1185 mContext.enforceCallingPermission(permission.LOCATION_HARDWARE, 1186 permission.LOCATION_HARDWARE + " permission required"); 1187 synchronized (mLock) { 1188 mExtraLocationControllerPackage = packageName; 1189 } 1190 } 1191 1192 @Override getExtraLocationControllerPackage()1193 public String getExtraLocationControllerPackage() { 1194 synchronized (mLock) { 1195 return mExtraLocationControllerPackage; 1196 } 1197 } 1198 1199 @Override setExtraLocationControllerPackageEnabled(boolean enabled)1200 public void setExtraLocationControllerPackageEnabled(boolean enabled) { 1201 mContext.enforceCallingPermission(permission.LOCATION_HARDWARE, 1202 permission.LOCATION_HARDWARE + " permission required"); 1203 synchronized (mLock) { 1204 mExtraLocationControllerPackageEnabled = enabled; 1205 } 1206 } 1207 1208 @Override isExtraLocationControllerPackageEnabled()1209 public boolean isExtraLocationControllerPackageEnabled() { 1210 synchronized (mLock) { 1211 return mExtraLocationControllerPackageEnabled 1212 && (mExtraLocationControllerPackage != null); 1213 } 1214 } 1215 1216 @Override setLocationEnabledForUser(boolean enabled, int userId)1217 public void setLocationEnabledForUser(boolean enabled, int userId) { 1218 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 1219 userId, false, false, "setLocationEnabledForUser", null); 1220 1221 mContext.enforceCallingOrSelfPermission(permission.WRITE_SECURE_SETTINGS, null); 1222 1223 LocationManager.invalidateLocalLocationEnabledCaches(); 1224 mInjector.getSettingsHelper().setLocationEnabled(enabled, userId); 1225 } 1226 1227 @Override isLocationEnabledForUser(int userId)1228 public boolean isLocationEnabledForUser(int userId) { 1229 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 1230 userId, false, false, "isLocationEnabledForUser", null); 1231 return mInjector.getSettingsHelper().isLocationEnabled(userId); 1232 } 1233 1234 @Override setAdasGnssLocationEnabledForUser(boolean enabled, int userId)1235 public void setAdasGnssLocationEnabledForUser(boolean enabled, int userId) { 1236 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 1237 userId, false, false, "setAdasGnssLocationEnabledForUser", null); 1238 1239 mContext.enforceCallingOrSelfPermission(permission.WRITE_SECURE_SETTINGS, null); 1240 1241 mInjector.getLocationSettings().updateUserSettings(userId, 1242 settings -> settings.withAdasGnssLocationEnabled(enabled)); 1243 } 1244 1245 @Override isAdasGnssLocationEnabledForUser(int userId)1246 public boolean isAdasGnssLocationEnabledForUser(int userId) { 1247 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), 1248 userId, false, false, "isAdasGnssLocationEnabledForUser", null); 1249 return mInjector.getLocationSettings().getUserSettings(userId).isAdasGnssLocationEnabled(); 1250 } 1251 1252 @Override isProviderEnabledForUser(String provider, int userId)1253 public boolean isProviderEnabledForUser(String provider, int userId) { 1254 return mLocalService.isProviderEnabledForUser(provider, userId); 1255 } 1256 1257 @Override geocoderIsPresent()1258 public boolean geocoderIsPresent() { 1259 return mGeocodeProvider != null; 1260 } 1261 1262 @Override getFromLocation(double latitude, double longitude, int maxResults, GeocoderParams params, IGeocodeListener listener)1263 public void getFromLocation(double latitude, double longitude, int maxResults, 1264 GeocoderParams params, IGeocodeListener listener) { 1265 // validate identity 1266 CallerIdentity identity = CallerIdentity.fromBinder(mContext, params.getClientPackage(), 1267 params.getClientAttributionTag()); 1268 Preconditions.checkArgument(identity.getUid() == params.getClientUid()); 1269 1270 if (mGeocodeProvider != null) { 1271 mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, params, listener); 1272 } else { 1273 try { 1274 listener.onResults(null, Collections.emptyList()); 1275 } catch (RemoteException e) { 1276 // ignore 1277 } 1278 } 1279 } 1280 1281 @Override getFromLocationName(String locationName, double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude, int maxResults, GeocoderParams params, IGeocodeListener listener)1282 public void getFromLocationName(String locationName, 1283 double lowerLeftLatitude, double lowerLeftLongitude, 1284 double upperRightLatitude, double upperRightLongitude, int maxResults, 1285 GeocoderParams params, IGeocodeListener listener) { 1286 // validate identity 1287 CallerIdentity identity = CallerIdentity.fromBinder(mContext, params.getClientPackage(), 1288 params.getClientAttributionTag()); 1289 Preconditions.checkArgument(identity.getUid() == params.getClientUid()); 1290 1291 if (mGeocodeProvider != null) { 1292 mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 1293 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 1294 maxResults, params, listener); 1295 } else { 1296 try { 1297 listener.onResults(null, Collections.emptyList()); 1298 } catch (RemoteException e) { 1299 // ignore 1300 } 1301 } 1302 } 1303 1304 @Override addTestProvider(String provider, ProviderProperties properties, List<String> extraAttributionTags, String packageName, String attributionTag)1305 public void addTestProvider(String provider, ProviderProperties properties, 1306 List<String> extraAttributionTags, String packageName, String attributionTag) { 1307 // unsafe is ok because app ops will verify the package name 1308 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag); 1309 if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) { 1310 return; 1311 } 1312 1313 final LocationProviderManager manager = getOrAddLocationProviderManager(provider); 1314 manager.setMockProvider(new MockLocationProvider(properties, identity, 1315 new ArraySet<>(extraAttributionTags))); 1316 } 1317 1318 @Override removeTestProvider(String provider, String packageName, String attributionTag)1319 public void removeTestProvider(String provider, String packageName, String attributionTag) { 1320 // unsafe is ok because app ops will verify the package name 1321 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, attributionTag); 1322 if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) { 1323 return; 1324 } 1325 1326 synchronized (mLock) { 1327 LocationProviderManager manager = getLocationProviderManager(provider); 1328 if (manager == null) { 1329 return; 1330 } 1331 1332 manager.setMockProvider(null); 1333 if (!manager.hasProvider()) { 1334 removeLocationProviderManager(manager); 1335 } 1336 } 1337 } 1338 1339 @Override setTestProviderLocation(String provider, Location location, String packageName, String attributionTag)1340 public void setTestProviderLocation(String provider, Location location, String packageName, 1341 String attributionTag) { 1342 // unsafe is ok because app ops will verify the package name 1343 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, 1344 attributionTag); 1345 if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) { 1346 return; 1347 } 1348 1349 Preconditions.checkArgument(location.isComplete(), 1350 "incomplete location object, missing timestamp or accuracy?"); 1351 1352 LocationProviderManager manager = getLocationProviderManager(provider); 1353 if (manager == null) { 1354 throw new IllegalArgumentException("provider doesn't exist: " + provider); 1355 } 1356 1357 manager.setMockProviderLocation(location); 1358 } 1359 1360 @Override setTestProviderEnabled(String provider, boolean enabled, String packageName, String attributionTag)1361 public void setTestProviderEnabled(String provider, boolean enabled, String packageName, 1362 String attributionTag) { 1363 // unsafe is ok because app ops will verify the package name 1364 CallerIdentity identity = CallerIdentity.fromBinderUnsafe(packageName, 1365 attributionTag); 1366 if (!mInjector.getAppOpsHelper().noteOp(AppOpsManager.OP_MOCK_LOCATION, identity)) { 1367 return; 1368 } 1369 1370 LocationProviderManager manager = getLocationProviderManager(provider); 1371 if (manager == null) { 1372 throw new IllegalArgumentException("provider doesn't exist: " + provider); 1373 } 1374 1375 manager.setMockProviderAllowed(enabled); 1376 } 1377 1378 @Override handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, ParcelFileDescriptor err, String[] args)1379 public int handleShellCommand(ParcelFileDescriptor in, ParcelFileDescriptor out, 1380 ParcelFileDescriptor err, String[] args) { 1381 return new LocationShellCommand(mContext, this).exec( 1382 this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(), 1383 args); 1384 } 1385 1386 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1387 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1388 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) { 1389 return; 1390 } 1391 1392 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 1393 1394 if (args.length > 0) { 1395 LocationProviderManager manager = getLocationProviderManager(args[0]); 1396 if (manager != null) { 1397 ipw.println("Provider:"); 1398 ipw.increaseIndent(); 1399 manager.dump(fd, ipw, args); 1400 ipw.decreaseIndent(); 1401 1402 ipw.println("Event Log:"); 1403 ipw.increaseIndent(); 1404 EVENT_LOG.iterate(manager.getName(), ipw::println); 1405 ipw.decreaseIndent(); 1406 return; 1407 } 1408 1409 if ("--gnssmetrics".equals(args[0])) { 1410 if (mGnssManagerService != null) { 1411 mGnssManagerService.dump(fd, ipw, args); 1412 } 1413 return; 1414 } 1415 } 1416 1417 ipw.println("Location Manager State:"); 1418 ipw.increaseIndent(); 1419 1420 ipw.println("User Info:"); 1421 ipw.increaseIndent(); 1422 mInjector.getUserInfoHelper().dump(fd, ipw, args); 1423 ipw.decreaseIndent(); 1424 1425 ipw.println("Location Settings:"); 1426 ipw.increaseIndent(); 1427 mInjector.getSettingsHelper().dump(fd, ipw, args); 1428 ipw.decreaseIndent(); 1429 1430 synchronized (mLock) { 1431 if (mExtraLocationControllerPackage != null) { 1432 ipw.println( 1433 "Location Controller Extra Package: " + mExtraLocationControllerPackage 1434 + (mExtraLocationControllerPackageEnabled ? " [enabled]" 1435 : " [disabled]")); 1436 } 1437 } 1438 1439 ipw.println("Location Providers:"); 1440 ipw.increaseIndent(); 1441 for (LocationProviderManager manager : mProviderManagers) { 1442 manager.dump(fd, ipw, args); 1443 } 1444 ipw.decreaseIndent(); 1445 1446 ipw.println("Historical Aggregate Location Provider Data:"); 1447 ipw.increaseIndent(); 1448 ArrayMap<String, ArrayMap<CallerIdentity, LocationEventLog.AggregateStats>> aggregateStats = 1449 EVENT_LOG.copyAggregateStats(); 1450 for (int i = 0; i < aggregateStats.size(); i++) { 1451 ipw.print(aggregateStats.keyAt(i)); 1452 ipw.println(":"); 1453 ipw.increaseIndent(); 1454 ArrayMap<CallerIdentity, LocationEventLog.AggregateStats> providerStats = 1455 aggregateStats.valueAt(i); 1456 for (int j = 0; j < providerStats.size(); j++) { 1457 ipw.print(providerStats.keyAt(j)); 1458 ipw.print(": "); 1459 providerStats.valueAt(j).updateTotals(); 1460 ipw.println(providerStats.valueAt(j)); 1461 } 1462 ipw.decreaseIndent(); 1463 } 1464 ipw.decreaseIndent(); 1465 1466 if (mGnssManagerService != null) { 1467 ipw.println("GNSS Manager:"); 1468 ipw.increaseIndent(); 1469 mGnssManagerService.dump(fd, ipw, args); 1470 ipw.decreaseIndent(); 1471 } 1472 1473 ipw.println("Geofence Manager:"); 1474 ipw.increaseIndent(); 1475 mGeofenceManager.dump(fd, ipw, args); 1476 ipw.decreaseIndent(); 1477 1478 ipw.println("Event Log:"); 1479 ipw.increaseIndent(); 1480 EVENT_LOG.iterate(ipw::println); 1481 ipw.decreaseIndent(); 1482 } 1483 1484 @Override onStateChanged(String provider, AbstractLocationProvider.State oldState, AbstractLocationProvider.State newState)1485 public void onStateChanged(String provider, AbstractLocationProvider.State oldState, 1486 AbstractLocationProvider.State newState) { 1487 if (!Objects.equals(oldState.identity, newState.identity)) { 1488 refreshAppOpsRestrictions(UserHandle.USER_ALL); 1489 } 1490 1491 if (!oldState.extraAttributionTags.equals(newState.extraAttributionTags) 1492 || !Objects.equals(oldState.identity, newState.identity)) { 1493 // since we're potentially affecting the tag lists for two different uids, acquire the 1494 // lock to ensure providers cannot change while we're looping over the providers 1495 // multiple times, which could lead to inconsistent results. 1496 synchronized (mLock) { 1497 LocationPackageTagsListener listener = mLocationTagsChangedListener; 1498 if (listener != null) { 1499 int oldUid = oldState.identity != null ? oldState.identity.getUid() : -1; 1500 int newUid = newState.identity != null ? newState.identity.getUid() : -1; 1501 if (oldUid != -1) { 1502 PackageTagsList tags = calculateAppOpsLocationSourceTags(oldUid); 1503 FgThread.getHandler().post( 1504 () -> listener.onLocationPackageTagsChanged(oldUid, tags)); 1505 } 1506 // if the new app id is the same as the old app id, no need to invoke the 1507 // listener twice, it's already been taken care of 1508 if (newUid != -1 && newUid != oldUid) { 1509 PackageTagsList tags = calculateAppOpsLocationSourceTags(newUid); 1510 FgThread.getHandler().post( 1511 () -> listener.onLocationPackageTagsChanged(newUid, tags)); 1512 } 1513 } 1514 } 1515 } 1516 } 1517 refreshAppOpsRestrictions(int userId)1518 private void refreshAppOpsRestrictions(int userId) { 1519 if (userId == UserHandle.USER_ALL) { 1520 final int[] runningUserIds = mInjector.getUserInfoHelper().getRunningUserIds(); 1521 for (int i = 0; i < runningUserIds.length; i++) { 1522 refreshAppOpsRestrictions(runningUserIds[i]); 1523 } 1524 return; 1525 } 1526 1527 Preconditions.checkArgument(userId >= 0); 1528 1529 boolean enabled = mInjector.getSettingsHelper().isLocationEnabled(userId); 1530 1531 PackageTagsList allowedPackages = null; 1532 if (!enabled) { 1533 PackageTagsList.Builder builder = new PackageTagsList.Builder(); 1534 for (LocationProviderManager manager : mProviderManagers) { 1535 CallerIdentity identity = manager.getIdentity(); 1536 if (identity != null) { 1537 builder.add(identity.getPackageName(), identity.getAttributionTag()); 1538 } 1539 } 1540 builder.add(mInjector.getSettingsHelper().getIgnoreSettingsAllowlist()); 1541 allowedPackages = builder.build(); 1542 } 1543 1544 AppOpsManager appOpsManager = Objects.requireNonNull( 1545 mContext.getSystemService(AppOpsManager.class)); 1546 appOpsManager.setUserRestrictionForUser( 1547 AppOpsManager.OP_COARSE_LOCATION, 1548 !enabled, 1549 LocationManagerService.this, 1550 allowedPackages, 1551 userId); 1552 appOpsManager.setUserRestrictionForUser( 1553 AppOpsManager.OP_FINE_LOCATION, 1554 !enabled, 1555 LocationManagerService.this, 1556 allowedPackages, 1557 userId); 1558 } 1559 calculateAppOpsLocationSourceTags(int uid)1560 PackageTagsList calculateAppOpsLocationSourceTags(int uid) { 1561 PackageTagsList.Builder builder = new PackageTagsList.Builder(); 1562 for (LocationProviderManager manager : mProviderManagers) { 1563 AbstractLocationProvider.State managerState = manager.getState(); 1564 if (managerState.identity == null) { 1565 continue; 1566 } 1567 if (managerState.identity.getUid() != uid) { 1568 continue; 1569 } 1570 1571 builder.add(managerState.identity.getPackageName(), managerState.extraAttributionTags); 1572 if (managerState.extraAttributionTags.isEmpty() 1573 || managerState.identity.getAttributionTag() != null) { 1574 builder.add(managerState.identity.getPackageName(), 1575 managerState.identity.getAttributionTag()); 1576 } else { 1577 Log.e(TAG, manager.getName() + " provider has specified a null attribution tag and " 1578 + "a non-empty set of extra attribution tags - dropping the null " 1579 + "attribution tag"); 1580 } 1581 } 1582 return builder.build(); 1583 } 1584 1585 private class LocalService extends LocationManagerInternal { 1586 LocalService()1587 LocalService() {} 1588 1589 @Override isProviderEnabledForUser(@onNull String provider, int userId)1590 public boolean isProviderEnabledForUser(@NonNull String provider, int userId) { 1591 userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), 1592 Binder.getCallingUid(), userId, false, false, "isProviderEnabledForUser", null); 1593 1594 LocationProviderManager manager = getLocationProviderManager(provider); 1595 if (manager == null) { 1596 return false; 1597 } 1598 1599 return manager.isEnabled(userId); 1600 } 1601 1602 @Override addProviderEnabledListener(String provider, ProviderEnabledListener listener)1603 public void addProviderEnabledListener(String provider, ProviderEnabledListener listener) { 1604 LocationProviderManager manager = Objects.requireNonNull( 1605 getLocationProviderManager(provider)); 1606 manager.addEnabledListener(listener); 1607 } 1608 1609 @Override removeProviderEnabledListener(String provider, ProviderEnabledListener listener)1610 public void removeProviderEnabledListener(String provider, 1611 ProviderEnabledListener listener) { 1612 LocationProviderManager manager = Objects.requireNonNull( 1613 getLocationProviderManager(provider)); 1614 manager.removeEnabledListener(listener); 1615 } 1616 1617 @Override isProvider(@ullable String provider, CallerIdentity identity)1618 public boolean isProvider(@Nullable String provider, CallerIdentity identity) { 1619 for (LocationProviderManager manager : mProviderManagers) { 1620 if (provider != null && !provider.equals(manager.getName())) { 1621 continue; 1622 } 1623 if (identity.equals(manager.getIdentity())) { 1624 return true; 1625 } 1626 } 1627 1628 return false; 1629 } 1630 1631 @Override sendNiResponse(int notifId, int userResponse)1632 public void sendNiResponse(int notifId, int userResponse) { 1633 if (mGnssManagerService != null) { 1634 mGnssManagerService.sendNiResponse(notifId, userResponse); 1635 } 1636 } 1637 1638 @Override getGnssTimeMillis()1639 public @Nullable LocationTime getGnssTimeMillis() { 1640 LocationProviderManager gpsManager = getLocationProviderManager(GPS_PROVIDER); 1641 if (gpsManager == null) { 1642 return null; 1643 } 1644 1645 Location location = gpsManager.getLastLocationUnsafe(UserHandle.USER_ALL, 1646 PERMISSION_FINE, false, Long.MAX_VALUE); 1647 if (location == null) { 1648 return null; 1649 } 1650 1651 return new LocationTime(location.getTime(), location.getElapsedRealtimeNanos()); 1652 } 1653 1654 @Override setLocationPackageTagsListener( @ullable LocationPackageTagsListener listener)1655 public void setLocationPackageTagsListener( 1656 @Nullable LocationPackageTagsListener listener) { 1657 synchronized (mLock) { 1658 mLocationTagsChangedListener = listener; 1659 1660 // calculate initial tag list and send to listener 1661 if (listener != null) { 1662 ArraySet<Integer> uids = new ArraySet<>(mProviderManagers.size()); 1663 for (LocationProviderManager manager : mProviderManagers) { 1664 CallerIdentity identity = manager.getIdentity(); 1665 if (identity != null) { 1666 uids.add(identity.getUid()); 1667 } 1668 } 1669 1670 for (int uid : uids) { 1671 PackageTagsList tags = calculateAppOpsLocationSourceTags(uid); 1672 if (!tags.isEmpty()) { 1673 FgThread.getHandler().post( 1674 () -> listener.onLocationPackageTagsChanged(uid, tags)); 1675 } 1676 } 1677 } 1678 } 1679 } 1680 } 1681 1682 private static final class SystemInjector implements Injector { 1683 1684 private final Context mContext; 1685 1686 private final UserInfoHelper mUserInfoHelper; 1687 private final LocationSettings mLocationSettings; 1688 private final AlarmHelper mAlarmHelper; 1689 private final SystemAppOpsHelper mAppOpsHelper; 1690 private final SystemLocationPermissionsHelper mLocationPermissionsHelper; 1691 private final SystemSettingsHelper mSettingsHelper; 1692 private final SystemAppForegroundHelper mAppForegroundHelper; 1693 private final SystemLocationPowerSaveModeHelper mLocationPowerSaveModeHelper; 1694 private final SystemScreenInteractiveHelper mScreenInteractiveHelper; 1695 private final SystemDeviceStationaryHelper mDeviceStationaryHelper; 1696 private final SystemDeviceIdleHelper mDeviceIdleHelper; 1697 private final LocationAttributionHelper mLocationAttributionHelper; 1698 private final LocationUsageLogger mLocationUsageLogger; 1699 1700 // lazily instantiated since they may not always be used 1701 1702 @GuardedBy("this") 1703 private @Nullable SystemEmergencyHelper mEmergencyCallHelper; 1704 1705 @GuardedBy("this") 1706 private boolean mSystemReady; 1707 SystemInjector(Context context, UserInfoHelper userInfoHelper)1708 SystemInjector(Context context, UserInfoHelper userInfoHelper) { 1709 mContext = context; 1710 1711 mUserInfoHelper = userInfoHelper; 1712 mLocationSettings = new LocationSettings(context); 1713 mAlarmHelper = new SystemAlarmHelper(context); 1714 mAppOpsHelper = new SystemAppOpsHelper(context); 1715 mLocationPermissionsHelper = new SystemLocationPermissionsHelper(context, 1716 mAppOpsHelper); 1717 mSettingsHelper = new SystemSettingsHelper(context); 1718 mAppForegroundHelper = new SystemAppForegroundHelper(context); 1719 mLocationPowerSaveModeHelper = new SystemLocationPowerSaveModeHelper(context); 1720 mScreenInteractiveHelper = new SystemScreenInteractiveHelper(context); 1721 mDeviceStationaryHelper = new SystemDeviceStationaryHelper(); 1722 mDeviceIdleHelper = new SystemDeviceIdleHelper(context); 1723 mLocationAttributionHelper = new LocationAttributionHelper(mAppOpsHelper); 1724 mLocationUsageLogger = new LocationUsageLogger(); 1725 } 1726 onSystemReady()1727 synchronized void onSystemReady() { 1728 mAppOpsHelper.onSystemReady(); 1729 mLocationPermissionsHelper.onSystemReady(); 1730 mSettingsHelper.onSystemReady(); 1731 mAppForegroundHelper.onSystemReady(); 1732 mLocationPowerSaveModeHelper.onSystemReady(); 1733 mScreenInteractiveHelper.onSystemReady(); 1734 mDeviceStationaryHelper.onSystemReady(); 1735 mDeviceIdleHelper.onSystemReady(); 1736 1737 if (mEmergencyCallHelper != null) { 1738 mEmergencyCallHelper.onSystemReady(); 1739 } 1740 1741 mSystemReady = true; 1742 } 1743 1744 @Override getUserInfoHelper()1745 public UserInfoHelper getUserInfoHelper() { 1746 return mUserInfoHelper; 1747 } 1748 1749 @Override getLocationSettings()1750 public LocationSettings getLocationSettings() { 1751 return mLocationSettings; 1752 } 1753 1754 @Override getAlarmHelper()1755 public AlarmHelper getAlarmHelper() { 1756 return mAlarmHelper; 1757 } 1758 1759 @Override getAppOpsHelper()1760 public AppOpsHelper getAppOpsHelper() { 1761 return mAppOpsHelper; 1762 } 1763 1764 @Override getLocationPermissionsHelper()1765 public LocationPermissionsHelper getLocationPermissionsHelper() { 1766 return mLocationPermissionsHelper; 1767 } 1768 1769 @Override getSettingsHelper()1770 public SettingsHelper getSettingsHelper() { 1771 return mSettingsHelper; 1772 } 1773 1774 @Override getAppForegroundHelper()1775 public AppForegroundHelper getAppForegroundHelper() { 1776 return mAppForegroundHelper; 1777 } 1778 1779 @Override getLocationPowerSaveModeHelper()1780 public LocationPowerSaveModeHelper getLocationPowerSaveModeHelper() { 1781 return mLocationPowerSaveModeHelper; 1782 } 1783 1784 @Override getScreenInteractiveHelper()1785 public ScreenInteractiveHelper getScreenInteractiveHelper() { 1786 return mScreenInteractiveHelper; 1787 } 1788 1789 @Override getDeviceStationaryHelper()1790 public DeviceStationaryHelper getDeviceStationaryHelper() { 1791 return mDeviceStationaryHelper; 1792 } 1793 1794 @Override getDeviceIdleHelper()1795 public DeviceIdleHelper getDeviceIdleHelper() { 1796 return mDeviceIdleHelper; 1797 } 1798 1799 @Override getLocationAttributionHelper()1800 public LocationAttributionHelper getLocationAttributionHelper() { 1801 return mLocationAttributionHelper; 1802 } 1803 1804 @Override getEmergencyHelper()1805 public synchronized EmergencyHelper getEmergencyHelper() { 1806 if (mEmergencyCallHelper == null) { 1807 mEmergencyCallHelper = new SystemEmergencyHelper(mContext); 1808 if (mSystemReady) { 1809 mEmergencyCallHelper.onSystemReady(); 1810 } 1811 } 1812 1813 return mEmergencyCallHelper; 1814 } 1815 1816 @Override getLocationUsageLogger()1817 public LocationUsageLogger getLocationUsageLogger() { 1818 return mLocationUsageLogger; 1819 } 1820 } 1821 } 1822