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