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