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