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