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