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