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