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