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