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