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