LocationManagerService.java revision 48f1a647655f3479bc655d2c3c4873c6aa9b712c
1/* 2 * Copyright (C) 2007 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 17package com.android.server; 18 19import android.app.ActivityManager; 20import android.annotation.NonNull; 21import android.util.ArrayMap; 22import android.util.ArraySet; 23 24import com.android.internal.content.PackageMonitor; 25import com.android.internal.location.ProviderProperties; 26import com.android.internal.location.ProviderRequest; 27import com.android.internal.os.BackgroundThread; 28import com.android.internal.util.ArrayUtils; 29import com.android.internal.util.DumpUtils; 30import com.android.server.location.ActivityRecognitionProxy; 31import com.android.server.location.FlpHardwareProvider; 32import com.android.server.location.FusedProxy; 33import com.android.server.location.GeocoderProxy; 34import com.android.server.location.GeofenceManager; 35import com.android.server.location.GeofenceProxy; 36import com.android.server.location.GnssLocationProvider; 37import com.android.server.location.GnssMeasurementsProvider; 38import com.android.server.location.GnssNavigationMessageProvider; 39import com.android.server.location.LocationBlacklist; 40import com.android.server.location.LocationFudger; 41import com.android.server.location.LocationProviderInterface; 42import com.android.server.location.LocationProviderProxy; 43import com.android.server.location.LocationRequestStatistics; 44import com.android.server.location.LocationRequestStatistics.PackageProviderKey; 45import com.android.server.location.LocationRequestStatistics.PackageStatistics; 46import com.android.server.location.MockProvider; 47import com.android.server.location.PassiveProvider; 48 49import android.app.AppOpsManager; 50import android.app.PendingIntent; 51import android.content.BroadcastReceiver; 52import android.content.ContentResolver; 53import android.content.Context; 54import android.content.Intent; 55import android.content.IntentFilter; 56import android.content.pm.ApplicationInfo; 57import android.content.pm.PackageInfo; 58import android.content.pm.PackageManager; 59import android.content.pm.PackageManagerInternal; 60import android.content.pm.PackageManager.NameNotFoundException; 61import android.content.pm.ResolveInfo; 62import android.content.pm.Signature; 63import android.content.res.Resources; 64import android.database.ContentObserver; 65import android.hardware.location.ActivityRecognitionHardware; 66import android.location.Address; 67import android.location.Criteria; 68import android.location.GeocoderParams; 69import android.location.Geofence; 70import android.location.IBatchedLocationCallback; 71import android.location.IGnssMeasurementsListener; 72import android.location.IGnssStatusListener; 73import android.location.IGnssStatusProvider; 74import android.location.IGpsGeofenceHardware; 75import android.location.IGnssNavigationMessageListener; 76import android.location.ILocationListener; 77import android.location.ILocationManager; 78import android.location.INetInitiatedListener; 79import android.location.Location; 80import android.location.LocationManager; 81import android.location.LocationProvider; 82import android.location.LocationRequest; 83import android.os.Binder; 84import android.os.Bundle; 85import android.os.Handler; 86import android.os.IBinder; 87import android.os.Looper; 88import android.os.Message; 89import android.os.PowerManager; 90import android.os.Process; 91import android.os.RemoteException; 92import android.os.SystemClock; 93import android.os.UserHandle; 94import android.os.UserManager; 95import android.os.WorkSource; 96import android.provider.Settings; 97import android.text.TextUtils; 98import android.util.EventLog; 99import android.util.Log; 100import android.util.Slog; 101 102import java.io.FileDescriptor; 103import java.io.PrintWriter; 104import java.util.ArrayList; 105import java.util.Arrays; 106import java.util.HashMap; 107import java.util.HashSet; 108import java.util.List; 109import java.util.Map; 110import java.util.Map.Entry; 111import java.util.NoSuchElementException; 112import java.util.Set; 113 114/** 115 * The service class that manages LocationProviders and issues location 116 * updates and alerts. 117 */ 118public class LocationManagerService extends ILocationManager.Stub { 119 private static final String TAG = "LocationManagerService"; 120 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); 121 122 private static final String WAKELOCK_KEY = "*location*"; 123 124 // Location resolution level: no location data whatsoever 125 private static final int RESOLUTION_LEVEL_NONE = 0; 126 // Location resolution level: coarse location data only 127 private static final int RESOLUTION_LEVEL_COARSE = 1; 128 // Location resolution level: fine location data 129 private static final int RESOLUTION_LEVEL_FINE = 2; 130 131 private static final String ACCESS_MOCK_LOCATION = 132 android.Manifest.permission.ACCESS_MOCK_LOCATION; 133 private static final String ACCESS_LOCATION_EXTRA_COMMANDS = 134 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS; 135 private static final String INSTALL_LOCATION_PROVIDER = 136 android.Manifest.permission.INSTALL_LOCATION_PROVIDER; 137 138 private static final String NETWORK_LOCATION_SERVICE_ACTION = 139 "com.android.location.service.v3.NetworkLocationProvider"; 140 private static final String FUSED_LOCATION_SERVICE_ACTION = 141 "com.android.location.service.FusedLocationProvider"; 142 143 private static final int MSG_LOCATION_CHANGED = 1; 144 145 private static final long NANOS_PER_MILLI = 1000000L; 146 147 // The maximum interval a location request can have and still be considered "high power". 148 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000; 149 150 private static final int FOREGROUND_IMPORTANCE_CUTOFF 151 = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; 152 153 // default background throttling interval if not overriden in settings 154 private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000; 155 156 // Location Providers may sometimes deliver location updates 157 // slightly faster that requested - provide grace period so 158 // we don't unnecessarily filter events that are otherwise on 159 // time 160 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100; 161 162 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest(); 163 164 private final Context mContext; 165 private final AppOpsManager mAppOps; 166 167 // used internally for synchronization 168 private final Object mLock = new Object(); 169 170 // --- fields below are final after systemRunning() --- 171 private LocationFudger mLocationFudger; 172 private GeofenceManager mGeofenceManager; 173 private PackageManager mPackageManager; 174 private PowerManager mPowerManager; 175 private ActivityManager mActivityManager; 176 private UserManager mUserManager; 177 private GeocoderProxy mGeocodeProvider; 178 private IGnssStatusProvider mGnssStatusProvider; 179 private INetInitiatedListener mNetInitiatedListener; 180 private LocationWorkerHandler mLocationHandler; 181 private PassiveProvider mPassiveProvider; // track passive provider for special cases 182 private LocationBlacklist mBlacklist; 183 private GnssMeasurementsProvider mGnssMeasurementsProvider; 184 private GnssNavigationMessageProvider mGnssNavigationMessageProvider; 185 private IGpsGeofenceHardware mGpsGeofenceProxy; 186 187 // --- fields below are protected by mLock --- 188 // Set of providers that are explicitly enabled 189 // Only used by passive, fused & test. Network & GPS are controlled separately, and not listed. 190 private final Set<String> mEnabledProviders = new HashSet<>(); 191 192 // Set of providers that are explicitly disabled 193 private final Set<String> mDisabledProviders = new HashSet<>(); 194 195 // Mock (test) providers 196 private final HashMap<String, MockProvider> mMockProviders = 197 new HashMap<>(); 198 199 // all receivers 200 private final HashMap<Object, Receiver> mReceivers = new HashMap<>(); 201 202 // currently installed providers (with mocks replacing real providers) 203 private final ArrayList<LocationProviderInterface> mProviders = 204 new ArrayList<>(); 205 206 // real providers, saved here when mocked out 207 private final HashMap<String, LocationProviderInterface> mRealProviders = 208 new HashMap<>(); 209 210 // mapping from provider name to provider 211 private final HashMap<String, LocationProviderInterface> mProvidersByName = 212 new HashMap<>(); 213 214 // mapping from provider name to all its UpdateRecords 215 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider = 216 new HashMap<>(); 217 218 private final LocationRequestStatistics mRequestStatistics = new LocationRequestStatistics(); 219 220 // mapping from provider name to last known location 221 private final HashMap<String, Location> mLastLocation = new HashMap<>(); 222 223 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS. 224 // locations stored here are not fudged for coarse permissions. 225 private final HashMap<String, Location> mLastLocationCoarseInterval = 226 new HashMap<>(); 227 228 // all providers that operate over proxy, for authorizing incoming location and whitelisting 229 // throttling 230 private final ArrayList<LocationProviderProxy> mProxyProviders = 231 new ArrayList<>(); 232 233 private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>(); 234 235 private final ArrayMap<IGnssMeasurementsListener, Identity> mGnssMeasurementsListeners = 236 new ArrayMap<>(); 237 238 private final ArrayMap<IGnssNavigationMessageListener, Identity> 239 mGnssNavigationMessageListeners = new ArrayMap<>(); 240 241 // current active user on the device - other users are denied location data 242 private int mCurrentUserId = UserHandle.USER_SYSTEM; 243 private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM}; 244 245 private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider; 246 247 private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider; 248 249 private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider; 250 private IBatchedLocationCallback mGnssBatchingCallback; 251 private LinkedCallback mGnssBatchingDeathCallback; 252 private boolean mGnssBatchingInProgress = false; 253 254 public LocationManagerService(Context context) { 255 super(); 256 mContext = context; 257 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 258 259 // Let the package manager query which are the default location 260 // providers as they get certain permissions granted by default. 261 PackageManagerInternal packageManagerInternal = LocalServices.getService( 262 PackageManagerInternal.class); 263 packageManagerInternal.setLocationPackagesProvider( 264 new PackageManagerInternal.PackagesProvider() { 265 @Override 266 public String[] getPackages(int userId) { 267 return mContext.getResources().getStringArray( 268 com.android.internal.R.array.config_locationProviderPackageNames); 269 } 270 }); 271 272 if (D) Log.d(TAG, "Constructed"); 273 274 // most startup is deferred until systemRunning() 275 } 276 277 public void systemRunning() { 278 synchronized (mLock) { 279 if (D) Log.d(TAG, "systemRunning()"); 280 281 // fetch package manager 282 mPackageManager = mContext.getPackageManager(); 283 284 // fetch power manager 285 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 286 287 // fetch activity manager 288 mActivityManager 289 = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); 290 291 // prepare worker thread 292 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper()); 293 294 // prepare mLocationHandler's dependents 295 mLocationFudger = new LocationFudger(mContext, mLocationHandler); 296 mBlacklist = new LocationBlacklist(mContext, mLocationHandler); 297 mBlacklist.init(); 298 mGeofenceManager = new GeofenceManager(mContext, mBlacklist); 299 300 // Monitor for app ops mode changes. 301 AppOpsManager.OnOpChangedListener callback 302 = new AppOpsManager.OnOpChangedInternalListener() { 303 public void onOpChanged(int op, String packageName) { 304 synchronized (mLock) { 305 for (Receiver receiver : mReceivers.values()) { 306 receiver.updateMonitoring(true); 307 } 308 applyAllProviderRequirementsLocked(); 309 } 310 } 311 }; 312 mAppOps.startWatchingMode(AppOpsManager.OP_COARSE_LOCATION, null, callback); 313 314 PackageManager.OnPermissionsChangedListener permissionListener 315 = new PackageManager.OnPermissionsChangedListener() { 316 @Override 317 public void onPermissionsChanged(final int uid) { 318 synchronized (mLock) { 319 applyAllProviderRequirementsLocked(); 320 } 321 } 322 }; 323 mPackageManager.addOnPermissionsChangeListener(permissionListener); 324 325 // listen for background/foreground changes 326 ActivityManager.OnUidImportanceListener uidImportanceListener 327 = new ActivityManager.OnUidImportanceListener() { 328 @Override 329 public void onUidImportance(final int uid, final int importance) { 330 mLocationHandler.post(new Runnable() { 331 @Override 332 public void run() { 333 onUidImportanceChanged(uid, importance); 334 } 335 }); 336 } 337 }; 338 mActivityManager.addOnUidImportanceListener(uidImportanceListener, 339 FOREGROUND_IMPORTANCE_CUTOFF); 340 341 mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); 342 updateUserProfiles(mCurrentUserId); 343 344 updateBackgroundThrottlingWhitelistLocked(); 345 346 // prepare providers 347 loadProvidersLocked(); 348 updateProvidersLocked(); 349 } 350 351 // listen for settings changes 352 mContext.getContentResolver().registerContentObserver( 353 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true, 354 new ContentObserver(mLocationHandler) { 355 @Override 356 public void onChange(boolean selfChange) { 357 synchronized (mLock) { 358 updateProvidersLocked(); 359 } 360 } 361 }, UserHandle.USER_ALL); 362 mContext.getContentResolver().registerContentObserver( 363 Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS), 364 true, 365 new ContentObserver(mLocationHandler) { 366 @Override 367 public void onChange(boolean selfChange) { 368 synchronized (mLock) { 369 updateProvidersLocked(); 370 } 371 } 372 }, UserHandle.USER_ALL); 373 mContext.getContentResolver().registerContentObserver( 374 Settings.Global.getUriFor( 375 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST), 376 true, 377 new ContentObserver(mLocationHandler) { 378 @Override 379 public void onChange(boolean selfChange) { 380 synchronized (mLock) { 381 updateBackgroundThrottlingWhitelistLocked(); 382 updateProvidersLocked(); 383 } 384 } 385 }, UserHandle.USER_ALL); 386 mPackageMonitor.register(mContext, mLocationHandler.getLooper(), true); 387 388 // listen for user change 389 IntentFilter intentFilter = new IntentFilter(); 390 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 391 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); 392 intentFilter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); 393 intentFilter.addAction(Intent.ACTION_SHUTDOWN); 394 395 mContext.registerReceiverAsUser(new BroadcastReceiver() { 396 @Override 397 public void onReceive(Context context, Intent intent) { 398 String action = intent.getAction(); 399 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 400 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 401 } else if (Intent.ACTION_MANAGED_PROFILE_ADDED.equals(action) 402 || Intent.ACTION_MANAGED_PROFILE_REMOVED.equals(action)) { 403 updateUserProfiles(mCurrentUserId); 404 } else if (Intent.ACTION_SHUTDOWN.equals(action)) { 405 // shutdown only if UserId indicates whole system, not just one user 406 if (D) Log.d(TAG, "Shutdown received with UserId: " + getSendingUserId()); 407 if (getSendingUserId() == UserHandle.USER_ALL) { 408 shutdownComponents(); 409 } 410 } 411 } 412 }, UserHandle.ALL, intentFilter, null, mLocationHandler); 413 } 414 415 private void onUidImportanceChanged(int uid, int importance) { 416 boolean foreground = isImportanceForeground(importance); 417 HashSet<String> affectedProviders = new HashSet<>(mRecordsByProvider.size()); 418 synchronized (mLock) { 419 for (Entry<String, ArrayList<UpdateRecord>> entry 420 : mRecordsByProvider.entrySet()) { 421 String provider = entry.getKey(); 422 for (UpdateRecord record : entry.getValue()) { 423 if (record.mReceiver.mIdentity.mUid == uid 424 && record.mIsForegroundUid != foreground) { 425 if (D) { 426 Log.d(TAG, "request from uid " + uid + " is now " 427 + (foreground ? "foreground" : "background)")); 428 } 429 record.mIsForegroundUid = foreground; 430 431 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) { 432 affectedProviders.add(provider); 433 } 434 } 435 } 436 } 437 for (String provider : affectedProviders) { 438 applyRequirementsLocked(provider); 439 } 440 441 for (Entry<IGnssMeasurementsListener, Identity> entry 442 : mGnssMeasurementsListeners.entrySet()) { 443 if (entry.getValue().mUid == uid) { 444 if (D) { 445 Log.d(TAG, "gnss measurements listener from uid " + uid 446 + " is now " + (foreground ? "foreground" : "background)")); 447 } 448 if (foreground || isThrottlingExemptLocked(entry.getValue())) { 449 mGnssMeasurementsProvider.addListener(entry.getKey()); 450 } else { 451 mGnssMeasurementsProvider.removeListener(entry.getKey()); 452 } 453 } 454 } 455 456 for (Entry<IGnssNavigationMessageListener, Identity> entry 457 : mGnssNavigationMessageListeners.entrySet()) { 458 if (entry.getValue().mUid == uid) { 459 if (D) { 460 Log.d(TAG, "gnss navigation message listener from uid " 461 + uid + " is now " 462 + (foreground ? "foreground" : "background)")); 463 } 464 if (foreground || isThrottlingExemptLocked(entry.getValue())) { 465 mGnssNavigationMessageProvider.addListener(entry.getKey()); 466 } else { 467 mGnssNavigationMessageProvider.removeListener(entry.getKey()); 468 } 469 } 470 } 471 } 472 } 473 474 private static boolean isImportanceForeground(int importance) { 475 return importance <= FOREGROUND_IMPORTANCE_CUTOFF; 476 } 477 478 /** 479 * Provides a way for components held by the {@link LocationManagerService} to clean-up 480 * gracefully on system's shutdown. 481 * 482 * NOTES: 483 * 1) Only provides a chance to clean-up on an opt-in basis. This guarantees back-compat 484 * support for components that do not wish to handle such event. 485 */ 486 private void shutdownComponents() { 487 if (D) Log.d(TAG, "Shutting down components..."); 488 489 LocationProviderInterface gpsProvider = mProvidersByName.get(LocationManager.GPS_PROVIDER); 490 if (gpsProvider != null && gpsProvider.isEnabled()) { 491 gpsProvider.disable(); 492 } 493 494 // it is needed to check if FLP HW provider is supported before accessing the instance, this 495 // avoids an exception to be thrown by the singleton factory method 496 if (FlpHardwareProvider.isSupported()) { 497 FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext); 498 flpHardwareProvider.cleanup(); 499 } 500 } 501 502 /** 503 * Makes a list of userids that are related to the current user. This is 504 * relevant when using managed profiles. Otherwise the list only contains 505 * the current user. 506 * 507 * @param currentUserId the current user, who might have an alter-ego. 508 */ 509 void updateUserProfiles(int currentUserId) { 510 int[] profileIds = mUserManager.getProfileIdsWithDisabled(currentUserId); 511 synchronized (mLock) { 512 mCurrentUserProfiles = profileIds; 513 } 514 } 515 516 /** 517 * Checks if the specified userId matches any of the current foreground 518 * users stored in mCurrentUserProfiles. 519 */ 520 private boolean isCurrentProfile(int userId) { 521 synchronized (mLock) { 522 return ArrayUtils.contains(mCurrentUserProfiles, userId); 523 } 524 } 525 526 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) { 527 PackageManager pm = mContext.getPackageManager(); 528 String systemPackageName = mContext.getPackageName(); 529 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs); 530 531 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser( 532 new Intent(FUSED_LOCATION_SERVICE_ACTION), 533 PackageManager.GET_META_DATA, mCurrentUserId); 534 for (ResolveInfo rInfo : rInfos) { 535 String packageName = rInfo.serviceInfo.packageName; 536 537 // Check that the signature is in the list of supported sigs. If it's not in 538 // this list the standard provider binding logic won't bind to it. 539 try { 540 PackageInfo pInfo; 541 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); 542 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) { 543 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION + 544 ", but has wrong signature, ignoring"); 545 continue; 546 } 547 } catch (NameNotFoundException e) { 548 Log.e(TAG, "missing package: " + packageName); 549 continue; 550 } 551 552 // Get the version info 553 if (rInfo.serviceInfo.metaData == null) { 554 Log.w(TAG, "Found fused provider without metadata: " + packageName); 555 continue; 556 } 557 558 int version = rInfo.serviceInfo.metaData.getInt( 559 ServiceWatcher.EXTRA_SERVICE_VERSION, -1); 560 if (version == 0) { 561 // This should be the fallback fused location provider. 562 563 // Make sure it's in the system partition. 564 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 565 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName); 566 continue; 567 } 568 569 // Check that the fallback is signed the same as the OS 570 // as a proxy for coreApp="true" 571 if (pm.checkSignatures(systemPackageName, packageName) 572 != PackageManager.SIGNATURE_MATCH) { 573 if (D) { 574 Log.d(TAG, "Fallback candidate not signed the same as system: " 575 + packageName); 576 } 577 continue; 578 } 579 580 // Found a valid fallback. 581 if (D) Log.d(TAG, "Found fallback provider: " + packageName); 582 return; 583 } else { 584 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName); 585 } 586 } 587 588 throw new IllegalStateException("Unable to find a fused location provider that is in the " 589 + "system partition with version 0 and signed with the platform certificate. " 590 + "Such a package is needed to provide a default fused location provider in the " 591 + "event that no other fused location provider has been installed or is currently " 592 + "available. For example, coreOnly boot mode when decrypting the data " 593 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest"); 594 } 595 596 private void loadProvidersLocked() { 597 // create a passive location provider, which is always enabled 598 PassiveProvider passiveProvider = new PassiveProvider(this); 599 addProviderLocked(passiveProvider); 600 mEnabledProviders.add(passiveProvider.getName()); 601 mPassiveProvider = passiveProvider; 602 603 if (GnssLocationProvider.isSupported()) { 604 // Create a gps location provider 605 GnssLocationProvider gnssProvider = new GnssLocationProvider(mContext, this, 606 mLocationHandler.getLooper()); 607 mGnssSystemInfoProvider = gnssProvider.getGnssSystemInfoProvider(); 608 mGnssBatchingProvider = gnssProvider.getGnssBatchingProvider(); 609 mGnssMetricsProvider = gnssProvider.getGnssMetricsProvider(); 610 mGnssStatusProvider = gnssProvider.getGnssStatusProvider(); 611 mNetInitiatedListener = gnssProvider.getNetInitiatedListener(); 612 addProviderLocked(gnssProvider); 613 mRealProviders.put(LocationManager.GPS_PROVIDER, gnssProvider); 614 mGnssMeasurementsProvider = gnssProvider.getGnssMeasurementsProvider(); 615 mGnssNavigationMessageProvider = gnssProvider.getGnssNavigationMessageProvider(); 616 mGpsGeofenceProxy = gnssProvider.getGpsGeofenceProxy(); 617 } 618 619 /* 620 Load package name(s) containing location provider support. 621 These packages can contain services implementing location providers: 622 Geocoder Provider, Network Location Provider, and 623 Fused Location Provider. They will each be searched for 624 service components implementing these providers. 625 The location framework also has support for installation 626 of new location providers at run-time. The new package does not 627 have to be explicitly listed here, however it must have a signature 628 that matches the signature of at least one package on this list. 629 */ 630 Resources resources = mContext.getResources(); 631 ArrayList<String> providerPackageNames = new ArrayList<>(); 632 String[] pkgs = resources.getStringArray( 633 com.android.internal.R.array.config_locationProviderPackageNames); 634 if (D) { 635 Log.d(TAG, "certificates for location providers pulled from: " + 636 Arrays.toString(pkgs)); 637 } 638 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs)); 639 640 ensureFallbackFusedProviderPresentLocked(providerPackageNames); 641 642 // bind to network provider 643 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind( 644 mContext, 645 LocationManager.NETWORK_PROVIDER, 646 NETWORK_LOCATION_SERVICE_ACTION, 647 com.android.internal.R.bool.config_enableNetworkLocationOverlay, 648 com.android.internal.R.string.config_networkLocationProviderPackageName, 649 com.android.internal.R.array.config_locationProviderPackageNames, 650 mLocationHandler); 651 if (networkProvider != null) { 652 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider); 653 mProxyProviders.add(networkProvider); 654 addProviderLocked(networkProvider); 655 } else { 656 Slog.w(TAG, "no network location provider found"); 657 } 658 659 // bind to fused provider 660 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind( 661 mContext, 662 LocationManager.FUSED_PROVIDER, 663 FUSED_LOCATION_SERVICE_ACTION, 664 com.android.internal.R.bool.config_enableFusedLocationOverlay, 665 com.android.internal.R.string.config_fusedLocationProviderPackageName, 666 com.android.internal.R.array.config_locationProviderPackageNames, 667 mLocationHandler); 668 if (fusedLocationProvider != null) { 669 addProviderLocked(fusedLocationProvider); 670 mProxyProviders.add(fusedLocationProvider); 671 mEnabledProviders.add(fusedLocationProvider.getName()); 672 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider); 673 } else { 674 Slog.e(TAG, "no fused location provider found", 675 new IllegalStateException("Location service needs a fused location provider")); 676 } 677 678 // bind to geocoder provider 679 mGeocodeProvider = GeocoderProxy.createAndBind(mContext, 680 com.android.internal.R.bool.config_enableGeocoderOverlay, 681 com.android.internal.R.string.config_geocoderProviderPackageName, 682 com.android.internal.R.array.config_locationProviderPackageNames, 683 mLocationHandler); 684 if (mGeocodeProvider == null) { 685 Slog.e(TAG, "no geocoder provider found"); 686 } 687 688 // bind to fused hardware provider if supported 689 // in devices without support, requesting an instance of FlpHardwareProvider will raise an 690 // exception, so make sure we only do that when supported 691 FlpHardwareProvider flpHardwareProvider; 692 if (FlpHardwareProvider.isSupported()) { 693 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext); 694 FusedProxy fusedProxy = FusedProxy.createAndBind( 695 mContext, 696 mLocationHandler, 697 flpHardwareProvider.getLocationHardware(), 698 com.android.internal.R.bool.config_enableHardwareFlpOverlay, 699 com.android.internal.R.string.config_hardwareFlpPackageName, 700 com.android.internal.R.array.config_locationProviderPackageNames); 701 if (fusedProxy == null) { 702 Slog.d(TAG, "Unable to bind FusedProxy."); 703 } 704 } else { 705 flpHardwareProvider = null; 706 Slog.d(TAG, "FLP HAL not supported"); 707 } 708 709 // bind to geofence provider 710 GeofenceProxy provider = GeofenceProxy.createAndBind( 711 mContext, com.android.internal.R.bool.config_enableGeofenceOverlay, 712 com.android.internal.R.string.config_geofenceProviderPackageName, 713 com.android.internal.R.array.config_locationProviderPackageNames, 714 mLocationHandler, 715 mGpsGeofenceProxy, 716 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null); 717 if (provider == null) { 718 Slog.d(TAG, "Unable to bind FLP Geofence proxy."); 719 } 720 721 // bind to hardware activity recognition 722 boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported(); 723 ActivityRecognitionHardware activityRecognitionHardware = null; 724 if (activityRecognitionHardwareIsSupported) { 725 activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext); 726 } else { 727 Slog.d(TAG, "Hardware Activity-Recognition not supported."); 728 } 729 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind( 730 mContext, 731 mLocationHandler, 732 activityRecognitionHardwareIsSupported, 733 activityRecognitionHardware, 734 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay, 735 com.android.internal.R.string.config_activityRecognitionHardwarePackageName, 736 com.android.internal.R.array.config_locationProviderPackageNames); 737 if (proxy == null) { 738 Slog.d(TAG, "Unable to bind ActivityRecognitionProxy."); 739 } 740 741 String[] testProviderStrings = resources.getStringArray( 742 com.android.internal.R.array.config_testLocationProviders); 743 for (String testProviderString : testProviderStrings) { 744 String fragments[] = testProviderString.split(","); 745 String name = fragments[0].trim(); 746 if (mProvidersByName.get(name) != null) { 747 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 748 } 749 ProviderProperties properties = new ProviderProperties( 750 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */, 751 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */, 752 Boolean.parseBoolean(fragments[3]) /* requiresCell */, 753 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */, 754 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */, 755 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */, 756 Boolean.parseBoolean(fragments[7]) /* supportsBearing */, 757 Integer.parseInt(fragments[8]) /* powerRequirement */, 758 Integer.parseInt(fragments[9]) /* accuracy */); 759 addTestProviderLocked(name, properties); 760 } 761 } 762 763 /** 764 * Called when the device's active user changes. 765 * 766 * @param userId the new active user's UserId 767 */ 768 private void switchUser(int userId) { 769 if (mCurrentUserId == userId) { 770 return; 771 } 772 mBlacklist.switchUser(userId); 773 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED); 774 synchronized (mLock) { 775 mLastLocation.clear(); 776 mLastLocationCoarseInterval.clear(); 777 for (LocationProviderInterface p : mProviders) { 778 updateProviderListenersLocked(p.getName(), false); 779 } 780 mCurrentUserId = userId; 781 updateUserProfiles(userId); 782 updateProvidersLocked(); 783 } 784 } 785 786 private static final class Identity { 787 final int mUid; 788 final int mPid; 789 final String mPackageName; 790 791 Identity(int uid, int pid, String packageName) { 792 mUid = uid; 793 mPid = pid; 794 mPackageName = packageName; 795 } 796 } 797 798 /** 799 * A wrapper class holding either an ILocationListener or a PendingIntent to receive 800 * location updates. 801 */ 802 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { 803 final Identity mIdentity; 804 final int mAllowedResolutionLevel; // resolution level allowed to receiver 805 806 final ILocationListener mListener; 807 final PendingIntent mPendingIntent; 808 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller. 809 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver. 810 final Object mKey; 811 812 final HashMap<String, UpdateRecord> mUpdateRecords = new HashMap<>(); 813 814 // True if app ops has started monitoring this receiver for locations. 815 boolean mOpMonitoring; 816 // True if app ops has started monitoring this receiver for high power (gps) locations. 817 boolean mOpHighPowerMonitoring; 818 int mPendingBroadcasts; 819 PowerManager.WakeLock mWakeLock; 820 821 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid, 822 String packageName, WorkSource workSource, boolean hideFromAppOps) { 823 mListener = listener; 824 mPendingIntent = intent; 825 if (listener != null) { 826 mKey = listener.asBinder(); 827 } else { 828 mKey = intent; 829 } 830 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid); 831 mIdentity = new Identity(uid, pid, packageName); 832 if (workSource != null && workSource.size() <= 0) { 833 workSource = null; 834 } 835 mWorkSource = workSource; 836 mHideFromAppOps = hideFromAppOps; 837 838 updateMonitoring(true); 839 840 // construct/configure wakelock 841 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 842 if (workSource == null) { 843 workSource = new WorkSource(mIdentity.mUid, mIdentity.mPackageName); 844 } 845 mWakeLock.setWorkSource(workSource); 846 } 847 848 @Override 849 public boolean equals(Object otherObj) { 850 return (otherObj instanceof Receiver) && mKey.equals(((Receiver) otherObj).mKey); 851 } 852 853 @Override 854 public int hashCode() { 855 return mKey.hashCode(); 856 } 857 858 @Override 859 public String toString() { 860 StringBuilder s = new StringBuilder(); 861 s.append("Reciever["); 862 s.append(Integer.toHexString(System.identityHashCode(this))); 863 if (mListener != null) { 864 s.append(" listener"); 865 } else { 866 s.append(" intent"); 867 } 868 for (String p : mUpdateRecords.keySet()) { 869 s.append(" ").append(mUpdateRecords.get(p).toString()); 870 } 871 s.append("]"); 872 return s.toString(); 873 } 874 875 /** 876 * Update AppOp monitoring for this receiver. 877 * 878 * @param allow If true receiver is currently active, if false it's been removed. 879 */ 880 public void updateMonitoring(boolean allow) { 881 if (mHideFromAppOps) { 882 return; 883 } 884 885 boolean requestingLocation = false; 886 boolean requestingHighPowerLocation = false; 887 if (allow) { 888 // See if receiver has any enabled update records. Also note if any update records 889 // are high power (has a high power provider with an interval under a threshold). 890 for (UpdateRecord updateRecord : mUpdateRecords.values()) { 891 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) { 892 requestingLocation = true; 893 LocationProviderInterface locationProvider 894 = mProvidersByName.get(updateRecord.mProvider); 895 ProviderProperties properties = locationProvider != null 896 ? locationProvider.getProperties() : null; 897 if (properties != null 898 && properties.mPowerRequirement == Criteria.POWER_HIGH 899 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) { 900 requestingHighPowerLocation = true; 901 break; 902 } 903 } 904 } 905 } 906 907 // First update monitoring of any location request (including high power). 908 mOpMonitoring = updateMonitoring( 909 requestingLocation, 910 mOpMonitoring, 911 AppOpsManager.OP_MONITOR_LOCATION); 912 913 // Now update monitoring of high power requests only. 914 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring; 915 mOpHighPowerMonitoring = updateMonitoring( 916 requestingHighPowerLocation, 917 mOpHighPowerMonitoring, 918 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION); 919 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) { 920 // Send an intent to notify that a high power request has been added/removed. 921 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION); 922 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 923 } 924 } 925 926 /** 927 * Update AppOps monitoring for a single location request and op type. 928 * 929 * @param allowMonitoring True if monitoring is allowed for this request/op. 930 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op. 931 * @param op AppOps code for the op to update. 932 * @return True if monitoring is on for this request/op after updating. 933 */ 934 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring, 935 int op) { 936 if (!currentlyMonitoring) { 937 if (allowMonitoring) { 938 return mAppOps.startOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName) 939 == AppOpsManager.MODE_ALLOWED; 940 } 941 } else { 942 if (!allowMonitoring 943 || mAppOps.checkOpNoThrow(op, mIdentity.mUid, mIdentity.mPackageName) 944 != AppOpsManager.MODE_ALLOWED) { 945 mAppOps.finishOp(op, mIdentity.mUid, mIdentity.mPackageName); 946 return false; 947 } 948 } 949 950 return currentlyMonitoring; 951 } 952 953 public boolean isListener() { 954 return mListener != null; 955 } 956 957 public boolean isPendingIntent() { 958 return mPendingIntent != null; 959 } 960 961 public ILocationListener getListener() { 962 if (mListener != null) { 963 return mListener; 964 } 965 throw new IllegalStateException("Request for non-existent listener"); 966 } 967 968 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { 969 if (mListener != null) { 970 try { 971 synchronized (this) { 972 // synchronize to ensure incrementPendingBroadcastsLocked() 973 // is called before decrementPendingBroadcasts() 974 mListener.onStatusChanged(provider, status, extras); 975 // call this after broadcasting so we do not increment 976 // if we throw an exeption. 977 incrementPendingBroadcastsLocked(); 978 } 979 } catch (RemoteException e) { 980 return false; 981 } 982 } else { 983 Intent statusChanged = new Intent(); 984 statusChanged.putExtras(new Bundle(extras)); 985 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); 986 try { 987 synchronized (this) { 988 // synchronize to ensure incrementPendingBroadcastsLocked() 989 // is called before decrementPendingBroadcasts() 990 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler, 991 getResolutionPermission(mAllowedResolutionLevel)); 992 // call this after broadcasting so we do not increment 993 // if we throw an exeption. 994 incrementPendingBroadcastsLocked(); 995 } 996 } catch (PendingIntent.CanceledException e) { 997 return false; 998 } 999 } 1000 return true; 1001 } 1002 1003 public boolean callLocationChangedLocked(Location location) { 1004 if (mListener != null) { 1005 try { 1006 synchronized (this) { 1007 // synchronize to ensure incrementPendingBroadcastsLocked() 1008 // is called before decrementPendingBroadcasts() 1009 mListener.onLocationChanged(new Location(location)); 1010 // call this after broadcasting so we do not increment 1011 // if we throw an exeption. 1012 incrementPendingBroadcastsLocked(); 1013 } 1014 } catch (RemoteException e) { 1015 return false; 1016 } 1017 } else { 1018 Intent locationChanged = new Intent(); 1019 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, 1020 new Location(location)); 1021 try { 1022 synchronized (this) { 1023 // synchronize to ensure incrementPendingBroadcastsLocked() 1024 // is called before decrementPendingBroadcasts() 1025 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler, 1026 getResolutionPermission(mAllowedResolutionLevel)); 1027 // call this after broadcasting so we do not increment 1028 // if we throw an exeption. 1029 incrementPendingBroadcastsLocked(); 1030 } 1031 } catch (PendingIntent.CanceledException e) { 1032 return false; 1033 } 1034 } 1035 return true; 1036 } 1037 1038 public boolean callProviderEnabledLocked(String provider, boolean enabled) { 1039 // First update AppOp monitoring. 1040 // An app may get/lose location access as providers are enabled/disabled. 1041 updateMonitoring(true); 1042 1043 if (mListener != null) { 1044 try { 1045 synchronized (this) { 1046 // synchronize to ensure incrementPendingBroadcastsLocked() 1047 // is called before decrementPendingBroadcasts() 1048 if (enabled) { 1049 mListener.onProviderEnabled(provider); 1050 } else { 1051 mListener.onProviderDisabled(provider); 1052 } 1053 // call this after broadcasting so we do not increment 1054 // if we throw an exeption. 1055 incrementPendingBroadcastsLocked(); 1056 } 1057 } catch (RemoteException e) { 1058 return false; 1059 } 1060 } else { 1061 Intent providerIntent = new Intent(); 1062 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); 1063 try { 1064 synchronized (this) { 1065 // synchronize to ensure incrementPendingBroadcastsLocked() 1066 // is called before decrementPendingBroadcasts() 1067 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler, 1068 getResolutionPermission(mAllowedResolutionLevel)); 1069 // call this after broadcasting so we do not increment 1070 // if we throw an exeption. 1071 incrementPendingBroadcastsLocked(); 1072 } 1073 } catch (PendingIntent.CanceledException e) { 1074 return false; 1075 } 1076 } 1077 return true; 1078 } 1079 1080 @Override 1081 public void binderDied() { 1082 if (D) Log.d(TAG, "Location listener died"); 1083 1084 synchronized (mLock) { 1085 removeUpdatesLocked(this); 1086 } 1087 synchronized (this) { 1088 clearPendingBroadcastsLocked(); 1089 } 1090 } 1091 1092 @Override 1093 public void onSendFinished(PendingIntent pendingIntent, Intent intent, 1094 int resultCode, String resultData, Bundle resultExtras) { 1095 synchronized (this) { 1096 decrementPendingBroadcastsLocked(); 1097 } 1098 } 1099 1100 // this must be called while synchronized by caller in a synchronized block 1101 // containing the sending of the broadcaset 1102 private void incrementPendingBroadcastsLocked() { 1103 if (mPendingBroadcasts++ == 0) { 1104 mWakeLock.acquire(); 1105 } 1106 } 1107 1108 private void decrementPendingBroadcastsLocked() { 1109 if (--mPendingBroadcasts == 0) { 1110 if (mWakeLock.isHeld()) { 1111 mWakeLock.release(); 1112 } 1113 } 1114 } 1115 1116 public void clearPendingBroadcastsLocked() { 1117 if (mPendingBroadcasts > 0) { 1118 mPendingBroadcasts = 0; 1119 if (mWakeLock.isHeld()) { 1120 mWakeLock.release(); 1121 } 1122 } 1123 } 1124 } 1125 1126 @Override 1127 public void locationCallbackFinished(ILocationListener listener) { 1128 //Do not use getReceiverLocked here as that will add the ILocationListener to 1129 //the receiver list if it is not found. If it is not found then the 1130 //LocationListener was removed when it had a pending broadcast and should 1131 //not be added back. 1132 synchronized (mLock) { 1133 IBinder binder = listener.asBinder(); 1134 Receiver receiver = mReceivers.get(binder); 1135 if (receiver != null) { 1136 synchronized (receiver) { 1137 // so wakelock calls will succeed 1138 long identity = Binder.clearCallingIdentity(); 1139 receiver.decrementPendingBroadcastsLocked(); 1140 Binder.restoreCallingIdentity(identity); 1141 } 1142 } 1143 } 1144 } 1145 1146 /** 1147 * Returns the system information of the GNSS hardware. 1148 */ 1149 @Override 1150 public int getGnssYearOfHardware() { 1151 if (mGnssSystemInfoProvider != null) { 1152 return mGnssSystemInfoProvider.getGnssYearOfHardware(); 1153 } else { 1154 return 0; 1155 } 1156 } 1157 1158 /** 1159 * Runs some checks for GNSS (FINE) level permissions, used by several methods which directly 1160 * (try to) access GNSS information at this layer. 1161 */ 1162 private boolean hasGnssPermissions(String packageName) { 1163 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1164 checkResolutionLevelIsSufficientForProviderUse( 1165 allowedResolutionLevel, 1166 LocationManager.GPS_PROVIDER); 1167 1168 int pid = Binder.getCallingPid(); 1169 int uid = Binder.getCallingUid(); 1170 long identity = Binder.clearCallingIdentity(); 1171 boolean hasLocationAccess; 1172 try { 1173 hasLocationAccess = checkLocationAccess(pid, uid, packageName, allowedResolutionLevel); 1174 } finally { 1175 Binder.restoreCallingIdentity(identity); 1176 } 1177 1178 return hasLocationAccess; 1179 } 1180 1181 /** 1182 * Returns the GNSS batching size, if available. 1183 */ 1184 @Override 1185 public int getGnssBatchSize(String packageName) { 1186 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, 1187 "Location Hardware permission not granted to access hardware batching"); 1188 1189 if (hasGnssPermissions(packageName) && mGnssBatchingProvider != null) { 1190 return mGnssBatchingProvider.getSize(); 1191 } else { 1192 return 0; 1193 } 1194 } 1195 1196 /** 1197 * Adds a callback for GNSS Batching events, if permissions allow, which are transported 1198 * to potentially multiple listeners by the BatchedLocationCallbackTransport above this. 1199 */ 1200 @Override 1201 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName) { 1202 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, 1203 "Location Hardware permission not granted to access hardware batching"); 1204 1205 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) { 1206 return false; 1207 } 1208 1209 mGnssBatchingCallback = callback; 1210 mGnssBatchingDeathCallback = new LinkedCallback(callback); 1211 try { 1212 callback.asBinder().linkToDeath(mGnssBatchingDeathCallback, 0 /* flags */); 1213 } catch (RemoteException e) { 1214 // if the remote process registering the listener is already dead, just swallow the 1215 // exception and return 1216 Log.e(TAG, "Remote listener already died.", e); 1217 return false; 1218 } 1219 1220 return true; 1221 } 1222 1223 private class LinkedCallback implements IBinder.DeathRecipient { 1224 private final IBatchedLocationCallback mCallback; 1225 1226 public LinkedCallback(@NonNull IBatchedLocationCallback callback) { 1227 mCallback = callback; 1228 } 1229 1230 @NonNull 1231 public IBatchedLocationCallback getUnderlyingListener() { 1232 return mCallback; 1233 } 1234 1235 @Override 1236 public void binderDied() { 1237 Log.d(TAG, "Remote Batching Callback died: " + mCallback); 1238 stopGnssBatch(); 1239 removeGnssBatchingCallback(); 1240 } 1241 } 1242 1243 /** 1244 * Removes callback for GNSS batching 1245 */ 1246 @Override 1247 public void removeGnssBatchingCallback() { 1248 try { 1249 mGnssBatchingCallback.asBinder().unlinkToDeath(mGnssBatchingDeathCallback, 1250 0 /* flags */); 1251 } catch (NoSuchElementException e) { 1252 // if the death callback isn't connected (it should be...), log error, swallow the 1253 // exception and return 1254 Log.e(TAG, "Couldn't unlink death callback.", e); 1255 } 1256 mGnssBatchingCallback = null; 1257 mGnssBatchingDeathCallback = null; 1258 } 1259 1260 1261 /** 1262 * Starts GNSS batching, if available. 1263 */ 1264 @Override 1265 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName) { 1266 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, 1267 "Location Hardware permission not granted to access hardware batching"); 1268 1269 if (!hasGnssPermissions(packageName) || mGnssBatchingProvider == null) { 1270 return false; 1271 } 1272 1273 if (mGnssBatchingInProgress) { 1274 // Current design does not expect multiple starts to be called repeatedly 1275 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch"); 1276 // Try to clean up anyway, and continue 1277 stopGnssBatch(); 1278 } 1279 1280 mGnssBatchingInProgress = true; 1281 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull); 1282 } 1283 1284 /** 1285 * Flushes a GNSS batch in progress 1286 */ 1287 @Override 1288 public void flushGnssBatch(String packageName) { 1289 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, 1290 "Location Hardware permission not granted to access hardware batching"); 1291 1292 if (!hasGnssPermissions(packageName)) { 1293 Log.e(TAG, "flushGnssBatch called without GNSS permissions"); 1294 return; 1295 } 1296 1297 if (!mGnssBatchingInProgress) { 1298 Log.w(TAG, "flushGnssBatch called with no batch in progress"); 1299 } 1300 1301 if (mGnssBatchingProvider != null) { 1302 mGnssBatchingProvider.flush(); 1303 } 1304 } 1305 1306 /** 1307 * Stops GNSS batching 1308 */ 1309 @Override 1310 public boolean stopGnssBatch() { 1311 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, 1312 "Location Hardware permission not granted to access hardware batching"); 1313 1314 if (mGnssBatchingProvider != null) { 1315 mGnssBatchingInProgress = false; 1316 return mGnssBatchingProvider.stop(); 1317 } else { 1318 return false; 1319 } 1320 } 1321 1322 @Override 1323 public void reportLocationBatch(List<Location> locations) { 1324 checkCallerIsProvider(); 1325 1326 // Currently used only for GNSS locations - update permissions check if changed 1327 if (isAllowedByCurrentUserSettingsLocked(LocationManager.GPS_PROVIDER)) { 1328 if (mGnssBatchingCallback == null) { 1329 Slog.e(TAG, "reportLocationBatch() called without active Callback"); 1330 return; 1331 } 1332 try { 1333 mGnssBatchingCallback.onLocationBatch(locations); 1334 } catch (RemoteException e) { 1335 Slog.e(TAG, "mGnssBatchingCallback.onLocationBatch failed", e); 1336 } 1337 } else { 1338 Slog.w(TAG, "reportLocationBatch() called without user permission, locations blocked"); 1339 } 1340 } 1341 1342 private void addProviderLocked(LocationProviderInterface provider) { 1343 mProviders.add(provider); 1344 mProvidersByName.put(provider.getName(), provider); 1345 } 1346 1347 private void removeProviderLocked(LocationProviderInterface provider) { 1348 provider.disable(); 1349 mProviders.remove(provider); 1350 mProvidersByName.remove(provider.getName()); 1351 } 1352 1353 /** 1354 * Returns "true" if access to the specified location provider is allowed by the current 1355 * user's settings. Access to all location providers is forbidden to non-location-provider 1356 * processes belonging to background users. 1357 * 1358 * @param provider the name of the location provider 1359 */ 1360 private boolean isAllowedByCurrentUserSettingsLocked(String provider) { 1361 if (mEnabledProviders.contains(provider)) { 1362 return true; 1363 } 1364 if (mDisabledProviders.contains(provider)) { 1365 return false; 1366 } 1367 // Use system settings 1368 ContentResolver resolver = mContext.getContentResolver(); 1369 1370 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId); 1371 } 1372 1373 /** 1374 * Returns "true" if access to the specified location provider is allowed by the specified 1375 * user's settings. Access to all location providers is forbidden to non-location-provider 1376 * processes belonging to background users. 1377 * 1378 * @param provider the name of the location provider 1379 * @param uid the requestor's UID 1380 */ 1381 private boolean isAllowedByUserSettingsLocked(String provider, int uid) { 1382 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) { 1383 return false; 1384 } 1385 return isAllowedByCurrentUserSettingsLocked(provider); 1386 } 1387 1388 /** 1389 * Returns the permission string associated with the specified resolution level. 1390 * 1391 * @param resolutionLevel the resolution level 1392 * @return the permission string 1393 */ 1394 private String getResolutionPermission(int resolutionLevel) { 1395 switch (resolutionLevel) { 1396 case RESOLUTION_LEVEL_FINE: 1397 return android.Manifest.permission.ACCESS_FINE_LOCATION; 1398 case RESOLUTION_LEVEL_COARSE: 1399 return android.Manifest.permission.ACCESS_COARSE_LOCATION; 1400 default: 1401 return null; 1402 } 1403 } 1404 1405 /** 1406 * Returns the resolution level allowed to the given PID/UID pair. 1407 * 1408 * @param pid the PID 1409 * @param uid the UID 1410 * @return resolution level allowed to the pid/uid pair 1411 */ 1412 private int getAllowedResolutionLevel(int pid, int uid) { 1413 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, 1414 pid, uid) == PackageManager.PERMISSION_GRANTED) { 1415 return RESOLUTION_LEVEL_FINE; 1416 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, 1417 pid, uid) == PackageManager.PERMISSION_GRANTED) { 1418 return RESOLUTION_LEVEL_COARSE; 1419 } else { 1420 return RESOLUTION_LEVEL_NONE; 1421 } 1422 } 1423 1424 /** 1425 * Returns the resolution level allowed to the caller 1426 * 1427 * @return resolution level allowed to caller 1428 */ 1429 private int getCallerAllowedResolutionLevel() { 1430 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid()); 1431 } 1432 1433 /** 1434 * Throw SecurityException if specified resolution level is insufficient to use geofences. 1435 * 1436 * @param allowedResolutionLevel resolution level allowed to caller 1437 */ 1438 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) { 1439 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1440 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission"); 1441 } 1442 } 1443 1444 /** 1445 * Return the minimum resolution level required to use the specified location provider. 1446 * 1447 * @param provider the name of the location provider 1448 * @return minimum resolution level required for provider 1449 */ 1450 private int getMinimumResolutionLevelForProviderUse(String provider) { 1451 if (LocationManager.GPS_PROVIDER.equals(provider) || 1452 LocationManager.PASSIVE_PROVIDER.equals(provider)) { 1453 // gps and passive providers require FINE permission 1454 return RESOLUTION_LEVEL_FINE; 1455 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) || 1456 LocationManager.FUSED_PROVIDER.equals(provider)) { 1457 // network and fused providers are ok with COARSE or FINE 1458 return RESOLUTION_LEVEL_COARSE; 1459 } else { 1460 // mock providers 1461 LocationProviderInterface lp = mMockProviders.get(provider); 1462 if (lp != null) { 1463 ProviderProperties properties = lp.getProperties(); 1464 if (properties != null) { 1465 if (properties.mRequiresSatellite) { 1466 // provider requiring satellites require FINE permission 1467 return RESOLUTION_LEVEL_FINE; 1468 } else if (properties.mRequiresNetwork || properties.mRequiresCell) { 1469 // provider requiring network and or cell require COARSE or FINE 1470 return RESOLUTION_LEVEL_COARSE; 1471 } 1472 } 1473 } 1474 } 1475 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE 1476 } 1477 1478 /** 1479 * Throw SecurityException if specified resolution level is insufficient to use the named 1480 * location provider. 1481 * 1482 * @param allowedResolutionLevel resolution level allowed to caller 1483 * @param providerName the name of the location provider 1484 */ 1485 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel, 1486 String providerName) { 1487 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName); 1488 if (allowedResolutionLevel < requiredResolutionLevel) { 1489 switch (requiredResolutionLevel) { 1490 case RESOLUTION_LEVEL_FINE: 1491 throw new SecurityException("\"" + providerName + "\" location provider " + 1492 "requires ACCESS_FINE_LOCATION permission."); 1493 case RESOLUTION_LEVEL_COARSE: 1494 throw new SecurityException("\"" + providerName + "\" location provider " + 1495 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission."); 1496 default: 1497 throw new SecurityException("Insufficient permission for \"" + providerName + 1498 "\" location provider."); 1499 } 1500 } 1501 } 1502 1503 /** 1504 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages 1505 * for battery). 1506 */ 1507 private void checkDeviceStatsAllowed() { 1508 mContext.enforceCallingOrSelfPermission( 1509 android.Manifest.permission.UPDATE_DEVICE_STATS, null); 1510 } 1511 1512 private void checkUpdateAppOpsAllowed() { 1513 mContext.enforceCallingOrSelfPermission( 1514 android.Manifest.permission.UPDATE_APP_OPS_STATS, null); 1515 } 1516 1517 public static int resolutionLevelToOp(int allowedResolutionLevel) { 1518 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) { 1519 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) { 1520 return AppOpsManager.OP_COARSE_LOCATION; 1521 } else { 1522 return AppOpsManager.OP_FINE_LOCATION; 1523 } 1524 } 1525 return -1; 1526 } 1527 1528 boolean reportLocationAccessNoThrow( 1529 int pid, int uid, String packageName, int allowedResolutionLevel) { 1530 int op = resolutionLevelToOp(allowedResolutionLevel); 1531 if (op >= 0) { 1532 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { 1533 return false; 1534 } 1535 } 1536 1537 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel; 1538 } 1539 1540 boolean checkLocationAccess(int pid, int uid, String packageName, int allowedResolutionLevel) { 1541 int op = resolutionLevelToOp(allowedResolutionLevel); 1542 if (op >= 0) { 1543 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { 1544 return false; 1545 } 1546 } 1547 1548 return getAllowedResolutionLevel(pid, uid) >= allowedResolutionLevel; 1549 } 1550 1551 /** 1552 * Returns all providers by name, including passive, but excluding 1553 * fused, also including ones that are not permitted to 1554 * be accessed by the calling activity or are currently disabled. 1555 */ 1556 @Override 1557 public List<String> getAllProviders() { 1558 List<String> out = getProviders(null /*criteria*/, false /*enabledOnly*/); 1559 if (D) Log.d(TAG, "getAllProviders()=" + out); 1560 return out; 1561 } 1562 1563 /** 1564 * Return all providers by name, that match criteria and are optionally 1565 * enabled. 1566 * Can return passive provider, but never returns fused provider. 1567 */ 1568 @Override 1569 public List<String> getProviders(Criteria criteria, boolean enabledOnly) { 1570 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1571 ArrayList<String> out; 1572 int uid = Binder.getCallingUid(); 1573 long identity = Binder.clearCallingIdentity(); 1574 try { 1575 synchronized (mLock) { 1576 out = new ArrayList<>(mProviders.size()); 1577 for (LocationProviderInterface provider : mProviders) { 1578 String name = provider.getName(); 1579 if (LocationManager.FUSED_PROVIDER.equals(name)) { 1580 continue; 1581 } 1582 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) { 1583 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) { 1584 continue; 1585 } 1586 if (criteria != null && !LocationProvider.propertiesMeetCriteria( 1587 name, provider.getProperties(), criteria)) { 1588 continue; 1589 } 1590 out.add(name); 1591 } 1592 } 1593 } 1594 } finally { 1595 Binder.restoreCallingIdentity(identity); 1596 } 1597 1598 if (D) Log.d(TAG, "getProviders()=" + out); 1599 return out; 1600 } 1601 1602 /** 1603 * Return the name of the best provider given a Criteria object. 1604 * This method has been deprecated from the public API, 1605 * and the whole LocationProvider (including #meetsCriteria) 1606 * has been deprecated as well. So this method now uses 1607 * some simplified logic. 1608 */ 1609 @Override 1610 public String getBestProvider(Criteria criteria, boolean enabledOnly) { 1611 String result = null; 1612 1613 List<String> providers = getProviders(criteria, enabledOnly); 1614 if (!providers.isEmpty()) { 1615 result = pickBest(providers); 1616 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 1617 return result; 1618 } 1619 providers = getProviders(null, enabledOnly); 1620 if (!providers.isEmpty()) { 1621 result = pickBest(providers); 1622 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 1623 return result; 1624 } 1625 1626 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 1627 return null; 1628 } 1629 1630 private String pickBest(List<String> providers) { 1631 if (providers.contains(LocationManager.GPS_PROVIDER)) { 1632 return LocationManager.GPS_PROVIDER; 1633 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) { 1634 return LocationManager.NETWORK_PROVIDER; 1635 } else { 1636 return providers.get(0); 1637 } 1638 } 1639 1640 @Override 1641 public boolean providerMeetsCriteria(String provider, Criteria criteria) { 1642 LocationProviderInterface p = mProvidersByName.get(provider); 1643 if (p == null) { 1644 throw new IllegalArgumentException("provider=" + provider); 1645 } 1646 1647 boolean result = LocationProvider.propertiesMeetCriteria( 1648 p.getName(), p.getProperties(), criteria); 1649 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result); 1650 return result; 1651 } 1652 1653 private void updateProvidersLocked() { 1654 boolean changesMade = false; 1655 for (int i = mProviders.size() - 1; i >= 0; i--) { 1656 LocationProviderInterface p = mProviders.get(i); 1657 boolean isEnabled = p.isEnabled(); 1658 String name = p.getName(); 1659 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name); 1660 if (isEnabled && !shouldBeEnabled) { 1661 updateProviderListenersLocked(name, false); 1662 // If any provider has been disabled, clear all last locations for all providers. 1663 // This is to be on the safe side in case a provider has location derived from 1664 // this disabled provider. 1665 mLastLocation.clear(); 1666 mLastLocationCoarseInterval.clear(); 1667 changesMade = true; 1668 } else if (!isEnabled && shouldBeEnabled) { 1669 updateProviderListenersLocked(name, true); 1670 changesMade = true; 1671 } 1672 } 1673 if (changesMade) { 1674 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION), 1675 UserHandle.ALL); 1676 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION), 1677 UserHandle.ALL); 1678 } 1679 } 1680 1681 private void updateProviderListenersLocked(String provider, boolean enabled) { 1682 int listeners = 0; 1683 1684 LocationProviderInterface p = mProvidersByName.get(provider); 1685 if (p == null) return; 1686 1687 ArrayList<Receiver> deadReceivers = null; 1688 1689 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1690 if (records != null) { 1691 for (UpdateRecord record : records) { 1692 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) { 1693 // Sends a notification message to the receiver 1694 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { 1695 if (deadReceivers == null) { 1696 deadReceivers = new ArrayList<>(); 1697 } 1698 deadReceivers.add(record.mReceiver); 1699 } 1700 listeners++; 1701 } 1702 } 1703 } 1704 1705 if (deadReceivers != null) { 1706 for (int i = deadReceivers.size() - 1; i >= 0; i--) { 1707 removeUpdatesLocked(deadReceivers.get(i)); 1708 } 1709 } 1710 1711 if (enabled) { 1712 p.enable(); 1713 if (listeners > 0) { 1714 applyRequirementsLocked(provider); 1715 } 1716 } else { 1717 p.disable(); 1718 } 1719 } 1720 1721 private void applyRequirementsLocked(String provider) { 1722 LocationProviderInterface p = mProvidersByName.get(provider); 1723 if (p == null) return; 1724 1725 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1726 WorkSource worksource = new WorkSource(); 1727 ProviderRequest providerRequest = new ProviderRequest(); 1728 1729 ContentResolver resolver = mContext.getContentResolver(); 1730 long backgroundThrottleInterval = Settings.Global.getLong( 1731 resolver, 1732 Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, 1733 DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS); 1734 // initialize the low power mode to true and set to false if any of the records requires 1735 1736 providerRequest.lowPowerMode = true; 1737 if (records != null) { 1738 for (UpdateRecord record : records) { 1739 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) { 1740 if (checkLocationAccess( 1741 record.mReceiver.mIdentity.mPid, 1742 record.mReceiver.mIdentity.mUid, 1743 record.mReceiver.mIdentity.mPackageName, 1744 record.mReceiver.mAllowedResolutionLevel)) { 1745 LocationRequest locationRequest = record.mRealRequest; 1746 long interval = locationRequest.getInterval(); 1747 1748 if (!isThrottlingExemptLocked(record.mReceiver.mIdentity)) { 1749 if (!record.mIsForegroundUid) { 1750 interval = Math.max(interval, backgroundThrottleInterval); 1751 } 1752 if (interval != locationRequest.getInterval()) { 1753 locationRequest = new LocationRequest(locationRequest); 1754 locationRequest.setInterval(interval); 1755 } 1756 } 1757 1758 record.mRequest = locationRequest; 1759 providerRequest.locationRequests.add(locationRequest); 1760 if (!locationRequest.isLowPowerMode()) { 1761 providerRequest.lowPowerMode = false; 1762 } 1763 if (interval < providerRequest.interval) { 1764 providerRequest.reportLocation = true; 1765 providerRequest.interval = interval; 1766 } 1767 } 1768 } 1769 } 1770 1771 if (providerRequest.reportLocation) { 1772 // calculate who to blame for power 1773 // This is somewhat arbitrary. We pick a threshold interval 1774 // that is slightly higher that the minimum interval, and 1775 // spread the blame across all applications with a request 1776 // under that threshold. 1777 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; 1778 for (UpdateRecord record : records) { 1779 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) { 1780 LocationRequest locationRequest = record.mRequest; 1781 1782 // Don't assign battery blame for update records whose 1783 // client has no permission to receive location data. 1784 if (!providerRequest.locationRequests.contains(locationRequest)) { 1785 continue; 1786 } 1787 1788 if (locationRequest.getInterval() <= thresholdInterval) { 1789 if (record.mReceiver.mWorkSource != null 1790 && record.mReceiver.mWorkSource.size() > 0 1791 && record.mReceiver.mWorkSource.getName(0) != null) { 1792 // Assign blame to another work source. 1793 // Can only assign blame if the WorkSource contains names. 1794 worksource.add(record.mReceiver.mWorkSource); 1795 } else { 1796 // Assign blame to caller. 1797 worksource.add( 1798 record.mReceiver.mIdentity.mUid, 1799 record.mReceiver.mIdentity.mPackageName); 1800 } 1801 } 1802 } 1803 } 1804 } 1805 } 1806 1807 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); 1808 p.setRequest(providerRequest, worksource); 1809 } 1810 1811 @Override 1812 public String[] getBackgroundThrottlingWhitelist() { 1813 synchronized (mLock) { 1814 return mBackgroundThrottlePackageWhitelist.toArray( 1815 new String[mBackgroundThrottlePackageWhitelist.size()]); 1816 } 1817 } 1818 1819 private void updateBackgroundThrottlingWhitelistLocked() { 1820 String setting = Settings.Global.getString( 1821 mContext.getContentResolver(), 1822 Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST); 1823 if (setting == null) { 1824 setting = ""; 1825 } 1826 1827 mBackgroundThrottlePackageWhitelist.clear(); 1828 mBackgroundThrottlePackageWhitelist.addAll( 1829 SystemConfig.getInstance().getAllowUnthrottledLocation()); 1830 mBackgroundThrottlePackageWhitelist.addAll( 1831 Arrays.asList(setting.split(","))); 1832 } 1833 1834 private boolean isThrottlingExemptLocked(Identity identity) { 1835 if (identity.mUid == Process.SYSTEM_UID) { 1836 return true; 1837 } 1838 1839 if (mBackgroundThrottlePackageWhitelist.contains(identity.mPackageName)) { 1840 return true; 1841 } 1842 1843 for (LocationProviderProxy provider : mProxyProviders) { 1844 if (identity.mPackageName.equals(provider.getConnectedPackageName())) { 1845 return true; 1846 } 1847 } 1848 1849 return false; 1850 } 1851 1852 private class UpdateRecord { 1853 final String mProvider; 1854 final LocationRequest mRealRequest; // original request from client 1855 LocationRequest mRequest; // possibly throttled version of the request 1856 final Receiver mReceiver; 1857 boolean mIsForegroundUid; 1858 Location mLastFixBroadcast; 1859 long mLastStatusBroadcast; 1860 1861 /** 1862 * Note: must be constructed with lock held. 1863 */ 1864 UpdateRecord(String provider, LocationRequest request, Receiver receiver) { 1865 mProvider = provider; 1866 mRealRequest = request; 1867 mRequest = request; 1868 mReceiver = receiver; 1869 mIsForegroundUid = isImportanceForeground( 1870 mActivityManager.getPackageImportance(mReceiver.mIdentity.mPackageName)); 1871 1872 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1873 if (records == null) { 1874 records = new ArrayList<>(); 1875 mRecordsByProvider.put(provider, records); 1876 } 1877 if (!records.contains(this)) { 1878 records.add(this); 1879 } 1880 1881 // Update statistics for historical location requests by package/provider 1882 mRequestStatistics.startRequesting( 1883 mReceiver.mIdentity.mPackageName, provider, request.getInterval()); 1884 } 1885 1886 /** 1887 * Method to be called when a record will no longer be used. 1888 */ 1889 void disposeLocked(boolean removeReceiver) { 1890 mRequestStatistics.stopRequesting(mReceiver.mIdentity.mPackageName, mProvider); 1891 1892 // remove from mRecordsByProvider 1893 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); 1894 if (globalRecords != null) { 1895 globalRecords.remove(this); 1896 } 1897 1898 if (!removeReceiver) return; // the caller will handle the rest 1899 1900 // remove from Receiver#mUpdateRecords 1901 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords; 1902 if (receiverRecords != null) { 1903 receiverRecords.remove(this.mProvider); 1904 1905 // and also remove the Receiver if it has no more update records 1906 if (receiverRecords.size() == 0) { 1907 removeUpdatesLocked(mReceiver); 1908 } 1909 } 1910 } 1911 1912 @Override 1913 public String toString() { 1914 return "UpdateRecord[" + mProvider + " " + mReceiver.mIdentity.mPackageName 1915 + "(" + mReceiver.mIdentity.mUid + (mIsForegroundUid ? " foreground" 1916 : " background") 1917 + ")" + " " + mRealRequest + "]"; 1918 } 1919 } 1920 1921 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid, 1922 String packageName, WorkSource workSource, boolean hideFromAppOps) { 1923 IBinder binder = listener.asBinder(); 1924 Receiver receiver = mReceivers.get(binder); 1925 if (receiver == null) { 1926 receiver = new Receiver(listener, null, pid, uid, packageName, workSource, 1927 hideFromAppOps); 1928 try { 1929 receiver.getListener().asBinder().linkToDeath(receiver, 0); 1930 } catch (RemoteException e) { 1931 Slog.e(TAG, "linkToDeath failed:", e); 1932 return null; 1933 } 1934 mReceivers.put(binder, receiver); 1935 } 1936 return receiver; 1937 } 1938 1939 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName, 1940 WorkSource workSource, boolean hideFromAppOps) { 1941 Receiver receiver = mReceivers.get(intent); 1942 if (receiver == null) { 1943 receiver = new Receiver(null, intent, pid, uid, packageName, workSource, 1944 hideFromAppOps); 1945 mReceivers.put(intent, receiver); 1946 } 1947 return receiver; 1948 } 1949 1950 /** 1951 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution 1952 * and consistency requirements. 1953 * 1954 * @param request the LocationRequest from which to create a sanitized version 1955 * @return a version of request that meets the given resolution and consistency requirements 1956 * @hide 1957 */ 1958 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel, 1959 boolean callerHasLocationHardwarePermission) { 1960 LocationRequest sanitizedRequest = new LocationRequest(request); 1961 if (!callerHasLocationHardwarePermission) { 1962 // allow setting low power mode only for callers with location hardware permission 1963 sanitizedRequest.setLowPowerMode(false); 1964 } 1965 if (resolutionLevel < RESOLUTION_LEVEL_FINE) { 1966 switch (sanitizedRequest.getQuality()) { 1967 case LocationRequest.ACCURACY_FINE: 1968 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK); 1969 break; 1970 case LocationRequest.POWER_HIGH: 1971 sanitizedRequest.setQuality(LocationRequest.POWER_LOW); 1972 break; 1973 } 1974 // throttle 1975 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1976 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS); 1977 } 1978 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1979 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS); 1980 } 1981 } 1982 // make getFastestInterval() the minimum of interval and fastest interval 1983 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) { 1984 request.setFastestInterval(request.getInterval()); 1985 } 1986 return sanitizedRequest; 1987 } 1988 1989 private void checkPackageName(String packageName) { 1990 if (packageName == null) { 1991 throw new SecurityException("invalid package name: " + packageName); 1992 } 1993 int uid = Binder.getCallingUid(); 1994 String[] packages = mPackageManager.getPackagesForUid(uid); 1995 if (packages == null) { 1996 throw new SecurityException("invalid UID " + uid); 1997 } 1998 for (String pkg : packages) { 1999 if (packageName.equals(pkg)) return; 2000 } 2001 throw new SecurityException("invalid package name: " + packageName); 2002 } 2003 2004 private void checkPendingIntent(PendingIntent intent) { 2005 if (intent == null) { 2006 throw new IllegalArgumentException("invalid pending intent: " + intent); 2007 } 2008 } 2009 2010 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent, 2011 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) { 2012 if (intent == null && listener == null) { 2013 throw new IllegalArgumentException("need either listener or intent"); 2014 } else if (intent != null && listener != null) { 2015 throw new IllegalArgumentException("cannot register both listener and intent"); 2016 } else if (intent != null) { 2017 checkPendingIntent(intent); 2018 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps); 2019 } else { 2020 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps); 2021 } 2022 } 2023 2024 @Override 2025 public void requestLocationUpdates(LocationRequest request, ILocationListener listener, 2026 PendingIntent intent, String packageName) { 2027 if (request == null) request = DEFAULT_LOCATION_REQUEST; 2028 checkPackageName(packageName); 2029 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 2030 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 2031 request.getProvider()); 2032 WorkSource workSource = request.getWorkSource(); 2033 if (workSource != null && workSource.size() > 0) { 2034 checkDeviceStatsAllowed(); 2035 } 2036 boolean hideFromAppOps = request.getHideFromAppOps(); 2037 if (hideFromAppOps) { 2038 checkUpdateAppOpsAllowed(); 2039 } 2040 boolean callerHasLocationHardwarePermission = 2041 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE) 2042 == PackageManager.PERMISSION_GRANTED; 2043 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel, 2044 callerHasLocationHardwarePermission); 2045 2046 final int pid = Binder.getCallingPid(); 2047 final int uid = Binder.getCallingUid(); 2048 // providers may use public location API's, need to clear identity 2049 long identity = Binder.clearCallingIdentity(); 2050 try { 2051 // We don't check for MODE_IGNORED here; we will do that when we go to deliver 2052 // a location. 2053 checkLocationAccess(pid, uid, packageName, allowedResolutionLevel); 2054 2055 synchronized (mLock) { 2056 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid, 2057 packageName, workSource, hideFromAppOps); 2058 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName); 2059 } 2060 } finally { 2061 Binder.restoreCallingIdentity(identity); 2062 } 2063 } 2064 2065 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, 2066 int pid, int uid, String packageName) { 2067 // Figure out the provider. Either its explicitly request (legacy use cases), or 2068 // use the fused provider 2069 if (request == null) request = DEFAULT_LOCATION_REQUEST; 2070 String name = request.getProvider(); 2071 if (name == null) { 2072 throw new IllegalArgumentException("provider name must not be null"); 2073 } 2074 2075 LocationProviderInterface provider = mProvidersByName.get(name); 2076 if (provider == null) { 2077 throw new IllegalArgumentException("provider doesn't exist: " + name); 2078 } 2079 2080 UpdateRecord record = new UpdateRecord(name, request, receiver); 2081 if (D) { 2082 Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) 2083 + " " + name + " " + request + " from " + packageName + "(" + uid + " " 2084 + (record.mIsForegroundUid ? "foreground" : "background") 2085 + (isThrottlingExemptLocked(receiver.mIdentity) 2086 ? " [whitelisted]" : "") + ")"); 2087 } 2088 2089 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record); 2090 if (oldRecord != null) { 2091 oldRecord.disposeLocked(false); 2092 } 2093 2094 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid); 2095 if (isProviderEnabled) { 2096 applyRequirementsLocked(name); 2097 } else { 2098 // Notify the listener that updates are currently disabled 2099 receiver.callProviderEnabledLocked(name, false); 2100 } 2101 // Update the monitoring here just in case multiple location requests were added to the 2102 // same receiver (this request may be high power and the initial might not have been). 2103 receiver.updateMonitoring(true); 2104 } 2105 2106 @Override 2107 public void removeUpdates(ILocationListener listener, PendingIntent intent, 2108 String packageName) { 2109 checkPackageName(packageName); 2110 2111 final int pid = Binder.getCallingPid(); 2112 final int uid = Binder.getCallingUid(); 2113 2114 synchronized (mLock) { 2115 WorkSource workSource = null; 2116 boolean hideFromAppOps = false; 2117 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid, 2118 packageName, workSource, hideFromAppOps); 2119 2120 // providers may use public location API's, need to clear identity 2121 long identity = Binder.clearCallingIdentity(); 2122 try { 2123 removeUpdatesLocked(receiver); 2124 } finally { 2125 Binder.restoreCallingIdentity(identity); 2126 } 2127 } 2128 } 2129 2130 private void removeUpdatesLocked(Receiver receiver) { 2131 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver))); 2132 2133 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 2134 receiver.getListener().asBinder().unlinkToDeath(receiver, 0); 2135 synchronized (receiver) { 2136 receiver.clearPendingBroadcastsLocked(); 2137 } 2138 } 2139 2140 receiver.updateMonitoring(false); 2141 2142 // Record which providers were associated with this listener 2143 HashSet<String> providers = new HashSet<>(); 2144 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords; 2145 if (oldRecords != null) { 2146 // Call dispose() on the obsolete update records. 2147 for (UpdateRecord record : oldRecords.values()) { 2148 // Update statistics for historical location requests by package/provider 2149 record.disposeLocked(false); 2150 } 2151 // Accumulate providers 2152 providers.addAll(oldRecords.keySet()); 2153 } 2154 2155 // update provider 2156 for (String provider : providers) { 2157 // If provider is already disabled, don't need to do anything 2158 if (!isAllowedByCurrentUserSettingsLocked(provider)) { 2159 continue; 2160 } 2161 2162 applyRequirementsLocked(provider); 2163 } 2164 } 2165 2166 private void applyAllProviderRequirementsLocked() { 2167 for (LocationProviderInterface p : mProviders) { 2168 // If provider is already disabled, don't need to do anything 2169 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) { 2170 continue; 2171 } 2172 2173 applyRequirementsLocked(p.getName()); 2174 } 2175 } 2176 2177 @Override 2178 public Location getLastLocation(LocationRequest request, String packageName) { 2179 if (D) Log.d(TAG, "getLastLocation: " + request); 2180 if (request == null) request = DEFAULT_LOCATION_REQUEST; 2181 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 2182 checkPackageName(packageName); 2183 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 2184 request.getProvider()); 2185 // no need to sanitize this request, as only the provider name is used 2186 2187 final int pid = Binder.getCallingPid(); 2188 final int uid = Binder.getCallingUid(); 2189 final long identity = Binder.clearCallingIdentity(); 2190 try { 2191 if (mBlacklist.isBlacklisted(packageName)) { 2192 if (D) { 2193 Log.d(TAG, "not returning last loc for blacklisted app: " + 2194 packageName); 2195 } 2196 return null; 2197 } 2198 2199 if (!reportLocationAccessNoThrow(pid, uid, packageName, allowedResolutionLevel)) { 2200 if (D) { 2201 Log.d(TAG, "not returning last loc for no op app: " + 2202 packageName); 2203 } 2204 return null; 2205 } 2206 2207 synchronized (mLock) { 2208 // Figure out the provider. Either its explicitly request (deprecated API's), 2209 // or use the fused provider 2210 String name = request.getProvider(); 2211 if (name == null) name = LocationManager.FUSED_PROVIDER; 2212 LocationProviderInterface provider = mProvidersByName.get(name); 2213 if (provider == null) return null; 2214 2215 if (!isAllowedByUserSettingsLocked(name, uid)) return null; 2216 2217 Location location; 2218 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2219 // Make sure that an app with coarse permissions can't get frequent location 2220 // updates by calling LocationManager.getLastKnownLocation repeatedly. 2221 location = mLastLocationCoarseInterval.get(name); 2222 } else { 2223 location = mLastLocation.get(name); 2224 } 2225 if (location == null) { 2226 return null; 2227 } 2228 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2229 Location noGPSLocation = location.getExtraLocation( 2230 Location.EXTRA_NO_GPS_LOCATION); 2231 if (noGPSLocation != null) { 2232 return new Location(mLocationFudger.getOrCreate(noGPSLocation)); 2233 } 2234 } else { 2235 return new Location(location); 2236 } 2237 } 2238 return null; 2239 } finally { 2240 Binder.restoreCallingIdentity(identity); 2241 } 2242 } 2243 2244 @Override 2245 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, 2246 String packageName) { 2247 if (request == null) request = DEFAULT_LOCATION_REQUEST; 2248 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 2249 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel); 2250 checkPendingIntent(intent); 2251 checkPackageName(packageName); 2252 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 2253 request.getProvider()); 2254 // Require that caller can manage given document 2255 boolean callerHasLocationHardwarePermission = 2256 mContext.checkCallingPermission(android.Manifest.permission.LOCATION_HARDWARE) 2257 == PackageManager.PERMISSION_GRANTED; 2258 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel, 2259 callerHasLocationHardwarePermission); 2260 2261 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent); 2262 2263 // geo-fence manager uses the public location API, need to clear identity 2264 int uid = Binder.getCallingUid(); 2265 // TODO: http://b/23822629 2266 if (UserHandle.getUserId(uid) != UserHandle.USER_SYSTEM) { 2267 // temporary measure until geofences work for secondary users 2268 Log.w(TAG, "proximity alerts are currently available only to the primary user"); 2269 return; 2270 } 2271 long identity = Binder.clearCallingIdentity(); 2272 try { 2273 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel, 2274 uid, packageName); 2275 } finally { 2276 Binder.restoreCallingIdentity(identity); 2277 } 2278 } 2279 2280 @Override 2281 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { 2282 checkPendingIntent(intent); 2283 checkPackageName(packageName); 2284 2285 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); 2286 2287 // geo-fence manager uses the public location API, need to clear identity 2288 long identity = Binder.clearCallingIdentity(); 2289 try { 2290 mGeofenceManager.removeFence(geofence, intent); 2291 } finally { 2292 Binder.restoreCallingIdentity(identity); 2293 } 2294 } 2295 2296 2297 @Override 2298 public boolean registerGnssStatusCallback(IGnssStatusListener callback, String packageName) { 2299 if (!hasGnssPermissions(packageName) || mGnssStatusProvider == null) { 2300 return false; 2301 } 2302 2303 try { 2304 mGnssStatusProvider.registerGnssStatusCallback(callback); 2305 } catch (RemoteException e) { 2306 Slog.e(TAG, "mGpsStatusProvider.registerGnssStatusCallback failed", e); 2307 return false; 2308 } 2309 return true; 2310 } 2311 2312 @Override 2313 public void unregisterGnssStatusCallback(IGnssStatusListener callback) { 2314 synchronized (mLock) { 2315 try { 2316 mGnssStatusProvider.unregisterGnssStatusCallback(callback); 2317 } catch (Exception e) { 2318 Slog.e(TAG, "mGpsStatusProvider.unregisterGnssStatusCallback failed", e); 2319 } 2320 } 2321 } 2322 2323 @Override 2324 public boolean addGnssMeasurementsListener( 2325 IGnssMeasurementsListener listener, String packageName) { 2326 if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) { 2327 return false; 2328 } 2329 2330 synchronized (mLock) { 2331 Identity callerIdentity 2332 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName); 2333 mGnssMeasurementsListeners.put(listener, callerIdentity); 2334 long identity = Binder.clearCallingIdentity(); 2335 try { 2336 if (isThrottlingExemptLocked(callerIdentity) 2337 || isImportanceForeground( 2338 mActivityManager.getPackageImportance(packageName))) { 2339 return mGnssMeasurementsProvider.addListener(listener); 2340 } 2341 } finally { 2342 Binder.restoreCallingIdentity(identity); 2343 } 2344 2345 return true; 2346 } 2347 } 2348 2349 @Override 2350 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { 2351 if (mGnssMeasurementsProvider != null) { 2352 synchronized (mLock) { 2353 mGnssMeasurementsListeners.remove(listener); 2354 mGnssMeasurementsProvider.removeListener(listener); 2355 } 2356 } 2357 } 2358 2359 @Override 2360 public boolean addGnssNavigationMessageListener( 2361 IGnssNavigationMessageListener listener, 2362 String packageName) { 2363 if (!hasGnssPermissions(packageName) || mGnssNavigationMessageProvider == null) { 2364 return false; 2365 } 2366 2367 synchronized (mLock) { 2368 Identity callerIdentity 2369 = new Identity(Binder.getCallingUid(), Binder.getCallingPid(), packageName); 2370 mGnssNavigationMessageListeners.put(listener, callerIdentity); 2371 long identity = Binder.clearCallingIdentity(); 2372 try { 2373 if (isThrottlingExemptLocked(callerIdentity) 2374 || isImportanceForeground( 2375 mActivityManager.getPackageImportance(packageName))) { 2376 return mGnssNavigationMessageProvider.addListener(listener); 2377 } 2378 } finally { 2379 Binder.restoreCallingIdentity(identity); 2380 } 2381 2382 return true; 2383 } 2384 } 2385 2386 @Override 2387 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { 2388 if (mGnssNavigationMessageProvider != null) { 2389 synchronized (mLock) { 2390 mGnssNavigationMessageListeners.remove(listener); 2391 mGnssNavigationMessageProvider.removeListener(listener); 2392 } 2393 } 2394 } 2395 2396 @Override 2397 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 2398 if (provider == null) { 2399 // throw NullPointerException to remain compatible with previous implementation 2400 throw new NullPointerException(); 2401 } 2402 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 2403 provider); 2404 2405 // and check for ACCESS_LOCATION_EXTRA_COMMANDS 2406 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 2407 != PackageManager.PERMISSION_GRANTED)) { 2408 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 2409 } 2410 2411 synchronized (mLock) { 2412 LocationProviderInterface p = mProvidersByName.get(provider); 2413 if (p == null) return false; 2414 2415 return p.sendExtraCommand(command, extras); 2416 } 2417 } 2418 2419 @Override 2420 public boolean sendNiResponse(int notifId, int userResponse) { 2421 if (Binder.getCallingUid() != Process.myUid()) { 2422 throw new SecurityException( 2423 "calling sendNiResponse from outside of the system is not allowed"); 2424 } 2425 try { 2426 return mNetInitiatedListener.sendNiResponse(notifId, userResponse); 2427 } catch (RemoteException e) { 2428 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); 2429 return false; 2430 } 2431 } 2432 2433 /** 2434 * @return null if the provider does not exist 2435 * @throws SecurityException if the provider is not allowed to be 2436 * accessed by the caller 2437 */ 2438 @Override 2439 public ProviderProperties getProviderProperties(String provider) { 2440 if (mProvidersByName.get(provider) == null) { 2441 return null; 2442 } 2443 2444 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 2445 provider); 2446 2447 LocationProviderInterface p; 2448 synchronized (mLock) { 2449 p = mProvidersByName.get(provider); 2450 } 2451 2452 if (p == null) return null; 2453 return p.getProperties(); 2454 } 2455 2456 /** 2457 * @return null if the provider does not exist 2458 * @throws SecurityException if the provider is not allowed to be 2459 * accessed by the caller 2460 */ 2461 @Override 2462 public String getNetworkProviderPackage() { 2463 LocationProviderInterface p; 2464 synchronized (mLock) { 2465 if (mProvidersByName.get(LocationManager.NETWORK_PROVIDER) == null) { 2466 return null; 2467 } 2468 p = mProvidersByName.get(LocationManager.NETWORK_PROVIDER); 2469 } 2470 2471 if (p instanceof LocationProviderProxy) { 2472 return ((LocationProviderProxy) p).getConnectedPackageName(); 2473 } 2474 return null; 2475 } 2476 2477 @Override 2478 public boolean isProviderEnabled(String provider) { 2479 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, 2480 // so we discourage its use 2481 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 2482 2483 int uid = Binder.getCallingUid(); 2484 long identity = Binder.clearCallingIdentity(); 2485 try { 2486 synchronized (mLock) { 2487 LocationProviderInterface p = mProvidersByName.get(provider); 2488 return p != null && isAllowedByUserSettingsLocked(provider, uid); 2489 } 2490 } finally { 2491 Binder.restoreCallingIdentity(identity); 2492 } 2493 } 2494 2495 /** 2496 * Returns "true" if the UID belongs to a bound location provider. 2497 * 2498 * @param uid the uid 2499 * @return true if uid belongs to a bound location provider 2500 */ 2501 private boolean isUidALocationProvider(int uid) { 2502 if (uid == Process.SYSTEM_UID) { 2503 return true; 2504 } 2505 if (mGeocodeProvider != null) { 2506 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true; 2507 } 2508 for (LocationProviderProxy proxy : mProxyProviders) { 2509 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true; 2510 } 2511 return false; 2512 } 2513 2514 private void checkCallerIsProvider() { 2515 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 2516 == PackageManager.PERMISSION_GRANTED) { 2517 return; 2518 } 2519 2520 // Previously we only used the INSTALL_LOCATION_PROVIDER 2521 // check. But that is system or signature 2522 // protection level which is not flexible enough for 2523 // providers installed oustide the system image. So 2524 // also allow providers with a UID matching the 2525 // currently bound package name 2526 2527 if (isUidALocationProvider(Binder.getCallingUid())) { 2528 return; 2529 } 2530 2531 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 2532 "or UID of a currently bound location provider"); 2533 } 2534 2535 /** 2536 * Returns true if the given package belongs to the given uid. 2537 */ 2538 private boolean doesUidHavePackage(int uid, String packageName) { 2539 if (packageName == null) { 2540 return false; 2541 } 2542 String[] packageNames = mPackageManager.getPackagesForUid(uid); 2543 if (packageNames == null) { 2544 return false; 2545 } 2546 for (String name : packageNames) { 2547 if (packageName.equals(name)) { 2548 return true; 2549 } 2550 } 2551 return false; 2552 } 2553 2554 @Override 2555 public void reportLocation(Location location, boolean passive) { 2556 checkCallerIsProvider(); 2557 2558 if (!location.isComplete()) { 2559 Log.w(TAG, "Dropping incomplete location: " + location); 2560 return; 2561 } 2562 2563 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 2564 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 2565 m.arg1 = (passive ? 1 : 0); 2566 mLocationHandler.sendMessageAtFrontOfQueue(m); 2567 } 2568 2569 2570 private static boolean shouldBroadcastSafe( 2571 Location loc, Location lastLoc, UpdateRecord record, long now) { 2572 // Always broadcast the first update 2573 if (lastLoc == null) { 2574 return true; 2575 } 2576 2577 // Check whether sufficient time has passed 2578 long minTime = record.mRealRequest.getFastestInterval(); 2579 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) 2580 / NANOS_PER_MILLI; 2581 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 2582 return false; 2583 } 2584 2585 // Check whether sufficient distance has been traveled 2586 double minDistance = record.mRealRequest.getSmallestDisplacement(); 2587 if (minDistance > 0.0) { 2588 if (loc.distanceTo(lastLoc) <= minDistance) { 2589 return false; 2590 } 2591 } 2592 2593 // Check whether sufficient number of udpates is left 2594 if (record.mRealRequest.getNumUpdates() <= 0) { 2595 return false; 2596 } 2597 2598 // Check whether the expiry date has passed 2599 return record.mRealRequest.getExpireAt() >= now; 2600 } 2601 2602 private void handleLocationChangedLocked(Location location, boolean passive) { 2603 if (D) Log.d(TAG, "incoming location: " + location); 2604 2605 long now = SystemClock.elapsedRealtime(); 2606 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 2607 2608 // Skip if the provider is unknown. 2609 LocationProviderInterface p = mProvidersByName.get(provider); 2610 if (p == null) return; 2611 2612 // Update last known locations 2613 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2614 Location lastNoGPSLocation; 2615 Location lastLocation = mLastLocation.get(provider); 2616 if (lastLocation == null) { 2617 lastLocation = new Location(provider); 2618 mLastLocation.put(provider, lastLocation); 2619 } else { 2620 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2621 if (noGPSLocation == null && lastNoGPSLocation != null) { 2622 // New location has no no-GPS location: adopt last no-GPS location. This is set 2623 // directly into location because we do not want to notify COARSE clients. 2624 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 2625 } 2626 } 2627 lastLocation.set(location); 2628 2629 // Update last known coarse interval location if enough time has passed. 2630 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider); 2631 if (lastLocationCoarseInterval == null) { 2632 lastLocationCoarseInterval = new Location(location); 2633 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval); 2634 } 2635 long timeDiffNanos = location.getElapsedRealtimeNanos() 2636 - lastLocationCoarseInterval.getElapsedRealtimeNanos(); 2637 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) { 2638 lastLocationCoarseInterval.set(location); 2639 } 2640 // Don't ever return a coarse location that is more recent than the allowed update 2641 // interval (i.e. don't allow an app to keep registering and unregistering for 2642 // location updates to overcome the minimum interval). 2643 noGPSLocation = 2644 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2645 2646 // Skip if there are no UpdateRecords for this provider. 2647 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 2648 if (records == null || records.size() == 0) return; 2649 2650 // Fetch coarse location 2651 Location coarseLocation = null; 2652 if (noGPSLocation != null) { 2653 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 2654 } 2655 2656 // Fetch latest status update time 2657 long newStatusUpdateTime = p.getStatusUpdateTime(); 2658 2659 // Get latest status 2660 Bundle extras = new Bundle(); 2661 int status = p.getStatus(extras); 2662 2663 ArrayList<Receiver> deadReceivers = null; 2664 ArrayList<UpdateRecord> deadUpdateRecords = null; 2665 2666 // Broadcast location or status to all listeners 2667 for (UpdateRecord r : records) { 2668 Receiver receiver = r.mReceiver; 2669 boolean receiverDead = false; 2670 2671 int receiverUserId = UserHandle.getUserId(receiver.mIdentity.mUid); 2672 if (!isCurrentProfile(receiverUserId) 2673 && !isUidALocationProvider(receiver.mIdentity.mUid)) { 2674 if (D) { 2675 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 2676 " (current user: " + mCurrentUserId + ", app: " + 2677 receiver.mIdentity.mPackageName + ")"); 2678 } 2679 continue; 2680 } 2681 2682 if (mBlacklist.isBlacklisted(receiver.mIdentity.mPackageName)) { 2683 if (D) { 2684 Log.d(TAG, "skipping loc update for blacklisted app: " + 2685 receiver.mIdentity.mPackageName); 2686 } 2687 continue; 2688 } 2689 2690 if (!reportLocationAccessNoThrow( 2691 receiver.mIdentity.mPid, 2692 receiver.mIdentity.mUid, 2693 receiver.mIdentity.mPackageName, 2694 receiver.mAllowedResolutionLevel)) { 2695 if (D) { 2696 Log.d(TAG, "skipping loc update for no op app: " + 2697 receiver.mIdentity.mPackageName); 2698 } 2699 continue; 2700 } 2701 2702 Location notifyLocation; 2703 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2704 notifyLocation = coarseLocation; // use coarse location 2705 } else { 2706 notifyLocation = lastLocation; // use fine location 2707 } 2708 if (notifyLocation != null) { 2709 Location lastLoc = r.mLastFixBroadcast; 2710 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) { 2711 if (lastLoc == null) { 2712 lastLoc = new Location(notifyLocation); 2713 r.mLastFixBroadcast = lastLoc; 2714 } else { 2715 lastLoc.set(notifyLocation); 2716 } 2717 if (!receiver.callLocationChangedLocked(notifyLocation)) { 2718 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 2719 receiverDead = true; 2720 } 2721 r.mRealRequest.decrementNumUpdates(); 2722 } 2723 } 2724 2725 long prevStatusUpdateTime = r.mLastStatusBroadcast; 2726 if ((newStatusUpdateTime > prevStatusUpdateTime) && 2727 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 2728 2729 r.mLastStatusBroadcast = newStatusUpdateTime; 2730 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 2731 receiverDead = true; 2732 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 2733 } 2734 } 2735 2736 // track expired records 2737 if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) { 2738 if (deadUpdateRecords == null) { 2739 deadUpdateRecords = new ArrayList<>(); 2740 } 2741 deadUpdateRecords.add(r); 2742 } 2743 // track dead receivers 2744 if (receiverDead) { 2745 if (deadReceivers == null) { 2746 deadReceivers = new ArrayList<>(); 2747 } 2748 if (!deadReceivers.contains(receiver)) { 2749 deadReceivers.add(receiver); 2750 } 2751 } 2752 } 2753 2754 // remove dead records and receivers outside the loop 2755 if (deadReceivers != null) { 2756 for (Receiver receiver : deadReceivers) { 2757 removeUpdatesLocked(receiver); 2758 } 2759 } 2760 if (deadUpdateRecords != null) { 2761 for (UpdateRecord r : deadUpdateRecords) { 2762 r.disposeLocked(true); 2763 } 2764 applyRequirementsLocked(provider); 2765 } 2766 } 2767 2768 private class LocationWorkerHandler extends Handler { 2769 public LocationWorkerHandler(Looper looper) { 2770 super(looper, null, true); 2771 } 2772 2773 @Override 2774 public void handleMessage(Message msg) { 2775 switch (msg.what) { 2776 case MSG_LOCATION_CHANGED: 2777 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 2778 break; 2779 } 2780 } 2781 } 2782 2783 private boolean isMockProvider(String provider) { 2784 synchronized (mLock) { 2785 return mMockProviders.containsKey(provider); 2786 } 2787 } 2788 2789 private void handleLocationChanged(Location location, boolean passive) { 2790 // create a working copy of the incoming Location so that the service can modify it without 2791 // disturbing the caller's copy 2792 Location myLocation = new Location(location); 2793 String provider = myLocation.getProvider(); 2794 2795 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this 2796 // bit if location did not come from a mock provider because passive/fused providers can 2797 // forward locations from mock providers, and should not grant them legitimacy in doing so. 2798 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) { 2799 myLocation.setIsFromMockProvider(true); 2800 } 2801 2802 synchronized (mLock) { 2803 if (isAllowedByCurrentUserSettingsLocked(provider)) { 2804 if (!passive) { 2805 // notify passive provider of the new location 2806 mPassiveProvider.updateLocation(myLocation); 2807 } 2808 handleLocationChangedLocked(myLocation, passive); 2809 } 2810 } 2811 } 2812 2813 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 2814 @Override 2815 public void onPackageDisappeared(String packageName, int reason) { 2816 // remove all receivers associated with this package name 2817 synchronized (mLock) { 2818 ArrayList<Receiver> deadReceivers = null; 2819 2820 for (Receiver receiver : mReceivers.values()) { 2821 if (receiver.mIdentity.mPackageName.equals(packageName)) { 2822 if (deadReceivers == null) { 2823 deadReceivers = new ArrayList<>(); 2824 } 2825 deadReceivers.add(receiver); 2826 } 2827 } 2828 2829 // perform removal outside of mReceivers loop 2830 if (deadReceivers != null) { 2831 for (Receiver receiver : deadReceivers) { 2832 removeUpdatesLocked(receiver); 2833 } 2834 } 2835 } 2836 } 2837 }; 2838 2839 // Geocoder 2840 2841 @Override 2842 public boolean geocoderIsPresent() { 2843 return mGeocodeProvider != null; 2844 } 2845 2846 @Override 2847 public String getFromLocation(double latitude, double longitude, int maxResults, 2848 GeocoderParams params, List<Address> addrs) { 2849 if (mGeocodeProvider != null) { 2850 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 2851 params, addrs); 2852 } 2853 return null; 2854 } 2855 2856 2857 @Override 2858 public String getFromLocationName(String locationName, 2859 double lowerLeftLatitude, double lowerLeftLongitude, 2860 double upperRightLatitude, double upperRightLongitude, int maxResults, 2861 GeocoderParams params, List<Address> addrs) { 2862 2863 if (mGeocodeProvider != null) { 2864 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 2865 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 2866 maxResults, params, addrs); 2867 } 2868 return null; 2869 } 2870 2871 // Mock Providers 2872 2873 private boolean canCallerAccessMockLocation(String opPackageName) { 2874 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), 2875 opPackageName) == AppOpsManager.MODE_ALLOWED; 2876 } 2877 2878 @Override 2879 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) { 2880 if (!canCallerAccessMockLocation(opPackageName)) { 2881 return; 2882 } 2883 2884 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 2885 throw new IllegalArgumentException("Cannot mock the passive location provider"); 2886 } 2887 2888 long identity = Binder.clearCallingIdentity(); 2889 synchronized (mLock) { 2890 // remove the real provider if we are replacing GPS or network provider 2891 if (LocationManager.GPS_PROVIDER.equals(name) 2892 || LocationManager.NETWORK_PROVIDER.equals(name) 2893 || LocationManager.FUSED_PROVIDER.equals(name)) { 2894 LocationProviderInterface p = mProvidersByName.get(name); 2895 if (p != null) { 2896 removeProviderLocked(p); 2897 } 2898 } 2899 addTestProviderLocked(name, properties); 2900 updateProvidersLocked(); 2901 } 2902 Binder.restoreCallingIdentity(identity); 2903 } 2904 2905 private void addTestProviderLocked(String name, ProviderProperties properties) { 2906 if (mProvidersByName.get(name) != null) { 2907 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 2908 } 2909 MockProvider provider = new MockProvider(name, this, properties); 2910 addProviderLocked(provider); 2911 mMockProviders.put(name, provider); 2912 mLastLocation.put(name, null); 2913 mLastLocationCoarseInterval.put(name, null); 2914 } 2915 2916 @Override 2917 public void removeTestProvider(String provider, String opPackageName) { 2918 if (!canCallerAccessMockLocation(opPackageName)) { 2919 return; 2920 } 2921 2922 synchronized (mLock) { 2923 2924 // These methods can't be called after removing the test provider, so first make sure 2925 // we don't leave anything dangling. 2926 clearTestProviderEnabled(provider, opPackageName); 2927 clearTestProviderLocation(provider, opPackageName); 2928 clearTestProviderStatus(provider, opPackageName); 2929 2930 MockProvider mockProvider = mMockProviders.remove(provider); 2931 if (mockProvider == null) { 2932 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2933 } 2934 long identity = Binder.clearCallingIdentity(); 2935 removeProviderLocked(mProvidersByName.get(provider)); 2936 2937 // reinstate real provider if available 2938 LocationProviderInterface realProvider = mRealProviders.get(provider); 2939 if (realProvider != null) { 2940 addProviderLocked(realProvider); 2941 } 2942 mLastLocation.put(provider, null); 2943 mLastLocationCoarseInterval.put(provider, null); 2944 updateProvidersLocked(); 2945 Binder.restoreCallingIdentity(identity); 2946 } 2947 } 2948 2949 @Override 2950 public void setTestProviderLocation(String provider, Location loc, String opPackageName) { 2951 if (!canCallerAccessMockLocation(opPackageName)) { 2952 return; 2953 } 2954 2955 synchronized (mLock) { 2956 MockProvider mockProvider = mMockProviders.get(provider); 2957 if (mockProvider == null) { 2958 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2959 } 2960 2961 // Ensure that the location is marked as being mock. There's some logic to do this in 2962 // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107). 2963 Location mock = new Location(loc); 2964 mock.setIsFromMockProvider(true); 2965 2966 if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) { 2967 // The location has an explicit provider that is different from the mock provider 2968 // name. The caller may be trying to fool us via bug 33091107. 2969 EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(), 2970 provider + "!=" + loc.getProvider()); 2971 } 2972 2973 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 2974 long identity = Binder.clearCallingIdentity(); 2975 mockProvider.setLocation(mock); 2976 Binder.restoreCallingIdentity(identity); 2977 } 2978 } 2979 2980 @Override 2981 public void clearTestProviderLocation(String provider, String opPackageName) { 2982 if (!canCallerAccessMockLocation(opPackageName)) { 2983 return; 2984 } 2985 2986 synchronized (mLock) { 2987 MockProvider mockProvider = mMockProviders.get(provider); 2988 if (mockProvider == null) { 2989 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2990 } 2991 mockProvider.clearLocation(); 2992 } 2993 } 2994 2995 @Override 2996 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) { 2997 if (!canCallerAccessMockLocation(opPackageName)) { 2998 return; 2999 } 3000 3001 synchronized (mLock) { 3002 MockProvider mockProvider = mMockProviders.get(provider); 3003 if (mockProvider == null) { 3004 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 3005 } 3006 long identity = Binder.clearCallingIdentity(); 3007 if (enabled) { 3008 mockProvider.enable(); 3009 mEnabledProviders.add(provider); 3010 mDisabledProviders.remove(provider); 3011 } else { 3012 mockProvider.disable(); 3013 mEnabledProviders.remove(provider); 3014 mDisabledProviders.add(provider); 3015 } 3016 updateProvidersLocked(); 3017 Binder.restoreCallingIdentity(identity); 3018 } 3019 } 3020 3021 @Override 3022 public void clearTestProviderEnabled(String provider, String opPackageName) { 3023 if (!canCallerAccessMockLocation(opPackageName)) { 3024 return; 3025 } 3026 3027 synchronized (mLock) { 3028 MockProvider mockProvider = mMockProviders.get(provider); 3029 if (mockProvider == null) { 3030 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 3031 } 3032 long identity = Binder.clearCallingIdentity(); 3033 mEnabledProviders.remove(provider); 3034 mDisabledProviders.remove(provider); 3035 updateProvidersLocked(); 3036 Binder.restoreCallingIdentity(identity); 3037 } 3038 } 3039 3040 @Override 3041 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime, 3042 String opPackageName) { 3043 if (!canCallerAccessMockLocation(opPackageName)) { 3044 return; 3045 } 3046 3047 synchronized (mLock) { 3048 MockProvider mockProvider = mMockProviders.get(provider); 3049 if (mockProvider == null) { 3050 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 3051 } 3052 mockProvider.setStatus(status, extras, updateTime); 3053 } 3054 } 3055 3056 @Override 3057 public void clearTestProviderStatus(String provider, String opPackageName) { 3058 if (!canCallerAccessMockLocation(opPackageName)) { 3059 return; 3060 } 3061 3062 synchronized (mLock) { 3063 MockProvider mockProvider = mMockProviders.get(provider); 3064 if (mockProvider == null) { 3065 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 3066 } 3067 mockProvider.clearStatus(); 3068 } 3069 } 3070 3071 private void log(String log) { 3072 if (Log.isLoggable(TAG, Log.VERBOSE)) { 3073 Slog.d(TAG, log); 3074 } 3075 } 3076 3077 @Override 3078 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 3079 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 3080 3081 synchronized (mLock) { 3082 if (args.length > 0 && args[0].equals("--gnssmetrics")) { 3083 if (mGnssMetricsProvider != null) { 3084 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString()); 3085 } 3086 return; 3087 } 3088 pw.println("Current Location Manager state:"); 3089 pw.println(" Location Listeners:"); 3090 for (Receiver receiver : mReceivers.values()) { 3091 pw.println(" " + receiver); 3092 } 3093 pw.println(" Active Records by Provider:"); 3094 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 3095 pw.println(" " + entry.getKey() + ":"); 3096 for (UpdateRecord record : entry.getValue()) { 3097 pw.println(" " + record); 3098 } 3099 } 3100 pw.println(" Overlay Provider Packages:"); 3101 for (LocationProviderInterface provider : mProviders) { 3102 if (provider instanceof LocationProviderProxy) { 3103 pw.println(" " + provider.getName() + ": " 3104 + ((LocationProviderProxy) provider).getConnectedPackageName()); 3105 } 3106 } 3107 pw.println(" Historical Records by Provider:"); 3108 for (Map.Entry<PackageProviderKey, PackageStatistics> entry 3109 : mRequestStatistics.statistics.entrySet()) { 3110 PackageProviderKey key = entry.getKey(); 3111 PackageStatistics stats = entry.getValue(); 3112 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats); 3113 } 3114 pw.println(" Last Known Locations:"); 3115 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 3116 String provider = entry.getKey(); 3117 Location location = entry.getValue(); 3118 pw.println(" " + provider + ": " + location); 3119 } 3120 3121 pw.println(" Last Known Locations Coarse Intervals:"); 3122 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) { 3123 String provider = entry.getKey(); 3124 Location location = entry.getValue(); 3125 pw.println(" " + provider + ": " + location); 3126 } 3127 3128 mGeofenceManager.dump(pw); 3129 3130 if (mEnabledProviders.size() > 0) { 3131 pw.println(" Enabled Providers:"); 3132 for (String i : mEnabledProviders) { 3133 pw.println(" " + i); 3134 } 3135 3136 } 3137 if (mDisabledProviders.size() > 0) { 3138 pw.println(" Disabled Providers:"); 3139 for (String i : mDisabledProviders) { 3140 pw.println(" " + i); 3141 } 3142 } 3143 pw.append(" "); 3144 mBlacklist.dump(pw); 3145 if (mMockProviders.size() > 0) { 3146 pw.println(" Mock Providers:"); 3147 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 3148 i.getValue().dump(pw, " "); 3149 } 3150 } 3151 3152 if (!mBackgroundThrottlePackageWhitelist.isEmpty()) { 3153 pw.println(" Throttling Whitelisted Packages:"); 3154 for (String packageName : mBackgroundThrottlePackageWhitelist) { 3155 pw.println(" " + packageName); 3156 } 3157 } 3158 3159 pw.append(" fudger: "); 3160 mLocationFudger.dump(fd, pw, args); 3161 3162 if (args.length > 0 && "short".equals(args[0])) { 3163 return; 3164 } 3165 for (LocationProviderInterface provider : mProviders) { 3166 pw.print(provider.getName() + " Internal State"); 3167 if (provider instanceof LocationProviderProxy) { 3168 LocationProviderProxy proxy = (LocationProviderProxy) provider; 3169 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 3170 } 3171 pw.println(":"); 3172 provider.dump(fd, pw, args); 3173 } 3174 if (mGnssBatchingInProgress) { 3175 pw.println(" GNSS batching in progress"); 3176 } 3177 } 3178 } 3179} 3180