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