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