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