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