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