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