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