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