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