LocationManagerService.java revision 8e4799ad456c972cc340d3f484afd69b2f14a761
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.IGpsGeofenceHardware; 64import android.location.IGpsMeasurementsListener; 65import android.location.IGpsNavigationMessageListener; 66import android.location.IGpsStatusListener; 67import android.location.IGpsStatusProvider; 68import android.location.ILocationListener; 69import android.location.ILocationManager; 70import android.location.INetInitiatedListener; 71import android.location.Location; 72import android.location.LocationManager; 73import android.location.LocationProvider; 74import android.location.LocationRequest; 75import android.os.Binder; 76import android.os.Bundle; 77import android.os.Handler; 78import android.os.IBinder; 79import android.os.Looper; 80import android.os.Message; 81import android.os.PowerManager; 82import android.os.Process; 83import android.os.RemoteException; 84import android.os.SystemClock; 85import android.os.UserHandle; 86import android.os.UserManager; 87import android.os.WorkSource; 88import android.provider.Settings; 89import android.util.Log; 90import android.util.Slog; 91 92import java.io.FileDescriptor; 93import java.io.PrintWriter; 94import java.util.ArrayList; 95import java.util.Arrays; 96import java.util.HashMap; 97import java.util.HashSet; 98import java.util.List; 99import java.util.Map; 100import java.util.Set; 101 102/** 103 * The service class that manages LocationProviders and issues location 104 * updates and alerts. 105 */ 106public class LocationManagerService extends ILocationManager.Stub { 107 private static final String TAG = "LocationManagerService"; 108 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); 109 110 private static final String WAKELOCK_KEY = TAG; 111 112 // Location resolution level: no location data whatsoever 113 private static final int RESOLUTION_LEVEL_NONE = 0; 114 // Location resolution level: coarse location data only 115 private static final int RESOLUTION_LEVEL_COARSE = 1; 116 // Location resolution level: fine location data 117 private static final int RESOLUTION_LEVEL_FINE = 2; 118 119 private static final String ACCESS_MOCK_LOCATION = 120 android.Manifest.permission.ACCESS_MOCK_LOCATION; 121 private static final String ACCESS_LOCATION_EXTRA_COMMANDS = 122 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS; 123 private static final String INSTALL_LOCATION_PROVIDER = 124 android.Manifest.permission.INSTALL_LOCATION_PROVIDER; 125 126 private static final String NETWORK_LOCATION_SERVICE_ACTION = 127 "com.android.location.service.v3.NetworkLocationProvider"; 128 private static final String FUSED_LOCATION_SERVICE_ACTION = 129 "com.android.location.service.FusedLocationProvider"; 130 131 private static final int MSG_LOCATION_CHANGED = 1; 132 133 private static final long NANOS_PER_MILLI = 1000000L; 134 135 // The maximum interval a location request can have and still be considered "high power". 136 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000; 137 138 // Location Providers may sometimes deliver location updates 139 // slightly faster that requested - provide grace period so 140 // we don't unnecessarily filter events that are otherwise on 141 // time 142 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100; 143 144 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest(); 145 146 private final Context mContext; 147 private final AppOpsManager mAppOps; 148 149 // used internally for synchronization 150 private final Object mLock = new Object(); 151 152 // --- fields below are final after systemReady() --- 153 private LocationFudger mLocationFudger; 154 private GeofenceManager mGeofenceManager; 155 private PackageManager mPackageManager; 156 private PowerManager mPowerManager; 157 private UserManager mUserManager; 158 private GeocoderProxy mGeocodeProvider; 159 private IGpsStatusProvider mGpsStatusProvider; 160 private INetInitiatedListener mNetInitiatedListener; 161 private LocationWorkerHandler mLocationHandler; 162 private PassiveProvider mPassiveProvider; // track passive provider for special cases 163 private LocationBlacklist mBlacklist; 164 private GpsMeasurementsProvider mGpsMeasurementsProvider; 165 private GpsNavigationMessageProvider mGpsNavigationMessageProvider; 166 private IGpsGeofenceHardware mGpsGeofenceProxy; 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 407 if (GpsLocationProvider.isSupported()) { 408 // Create a gps location provider 409 GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this, 410 mLocationHandler.getLooper()); 411 mGpsStatusProvider = gpsProvider.getGpsStatusProvider(); 412 mNetInitiatedListener = gpsProvider.getNetInitiatedListener(); 413 addProviderLocked(gpsProvider); 414 mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider); 415 mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider(); 416 mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider(); 417 mGpsGeofenceProxy = gpsProvider.getGpsGeofenceProxy(); 418 } 419 420 /* 421 Load package name(s) containing location provider support. 422 These packages can contain services implementing location providers: 423 Geocoder Provider, Network Location Provider, and 424 Fused Location Provider. They will each be searched for 425 service components implementing these providers. 426 The location framework also has support for installation 427 of new location providers at run-time. The new package does not 428 have to be explicitly listed here, however it must have a signature 429 that matches the signature of at least one package on this list. 430 */ 431 Resources resources = mContext.getResources(); 432 ArrayList<String> providerPackageNames = new ArrayList<String>(); 433 String[] pkgs = resources.getStringArray( 434 com.android.internal.R.array.config_locationProviderPackageNames); 435 if (D) Log.d(TAG, "certificates for location providers pulled from: " + 436 Arrays.toString(pkgs)); 437 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs)); 438 439 ensureFallbackFusedProviderPresentLocked(providerPackageNames); 440 441 // bind to network provider 442 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind( 443 mContext, 444 LocationManager.NETWORK_PROVIDER, 445 NETWORK_LOCATION_SERVICE_ACTION, 446 com.android.internal.R.bool.config_enableNetworkLocationOverlay, 447 com.android.internal.R.string.config_networkLocationProviderPackageName, 448 com.android.internal.R.array.config_locationProviderPackageNames, 449 mLocationHandler); 450 if (networkProvider != null) { 451 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider); 452 mProxyProviders.add(networkProvider); 453 addProviderLocked(networkProvider); 454 } else { 455 Slog.w(TAG, "no network location provider found"); 456 } 457 458 // bind to fused provider 459 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind( 460 mContext, 461 LocationManager.FUSED_PROVIDER, 462 FUSED_LOCATION_SERVICE_ACTION, 463 com.android.internal.R.bool.config_enableFusedLocationOverlay, 464 com.android.internal.R.string.config_fusedLocationProviderPackageName, 465 com.android.internal.R.array.config_locationProviderPackageNames, 466 mLocationHandler); 467 if (fusedLocationProvider != null) { 468 addProviderLocked(fusedLocationProvider); 469 mProxyProviders.add(fusedLocationProvider); 470 mEnabledProviders.add(fusedLocationProvider.getName()); 471 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider); 472 } else { 473 Slog.e(TAG, "no fused location provider found", 474 new IllegalStateException("Location service needs a fused location provider")); 475 } 476 477 // bind to geocoder provider 478 mGeocodeProvider = GeocoderProxy.createAndBind(mContext, 479 com.android.internal.R.bool.config_enableGeocoderOverlay, 480 com.android.internal.R.string.config_geocoderProviderPackageName, 481 com.android.internal.R.array.config_locationProviderPackageNames, 482 mLocationHandler); 483 if (mGeocodeProvider == null) { 484 Slog.e(TAG, "no geocoder provider found"); 485 } 486 487 // bind to fused hardware provider if supported 488 // in devices without support, requesting an instance of FlpHardwareProvider will raise an 489 // exception, so make sure we only do that when supported 490 FlpHardwareProvider flpHardwareProvider; 491 if (FlpHardwareProvider.isSupported()) { 492 flpHardwareProvider = FlpHardwareProvider.getInstance(mContext); 493 FusedProxy fusedProxy = FusedProxy.createAndBind( 494 mContext, 495 mLocationHandler, 496 flpHardwareProvider.getLocationHardware(), 497 com.android.internal.R.bool.config_enableHardwareFlpOverlay, 498 com.android.internal.R.string.config_hardwareFlpPackageName, 499 com.android.internal.R.array.config_locationProviderPackageNames); 500 if (fusedProxy == null) { 501 Slog.e(TAG, "Unable to bind FusedProxy."); 502 } 503 } else { 504 flpHardwareProvider = null; 505 Slog.e(TAG, "FLP HAL not supported"); 506 } 507 508 // bind to geofence provider 509 GeofenceProxy provider = GeofenceProxy.createAndBind( 510 mContext,com.android.internal.R.bool.config_enableGeofenceOverlay, 511 com.android.internal.R.string.config_geofenceProviderPackageName, 512 com.android.internal.R.array.config_locationProviderPackageNames, 513 mLocationHandler, 514 mGpsGeofenceProxy, 515 flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null); 516 if (provider == null) { 517 Slog.e(TAG, "Unable to bind FLP Geofence proxy."); 518 } 519 520 // bind to the hardware activity recognition if supported 521 if (ActivityRecognitionHardware.isSupported()) { 522 ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind( 523 mContext, 524 mLocationHandler, 525 ActivityRecognitionHardware.getInstance(mContext), 526 com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay, 527 com.android.internal.R.string.config_activityRecognitionHardwarePackageName, 528 com.android.internal.R.array.config_locationProviderPackageNames); 529 530 if (proxy == null) { 531 Slog.e(TAG, "Unable to bind ActivityRecognitionProxy."); 532 } 533 } else { 534 Slog.e(TAG, "Hardware Activity-Recognition not supported."); 535 } 536 537 String[] testProviderStrings = resources.getStringArray( 538 com.android.internal.R.array.config_testLocationProviders); 539 for (String testProviderString : testProviderStrings) { 540 String fragments[] = testProviderString.split(","); 541 String name = fragments[0].trim(); 542 if (mProvidersByName.get(name) != null) { 543 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 544 } 545 ProviderProperties properties = new ProviderProperties( 546 Boolean.parseBoolean(fragments[1]) /* requiresNetwork */, 547 Boolean.parseBoolean(fragments[2]) /* requiresSatellite */, 548 Boolean.parseBoolean(fragments[3]) /* requiresCell */, 549 Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */, 550 Boolean.parseBoolean(fragments[5]) /* supportsAltitude */, 551 Boolean.parseBoolean(fragments[6]) /* supportsSpeed */, 552 Boolean.parseBoolean(fragments[7]) /* supportsBearing */, 553 Integer.parseInt(fragments[8]) /* powerRequirement */, 554 Integer.parseInt(fragments[9]) /* accuracy */); 555 addTestProviderLocked(name, properties); 556 } 557 } 558 559 /** 560 * Called when the device's active user changes. 561 * @param userId the new active user's UserId 562 */ 563 private void switchUser(int userId) { 564 if (mCurrentUserId == userId) { 565 return; 566 } 567 mBlacklist.switchUser(userId); 568 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED); 569 synchronized (mLock) { 570 mLastLocation.clear(); 571 mLastLocationCoarseInterval.clear(); 572 for (LocationProviderInterface p : mProviders) { 573 updateProviderListenersLocked(p.getName(), false); 574 } 575 mCurrentUserId = userId; 576 updateUserProfiles(userId); 577 updateProvidersLocked(); 578 } 579 } 580 581 /** 582 * A wrapper class holding either an ILocationListener or a PendingIntent to receive 583 * location updates. 584 */ 585 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { 586 final int mUid; // uid of receiver 587 final int mPid; // pid of receiver 588 final String mPackageName; // package name of receiver 589 final int mAllowedResolutionLevel; // resolution level allowed to receiver 590 591 final ILocationListener mListener; 592 final PendingIntent mPendingIntent; 593 final WorkSource mWorkSource; // WorkSource for battery blame, or null to assign to caller. 594 final boolean mHideFromAppOps; // True if AppOps should not monitor this receiver. 595 final Object mKey; 596 597 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); 598 599 // True if app ops has started monitoring this receiver for locations. 600 boolean mOpMonitoring; 601 // True if app ops has started monitoring this receiver for high power (gps) locations. 602 boolean mOpHighPowerMonitoring; 603 int mPendingBroadcasts; 604 PowerManager.WakeLock mWakeLock; 605 606 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid, 607 String packageName, WorkSource workSource, boolean hideFromAppOps) { 608 mListener = listener; 609 mPendingIntent = intent; 610 if (listener != null) { 611 mKey = listener.asBinder(); 612 } else { 613 mKey = intent; 614 } 615 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid); 616 mUid = uid; 617 mPid = pid; 618 mPackageName = packageName; 619 if (workSource != null && workSource.size() <= 0) { 620 workSource = null; 621 } 622 mWorkSource = workSource; 623 mHideFromAppOps = hideFromAppOps; 624 625 updateMonitoring(true); 626 627 // construct/configure wakelock 628 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 629 if (workSource == null) { 630 workSource = new WorkSource(mUid, mPackageName); 631 } 632 mWakeLock.setWorkSource(workSource); 633 } 634 635 @Override 636 public boolean equals(Object otherObj) { 637 if (otherObj instanceof Receiver) { 638 return mKey.equals(((Receiver)otherObj).mKey); 639 } 640 return false; 641 } 642 643 @Override 644 public int hashCode() { 645 return mKey.hashCode(); 646 } 647 648 @Override 649 public String toString() { 650 StringBuilder s = new StringBuilder(); 651 s.append("Reciever["); 652 s.append(Integer.toHexString(System.identityHashCode(this))); 653 if (mListener != null) { 654 s.append(" listener"); 655 } else { 656 s.append(" intent"); 657 } 658 for (String p : mUpdateRecords.keySet()) { 659 s.append(" ").append(mUpdateRecords.get(p).toString()); 660 } 661 s.append("]"); 662 return s.toString(); 663 } 664 665 /** 666 * Update AppOp monitoring for this receiver. 667 * 668 * @param allow If true receiver is currently active, if false it's been removed. 669 */ 670 public void updateMonitoring(boolean allow) { 671 if (mHideFromAppOps) { 672 return; 673 } 674 675 boolean requestingLocation = false; 676 boolean requestingHighPowerLocation = false; 677 if (allow) { 678 // See if receiver has any enabled update records. Also note if any update records 679 // are high power (has a high power provider with an interval under a threshold). 680 for (UpdateRecord updateRecord : mUpdateRecords.values()) { 681 if (isAllowedByCurrentUserSettingsLocked(updateRecord.mProvider)) { 682 requestingLocation = true; 683 LocationProviderInterface locationProvider 684 = mProvidersByName.get(updateRecord.mProvider); 685 ProviderProperties properties = locationProvider != null 686 ? locationProvider.getProperties() : null; 687 if (properties != null 688 && properties.mPowerRequirement == Criteria.POWER_HIGH 689 && updateRecord.mRequest.getInterval() < HIGH_POWER_INTERVAL_MS) { 690 requestingHighPowerLocation = true; 691 break; 692 } 693 } 694 } 695 } 696 697 // First update monitoring of any location request (including high power). 698 mOpMonitoring = updateMonitoring( 699 requestingLocation, 700 mOpMonitoring, 701 AppOpsManager.OP_MONITOR_LOCATION); 702 703 // Now update monitoring of high power requests only. 704 boolean wasHighPowerMonitoring = mOpHighPowerMonitoring; 705 mOpHighPowerMonitoring = updateMonitoring( 706 requestingHighPowerLocation, 707 mOpHighPowerMonitoring, 708 AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION); 709 if (mOpHighPowerMonitoring != wasHighPowerMonitoring) { 710 // Send an intent to notify that a high power request has been added/removed. 711 Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION); 712 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 713 } 714 } 715 716 /** 717 * Update AppOps monitoring for a single location request and op type. 718 * 719 * @param allowMonitoring True if monitoring is allowed for this request/op. 720 * @param currentlyMonitoring True if AppOps is currently monitoring this request/op. 721 * @param op AppOps code for the op to update. 722 * @return True if monitoring is on for this request/op after updating. 723 */ 724 private boolean updateMonitoring(boolean allowMonitoring, boolean currentlyMonitoring, 725 int op) { 726 if (!currentlyMonitoring) { 727 if (allowMonitoring) { 728 return mAppOps.startOpNoThrow(op, mUid, mPackageName) 729 == AppOpsManager.MODE_ALLOWED; 730 } 731 } else { 732 if (!allowMonitoring || mAppOps.checkOpNoThrow(op, mUid, mPackageName) 733 != AppOpsManager.MODE_ALLOWED) { 734 mAppOps.finishOp(op, mUid, mPackageName); 735 return false; 736 } 737 } 738 739 return currentlyMonitoring; 740 } 741 742 public boolean isListener() { 743 return mListener != null; 744 } 745 746 public boolean isPendingIntent() { 747 return mPendingIntent != null; 748 } 749 750 public ILocationListener getListener() { 751 if (mListener != null) { 752 return mListener; 753 } 754 throw new IllegalStateException("Request for non-existent listener"); 755 } 756 757 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { 758 if (mListener != null) { 759 try { 760 synchronized (this) { 761 // synchronize to ensure incrementPendingBroadcastsLocked() 762 // is called before decrementPendingBroadcasts() 763 mListener.onStatusChanged(provider, status, extras); 764 // call this after broadcasting so we do not increment 765 // if we throw an exeption. 766 incrementPendingBroadcastsLocked(); 767 } 768 } catch (RemoteException e) { 769 return false; 770 } 771 } else { 772 Intent statusChanged = new Intent(); 773 statusChanged.putExtras(new Bundle(extras)); 774 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); 775 try { 776 synchronized (this) { 777 // synchronize to ensure incrementPendingBroadcastsLocked() 778 // is called before decrementPendingBroadcasts() 779 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler, 780 getResolutionPermission(mAllowedResolutionLevel)); 781 // call this after broadcasting so we do not increment 782 // if we throw an exeption. 783 incrementPendingBroadcastsLocked(); 784 } 785 } catch (PendingIntent.CanceledException e) { 786 return false; 787 } 788 } 789 return true; 790 } 791 792 public boolean callLocationChangedLocked(Location location) { 793 if (mListener != null) { 794 try { 795 synchronized (this) { 796 // synchronize to ensure incrementPendingBroadcastsLocked() 797 // is called before decrementPendingBroadcasts() 798 mListener.onLocationChanged(new Location(location)); 799 // call this after broadcasting so we do not increment 800 // if we throw an exeption. 801 incrementPendingBroadcastsLocked(); 802 } 803 } catch (RemoteException e) { 804 return false; 805 } 806 } else { 807 Intent locationChanged = new Intent(); 808 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, new Location(location)); 809 try { 810 synchronized (this) { 811 // synchronize to ensure incrementPendingBroadcastsLocked() 812 // is called before decrementPendingBroadcasts() 813 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler, 814 getResolutionPermission(mAllowedResolutionLevel)); 815 // call this after broadcasting so we do not increment 816 // if we throw an exeption. 817 incrementPendingBroadcastsLocked(); 818 } 819 } catch (PendingIntent.CanceledException e) { 820 return false; 821 } 822 } 823 return true; 824 } 825 826 public boolean callProviderEnabledLocked(String provider, boolean enabled) { 827 // First update AppOp monitoring. 828 // An app may get/lose location access as providers are enabled/disabled. 829 updateMonitoring(true); 830 831 if (mListener != null) { 832 try { 833 synchronized (this) { 834 // synchronize to ensure incrementPendingBroadcastsLocked() 835 // is called before decrementPendingBroadcasts() 836 if (enabled) { 837 mListener.onProviderEnabled(provider); 838 } else { 839 mListener.onProviderDisabled(provider); 840 } 841 // call this after broadcasting so we do not increment 842 // if we throw an exeption. 843 incrementPendingBroadcastsLocked(); 844 } 845 } catch (RemoteException e) { 846 return false; 847 } 848 } else { 849 Intent providerIntent = new Intent(); 850 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); 851 try { 852 synchronized (this) { 853 // synchronize to ensure incrementPendingBroadcastsLocked() 854 // is called before decrementPendingBroadcasts() 855 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler, 856 getResolutionPermission(mAllowedResolutionLevel)); 857 // call this after broadcasting so we do not increment 858 // if we throw an exeption. 859 incrementPendingBroadcastsLocked(); 860 } 861 } catch (PendingIntent.CanceledException e) { 862 return false; 863 } 864 } 865 return true; 866 } 867 868 @Override 869 public void binderDied() { 870 if (D) Log.d(TAG, "Location listener died"); 871 872 synchronized (mLock) { 873 removeUpdatesLocked(this); 874 } 875 synchronized (this) { 876 clearPendingBroadcastsLocked(); 877 } 878 } 879 880 @Override 881 public void onSendFinished(PendingIntent pendingIntent, Intent intent, 882 int resultCode, String resultData, Bundle resultExtras) { 883 synchronized (this) { 884 decrementPendingBroadcastsLocked(); 885 } 886 } 887 888 // this must be called while synchronized by caller in a synchronized block 889 // containing the sending of the broadcaset 890 private void incrementPendingBroadcastsLocked() { 891 if (mPendingBroadcasts++ == 0) { 892 mWakeLock.acquire(); 893 } 894 } 895 896 private void decrementPendingBroadcastsLocked() { 897 if (--mPendingBroadcasts == 0) { 898 if (mWakeLock.isHeld()) { 899 mWakeLock.release(); 900 } 901 } 902 } 903 904 public void clearPendingBroadcastsLocked() { 905 if (mPendingBroadcasts > 0) { 906 mPendingBroadcasts = 0; 907 if (mWakeLock.isHeld()) { 908 mWakeLock.release(); 909 } 910 } 911 } 912 } 913 914 @Override 915 public void locationCallbackFinished(ILocationListener listener) { 916 //Do not use getReceiverLocked here as that will add the ILocationListener to 917 //the receiver list if it is not found. If it is not found then the 918 //LocationListener was removed when it had a pending broadcast and should 919 //not be added back. 920 synchronized (mLock) { 921 IBinder binder = listener.asBinder(); 922 Receiver receiver = mReceivers.get(binder); 923 if (receiver != null) { 924 synchronized (receiver) { 925 // so wakelock calls will succeed 926 long identity = Binder.clearCallingIdentity(); 927 receiver.decrementPendingBroadcastsLocked(); 928 Binder.restoreCallingIdentity(identity); 929 } 930 } 931 } 932 } 933 934 private void addProviderLocked(LocationProviderInterface provider) { 935 mProviders.add(provider); 936 mProvidersByName.put(provider.getName(), provider); 937 } 938 939 private void removeProviderLocked(LocationProviderInterface provider) { 940 provider.disable(); 941 mProviders.remove(provider); 942 mProvidersByName.remove(provider.getName()); 943 } 944 945 /** 946 * Returns "true" if access to the specified location provider is allowed by the current 947 * user's settings. Access to all location providers is forbidden to non-location-provider 948 * processes belonging to background users. 949 * 950 * @param provider the name of the location provider 951 * @return 952 */ 953 private boolean isAllowedByCurrentUserSettingsLocked(String provider) { 954 if (mEnabledProviders.contains(provider)) { 955 return true; 956 } 957 if (mDisabledProviders.contains(provider)) { 958 return false; 959 } 960 // Use system settings 961 ContentResolver resolver = mContext.getContentResolver(); 962 963 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId); 964 } 965 966 /** 967 * Returns "true" if access to the specified location provider is allowed by the specified 968 * user's settings. Access to all location providers is forbidden to non-location-provider 969 * processes belonging to background users. 970 * 971 * @param provider the name of the location provider 972 * @param uid the requestor's UID 973 * @return 974 */ 975 private boolean isAllowedByUserSettingsLocked(String provider, int uid) { 976 if (!isCurrentProfile(UserHandle.getUserId(uid)) && !isUidALocationProvider(uid)) { 977 return false; 978 } 979 return isAllowedByCurrentUserSettingsLocked(provider); 980 } 981 982 /** 983 * Returns the permission string associated with the specified resolution level. 984 * 985 * @param resolutionLevel the resolution level 986 * @return the permission string 987 */ 988 private String getResolutionPermission(int resolutionLevel) { 989 switch (resolutionLevel) { 990 case RESOLUTION_LEVEL_FINE: 991 return android.Manifest.permission.ACCESS_FINE_LOCATION; 992 case RESOLUTION_LEVEL_COARSE: 993 return android.Manifest.permission.ACCESS_COARSE_LOCATION; 994 default: 995 return null; 996 } 997 } 998 999 /** 1000 * Returns the resolution level allowed to the given PID/UID pair. 1001 * 1002 * @param pid the PID 1003 * @param uid the UID 1004 * @return resolution level allowed to the pid/uid pair 1005 */ 1006 private int getAllowedResolutionLevel(int pid, int uid) { 1007 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, 1008 pid, uid) == PackageManager.PERMISSION_GRANTED) { 1009 return RESOLUTION_LEVEL_FINE; 1010 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, 1011 pid, uid) == PackageManager.PERMISSION_GRANTED) { 1012 return RESOLUTION_LEVEL_COARSE; 1013 } else { 1014 return RESOLUTION_LEVEL_NONE; 1015 } 1016 } 1017 1018 /** 1019 * Returns the resolution level allowed to the caller 1020 * 1021 * @return resolution level allowed to caller 1022 */ 1023 private int getCallerAllowedResolutionLevel() { 1024 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid()); 1025 } 1026 1027 /** 1028 * Throw SecurityException if specified resolution level is insufficient to use geofences. 1029 * 1030 * @param allowedResolutionLevel resolution level allowed to caller 1031 */ 1032 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) { 1033 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1034 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission"); 1035 } 1036 } 1037 1038 /** 1039 * Return the minimum resolution level required to use the specified location provider. 1040 * 1041 * @param provider the name of the location provider 1042 * @return minimum resolution level required for provider 1043 */ 1044 private int getMinimumResolutionLevelForProviderUse(String provider) { 1045 if (LocationManager.GPS_PROVIDER.equals(provider) || 1046 LocationManager.PASSIVE_PROVIDER.equals(provider)) { 1047 // gps and passive providers require FINE permission 1048 return RESOLUTION_LEVEL_FINE; 1049 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) || 1050 LocationManager.FUSED_PROVIDER.equals(provider)) { 1051 // network and fused providers are ok with COARSE or FINE 1052 return RESOLUTION_LEVEL_COARSE; 1053 } else { 1054 // mock providers 1055 LocationProviderInterface lp = mMockProviders.get(provider); 1056 if (lp != null) { 1057 ProviderProperties properties = lp.getProperties(); 1058 if (properties != null) { 1059 if (properties.mRequiresSatellite) { 1060 // provider requiring satellites require FINE permission 1061 return RESOLUTION_LEVEL_FINE; 1062 } else if (properties.mRequiresNetwork || properties.mRequiresCell) { 1063 // provider requiring network and or cell require COARSE or FINE 1064 return RESOLUTION_LEVEL_COARSE; 1065 } 1066 } 1067 } 1068 } 1069 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE 1070 } 1071 1072 /** 1073 * Throw SecurityException if specified resolution level is insufficient to use the named 1074 * location provider. 1075 * 1076 * @param allowedResolutionLevel resolution level allowed to caller 1077 * @param providerName the name of the location provider 1078 */ 1079 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel, 1080 String providerName) { 1081 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName); 1082 if (allowedResolutionLevel < requiredResolutionLevel) { 1083 switch (requiredResolutionLevel) { 1084 case RESOLUTION_LEVEL_FINE: 1085 throw new SecurityException("\"" + providerName + "\" location provider " + 1086 "requires ACCESS_FINE_LOCATION permission."); 1087 case RESOLUTION_LEVEL_COARSE: 1088 throw new SecurityException("\"" + providerName + "\" location provider " + 1089 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission."); 1090 default: 1091 throw new SecurityException("Insufficient permission for \"" + providerName + 1092 "\" location provider."); 1093 } 1094 } 1095 } 1096 1097 /** 1098 * Throw SecurityException if WorkSource use is not allowed (i.e. can't blame other packages 1099 * for battery). 1100 */ 1101 private void checkDeviceStatsAllowed() { 1102 mContext.enforceCallingOrSelfPermission( 1103 android.Manifest.permission.UPDATE_DEVICE_STATS, null); 1104 } 1105 1106 private void checkUpdateAppOpsAllowed() { 1107 mContext.enforceCallingOrSelfPermission( 1108 android.Manifest.permission.UPDATE_APP_OPS_STATS, null); 1109 } 1110 1111 public static int resolutionLevelToOp(int allowedResolutionLevel) { 1112 if (allowedResolutionLevel != RESOLUTION_LEVEL_NONE) { 1113 if (allowedResolutionLevel == RESOLUTION_LEVEL_COARSE) { 1114 return AppOpsManager.OP_COARSE_LOCATION; 1115 } else { 1116 return AppOpsManager.OP_FINE_LOCATION; 1117 } 1118 } 1119 return -1; 1120 } 1121 1122 boolean reportLocationAccessNoThrow(int uid, String packageName, int allowedResolutionLevel) { 1123 int op = resolutionLevelToOp(allowedResolutionLevel); 1124 if (op >= 0) { 1125 if (mAppOps.noteOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { 1126 return false; 1127 } 1128 } 1129 return true; 1130 } 1131 1132 boolean checkLocationAccess(int uid, String packageName, int allowedResolutionLevel) { 1133 int op = resolutionLevelToOp(allowedResolutionLevel); 1134 if (op >= 0) { 1135 if (mAppOps.checkOp(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) { 1136 return false; 1137 } 1138 } 1139 return true; 1140 } 1141 1142 /** 1143 * Returns all providers by name, including passive, but excluding 1144 * fused, also including ones that are not permitted to 1145 * be accessed by the calling activity or are currently disabled. 1146 */ 1147 @Override 1148 public List<String> getAllProviders() { 1149 ArrayList<String> out; 1150 synchronized (mLock) { 1151 out = new ArrayList<String>(mProviders.size()); 1152 for (LocationProviderInterface provider : mProviders) { 1153 String name = provider.getName(); 1154 if (LocationManager.FUSED_PROVIDER.equals(name)) { 1155 continue; 1156 } 1157 out.add(name); 1158 } 1159 } 1160 1161 if (D) Log.d(TAG, "getAllProviders()=" + out); 1162 return out; 1163 } 1164 1165 /** 1166 * Return all providers by name, that match criteria and are optionally 1167 * enabled. 1168 * Can return passive provider, but never returns fused provider. 1169 */ 1170 @Override 1171 public List<String> getProviders(Criteria criteria, boolean enabledOnly) { 1172 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1173 ArrayList<String> out; 1174 int uid = Binder.getCallingUid();; 1175 long identity = Binder.clearCallingIdentity(); 1176 try { 1177 synchronized (mLock) { 1178 out = new ArrayList<String>(mProviders.size()); 1179 for (LocationProviderInterface provider : mProviders) { 1180 String name = provider.getName(); 1181 if (LocationManager.FUSED_PROVIDER.equals(name)) { 1182 continue; 1183 } 1184 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) { 1185 if (enabledOnly && !isAllowedByUserSettingsLocked(name, uid)) { 1186 continue; 1187 } 1188 if (criteria != null && !LocationProvider.propertiesMeetCriteria( 1189 name, provider.getProperties(), criteria)) { 1190 continue; 1191 } 1192 out.add(name); 1193 } 1194 } 1195 } 1196 } finally { 1197 Binder.restoreCallingIdentity(identity); 1198 } 1199 1200 if (D) Log.d(TAG, "getProviders()=" + out); 1201 return out; 1202 } 1203 1204 /** 1205 * Return the name of the best provider given a Criteria object. 1206 * This method has been deprecated from the public API, 1207 * and the whole LocationProvider (including #meetsCriteria) 1208 * has been deprecated as well. So this method now uses 1209 * some simplified logic. 1210 */ 1211 @Override 1212 public String getBestProvider(Criteria criteria, boolean enabledOnly) { 1213 String result = null; 1214 1215 List<String> providers = getProviders(criteria, enabledOnly); 1216 if (!providers.isEmpty()) { 1217 result = pickBest(providers); 1218 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 1219 return result; 1220 } 1221 providers = getProviders(null, enabledOnly); 1222 if (!providers.isEmpty()) { 1223 result = pickBest(providers); 1224 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 1225 return result; 1226 } 1227 1228 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 1229 return null; 1230 } 1231 1232 private String pickBest(List<String> providers) { 1233 if (providers.contains(LocationManager.GPS_PROVIDER)) { 1234 return LocationManager.GPS_PROVIDER; 1235 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) { 1236 return LocationManager.NETWORK_PROVIDER; 1237 } else { 1238 return providers.get(0); 1239 } 1240 } 1241 1242 @Override 1243 public boolean providerMeetsCriteria(String provider, Criteria criteria) { 1244 LocationProviderInterface p = mProvidersByName.get(provider); 1245 if (p == null) { 1246 throw new IllegalArgumentException("provider=" + provider); 1247 } 1248 1249 boolean result = LocationProvider.propertiesMeetCriteria( 1250 p.getName(), p.getProperties(), criteria); 1251 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result); 1252 return result; 1253 } 1254 1255 private void updateProvidersLocked() { 1256 boolean changesMade = false; 1257 for (int i = mProviders.size() - 1; i >= 0; i--) { 1258 LocationProviderInterface p = mProviders.get(i); 1259 boolean isEnabled = p.isEnabled(); 1260 String name = p.getName(); 1261 boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name); 1262 if (isEnabled && !shouldBeEnabled) { 1263 updateProviderListenersLocked(name, false); 1264 // If any provider has been disabled, clear all last locations for all providers. 1265 // This is to be on the safe side in case a provider has location derived from 1266 // this disabled provider. 1267 mLastLocation.clear(); 1268 mLastLocationCoarseInterval.clear(); 1269 changesMade = true; 1270 } else if (!isEnabled && shouldBeEnabled) { 1271 updateProviderListenersLocked(name, true); 1272 changesMade = true; 1273 } 1274 } 1275 if (changesMade) { 1276 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION), 1277 UserHandle.ALL); 1278 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION), 1279 UserHandle.ALL); 1280 } 1281 } 1282 1283 private void updateProviderListenersLocked(String provider, boolean enabled) { 1284 int listeners = 0; 1285 1286 LocationProviderInterface p = mProvidersByName.get(provider); 1287 if (p == null) return; 1288 1289 ArrayList<Receiver> deadReceivers = null; 1290 1291 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1292 if (records != null) { 1293 final int N = records.size(); 1294 for (int i = 0; i < N; i++) { 1295 UpdateRecord record = records.get(i); 1296 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) { 1297 // Sends a notification message to the receiver 1298 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { 1299 if (deadReceivers == null) { 1300 deadReceivers = new ArrayList<Receiver>(); 1301 } 1302 deadReceivers.add(record.mReceiver); 1303 } 1304 listeners++; 1305 } 1306 } 1307 } 1308 1309 if (deadReceivers != null) { 1310 for (int i = deadReceivers.size() - 1; i >= 0; i--) { 1311 removeUpdatesLocked(deadReceivers.get(i)); 1312 } 1313 } 1314 1315 if (enabled) { 1316 p.enable(); 1317 if (listeners > 0) { 1318 applyRequirementsLocked(provider); 1319 } 1320 } else { 1321 p.disable(); 1322 } 1323 } 1324 1325 private void applyRequirementsLocked(String provider) { 1326 LocationProviderInterface p = mProvidersByName.get(provider); 1327 if (p == null) return; 1328 1329 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1330 WorkSource worksource = new WorkSource(); 1331 ProviderRequest providerRequest = new ProviderRequest(); 1332 1333 if (records != null) { 1334 for (UpdateRecord record : records) { 1335 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) { 1336 if (checkLocationAccess(record.mReceiver.mUid, record.mReceiver.mPackageName, 1337 record.mReceiver.mAllowedResolutionLevel)) { 1338 LocationRequest locationRequest = record.mRequest; 1339 providerRequest.locationRequests.add(locationRequest); 1340 if (locationRequest.getInterval() < providerRequest.interval) { 1341 providerRequest.reportLocation = true; 1342 providerRequest.interval = locationRequest.getInterval(); 1343 } 1344 } 1345 } 1346 } 1347 1348 if (providerRequest.reportLocation) { 1349 // calculate who to blame for power 1350 // This is somewhat arbitrary. We pick a threshold interval 1351 // that is slightly higher that the minimum interval, and 1352 // spread the blame across all applications with a request 1353 // under that threshold. 1354 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; 1355 for (UpdateRecord record : records) { 1356 if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) { 1357 LocationRequest locationRequest = record.mRequest; 1358 if (locationRequest.getInterval() <= thresholdInterval) { 1359 if (record.mReceiver.mWorkSource != null 1360 && record.mReceiver.mWorkSource.size() > 0 1361 && record.mReceiver.mWorkSource.getName(0) != null) { 1362 // Assign blame to another work source. 1363 // Can only assign blame if the WorkSource contains names. 1364 worksource.add(record.mReceiver.mWorkSource); 1365 } else { 1366 // Assign blame to caller. 1367 worksource.add( 1368 record.mReceiver.mUid, 1369 record.mReceiver.mPackageName); 1370 } 1371 } 1372 } 1373 } 1374 } 1375 } 1376 1377 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); 1378 p.setRequest(providerRequest, worksource); 1379 } 1380 1381 private class UpdateRecord { 1382 final String mProvider; 1383 final LocationRequest mRequest; 1384 final Receiver mReceiver; 1385 Location mLastFixBroadcast; 1386 long mLastStatusBroadcast; 1387 1388 /** 1389 * Note: must be constructed with lock held. 1390 */ 1391 UpdateRecord(String provider, LocationRequest request, Receiver receiver) { 1392 mProvider = provider; 1393 mRequest = request; 1394 mReceiver = receiver; 1395 1396 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1397 if (records == null) { 1398 records = new ArrayList<UpdateRecord>(); 1399 mRecordsByProvider.put(provider, records); 1400 } 1401 if (!records.contains(this)) { 1402 records.add(this); 1403 } 1404 1405 // Update statistics for historical location requests by package/provider 1406 mRequestStatistics.startRequesting( 1407 mReceiver.mPackageName, provider, request.getInterval()); 1408 } 1409 1410 /** 1411 * Method to be called when a record will no longer be used. 1412 */ 1413 void disposeLocked(boolean removeReceiver) { 1414 mRequestStatistics.stopRequesting(mReceiver.mPackageName, mProvider); 1415 1416 // remove from mRecordsByProvider 1417 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); 1418 if (globalRecords != null) { 1419 globalRecords.remove(this); 1420 } 1421 1422 if (!removeReceiver) return; // the caller will handle the rest 1423 1424 // remove from Receiver#mUpdateRecords 1425 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords; 1426 if (receiverRecords != null) { 1427 receiverRecords.remove(this.mProvider); 1428 1429 // and also remove the Receiver if it has no more update records 1430 if (removeReceiver && receiverRecords.size() == 0) { 1431 removeUpdatesLocked(mReceiver); 1432 } 1433 } 1434 } 1435 1436 @Override 1437 public String toString() { 1438 StringBuilder s = new StringBuilder(); 1439 s.append("UpdateRecord["); 1440 s.append(mProvider); 1441 s.append(' ').append(mReceiver.mPackageName).append('('); 1442 s.append(mReceiver.mUid).append(')'); 1443 s.append(' ').append(mRequest); 1444 s.append(']'); 1445 return s.toString(); 1446 } 1447 } 1448 1449 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid, 1450 String packageName, WorkSource workSource, boolean hideFromAppOps) { 1451 IBinder binder = listener.asBinder(); 1452 Receiver receiver = mReceivers.get(binder); 1453 if (receiver == null) { 1454 receiver = new Receiver(listener, null, pid, uid, packageName, workSource, 1455 hideFromAppOps); 1456 try { 1457 receiver.getListener().asBinder().linkToDeath(receiver, 0); 1458 } catch (RemoteException e) { 1459 Slog.e(TAG, "linkToDeath failed:", e); 1460 return null; 1461 } 1462 mReceivers.put(binder, receiver); 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 || mGpsMeasurementsProvider == null) { 1858 return false; 1859 } 1860 return mGpsMeasurementsProvider.addListener(listener); 1861 } 1862 1863 @Override 1864 public void removeGpsMeasurementsListener(IGpsMeasurementsListener listener) { 1865 if (mGpsMeasurementsProvider != null) { 1866 mGpsMeasurementsProvider.removeListener(listener); 1867 } 1868 } 1869 1870 @Override 1871 public boolean addGpsNavigationMessageListener( 1872 IGpsNavigationMessageListener listener, 1873 String packageName) { 1874 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1875 checkResolutionLevelIsSufficientForProviderUse( 1876 allowedResolutionLevel, 1877 LocationManager.GPS_PROVIDER); 1878 1879 int uid = Binder.getCallingUid(); 1880 long identity = Binder.clearCallingIdentity(); 1881 boolean hasLocationAccess; 1882 try { 1883 hasLocationAccess = checkLocationAccess(uid, packageName, allowedResolutionLevel); 1884 } finally { 1885 Binder.restoreCallingIdentity(identity); 1886 } 1887 1888 if (!hasLocationAccess || mGpsNavigationMessageProvider == null) { 1889 return false; 1890 } 1891 return mGpsNavigationMessageProvider.addListener(listener); 1892 } 1893 1894 @Override 1895 public void removeGpsNavigationMessageListener(IGpsNavigationMessageListener listener) { 1896 if (mGpsNavigationMessageProvider != null) { 1897 mGpsNavigationMessageProvider.removeListener(listener); 1898 } 1899 } 1900 1901 @Override 1902 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 1903 if (provider == null) { 1904 // throw NullPointerException to remain compatible with previous implementation 1905 throw new NullPointerException(); 1906 } 1907 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1908 provider); 1909 1910 // and check for ACCESS_LOCATION_EXTRA_COMMANDS 1911 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 1912 != PackageManager.PERMISSION_GRANTED)) { 1913 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 1914 } 1915 1916 synchronized (mLock) { 1917 LocationProviderInterface p = mProvidersByName.get(provider); 1918 if (p == null) return false; 1919 1920 return p.sendExtraCommand(command, extras); 1921 } 1922 } 1923 1924 @Override 1925 public boolean sendNiResponse(int notifId, int userResponse) { 1926 if (Binder.getCallingUid() != Process.myUid()) { 1927 throw new SecurityException( 1928 "calling sendNiResponse from outside of the system is not allowed"); 1929 } 1930 try { 1931 return mNetInitiatedListener.sendNiResponse(notifId, userResponse); 1932 } catch (RemoteException e) { 1933 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); 1934 return false; 1935 } 1936 } 1937 1938 /** 1939 * @return null if the provider does not exist 1940 * @throws SecurityException if the provider is not allowed to be 1941 * accessed by the caller 1942 */ 1943 @Override 1944 public ProviderProperties getProviderProperties(String provider) { 1945 if (mProvidersByName.get(provider) == null) { 1946 return null; 1947 } 1948 1949 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1950 provider); 1951 1952 LocationProviderInterface p; 1953 synchronized (mLock) { 1954 p = mProvidersByName.get(provider); 1955 } 1956 1957 if (p == null) return null; 1958 return p.getProperties(); 1959 } 1960 1961 @Override 1962 public boolean isProviderEnabled(String provider) { 1963 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, 1964 // so we discourage its use 1965 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1966 1967 int uid = Binder.getCallingUid(); 1968 long identity = Binder.clearCallingIdentity(); 1969 try { 1970 synchronized (mLock) { 1971 LocationProviderInterface p = mProvidersByName.get(provider); 1972 if (p == null) return false; 1973 1974 return isAllowedByUserSettingsLocked(provider, uid); 1975 } 1976 } finally { 1977 Binder.restoreCallingIdentity(identity); 1978 } 1979 } 1980 1981 /** 1982 * Returns "true" if the UID belongs to a bound location provider. 1983 * 1984 * @param uid the uid 1985 * @return true if uid belongs to a bound location provider 1986 */ 1987 private boolean isUidALocationProvider(int uid) { 1988 if (uid == Process.SYSTEM_UID) { 1989 return true; 1990 } 1991 if (mGeocodeProvider != null) { 1992 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true; 1993 } 1994 for (LocationProviderProxy proxy : mProxyProviders) { 1995 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true; 1996 } 1997 return false; 1998 } 1999 2000 private void checkCallerIsProvider() { 2001 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 2002 == PackageManager.PERMISSION_GRANTED) { 2003 return; 2004 } 2005 2006 // Previously we only used the INSTALL_LOCATION_PROVIDER 2007 // check. But that is system or signature 2008 // protection level which is not flexible enough for 2009 // providers installed oustide the system image. So 2010 // also allow providers with a UID matching the 2011 // currently bound package name 2012 2013 if (isUidALocationProvider(Binder.getCallingUid())) { 2014 return; 2015 } 2016 2017 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 2018 "or UID of a currently bound location provider"); 2019 } 2020 2021 /** 2022 * Returns true if the given package belongs to the given uid. 2023 */ 2024 private boolean doesUidHavePackage(int uid, String packageName) { 2025 if (packageName == null) { 2026 return false; 2027 } 2028 String[] packageNames = mPackageManager.getPackagesForUid(uid); 2029 if (packageNames == null) { 2030 return false; 2031 } 2032 for (String name : packageNames) { 2033 if (packageName.equals(name)) { 2034 return true; 2035 } 2036 } 2037 return false; 2038 } 2039 2040 @Override 2041 public void reportLocation(Location location, boolean passive) { 2042 checkCallerIsProvider(); 2043 2044 if (!location.isComplete()) { 2045 Log.w(TAG, "Dropping incomplete location: " + location); 2046 return; 2047 } 2048 2049 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 2050 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 2051 m.arg1 = (passive ? 1 : 0); 2052 mLocationHandler.sendMessageAtFrontOfQueue(m); 2053 } 2054 2055 2056 private static boolean shouldBroadcastSafe( 2057 Location loc, Location lastLoc, UpdateRecord record, long now) { 2058 // Always broadcast the first update 2059 if (lastLoc == null) { 2060 return true; 2061 } 2062 2063 // Check whether sufficient time has passed 2064 long minTime = record.mRequest.getFastestInterval(); 2065 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) 2066 / NANOS_PER_MILLI; 2067 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 2068 return false; 2069 } 2070 2071 // Check whether sufficient distance has been traveled 2072 double minDistance = record.mRequest.getSmallestDisplacement(); 2073 if (minDistance > 0.0) { 2074 if (loc.distanceTo(lastLoc) <= minDistance) { 2075 return false; 2076 } 2077 } 2078 2079 // Check whether sufficient number of udpates is left 2080 if (record.mRequest.getNumUpdates() <= 0) { 2081 return false; 2082 } 2083 2084 // Check whether the expiry date has passed 2085 if (record.mRequest.getExpireAt() < now) { 2086 return false; 2087 } 2088 2089 return true; 2090 } 2091 2092 private void handleLocationChangedLocked(Location location, boolean passive) { 2093 if (D) Log.d(TAG, "incoming location: " + location); 2094 2095 long now = SystemClock.elapsedRealtime(); 2096 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 2097 2098 // Skip if the provider is unknown. 2099 LocationProviderInterface p = mProvidersByName.get(provider); 2100 if (p == null) return; 2101 2102 // Update last known locations 2103 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2104 Location lastNoGPSLocation = null; 2105 Location lastLocation = mLastLocation.get(provider); 2106 if (lastLocation == null) { 2107 lastLocation = new Location(provider); 2108 mLastLocation.put(provider, lastLocation); 2109 } else { 2110 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2111 if (noGPSLocation == null && lastNoGPSLocation != null) { 2112 // New location has no no-GPS location: adopt last no-GPS location. This is set 2113 // directly into location because we do not want to notify COARSE clients. 2114 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 2115 } 2116 } 2117 lastLocation.set(location); 2118 2119 // Update last known coarse interval location if enough time has passed. 2120 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider); 2121 if (lastLocationCoarseInterval == null) { 2122 lastLocationCoarseInterval = new Location(location); 2123 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval); 2124 } 2125 long timeDiffNanos = location.getElapsedRealtimeNanos() 2126 - lastLocationCoarseInterval.getElapsedRealtimeNanos(); 2127 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) { 2128 lastLocationCoarseInterval.set(location); 2129 } 2130 // Don't ever return a coarse location that is more recent than the allowed update 2131 // interval (i.e. don't allow an app to keep registering and unregistering for 2132 // location updates to overcome the minimum interval). 2133 noGPSLocation = 2134 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2135 2136 // Skip if there are no UpdateRecords for this provider. 2137 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 2138 if (records == null || records.size() == 0) return; 2139 2140 // Fetch coarse location 2141 Location coarseLocation = null; 2142 if (noGPSLocation != null) { 2143 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 2144 } 2145 2146 // Fetch latest status update time 2147 long newStatusUpdateTime = p.getStatusUpdateTime(); 2148 2149 // Get latest status 2150 Bundle extras = new Bundle(); 2151 int status = p.getStatus(extras); 2152 2153 ArrayList<Receiver> deadReceivers = null; 2154 ArrayList<UpdateRecord> deadUpdateRecords = null; 2155 2156 // Broadcast location or status to all listeners 2157 for (UpdateRecord r : records) { 2158 Receiver receiver = r.mReceiver; 2159 boolean receiverDead = false; 2160 2161 int receiverUserId = UserHandle.getUserId(receiver.mUid); 2162 if (!isCurrentProfile(receiverUserId) && !isUidALocationProvider(receiver.mUid)) { 2163 if (D) { 2164 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 2165 " (current user: " + mCurrentUserId + ", app: " + 2166 receiver.mPackageName + ")"); 2167 } 2168 continue; 2169 } 2170 2171 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 2172 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 2173 receiver.mPackageName); 2174 continue; 2175 } 2176 2177 if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName, 2178 receiver.mAllowedResolutionLevel)) { 2179 if (D) Log.d(TAG, "skipping loc update for no op app: " + 2180 receiver.mPackageName); 2181 continue; 2182 } 2183 2184 Location notifyLocation = null; 2185 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2186 notifyLocation = coarseLocation; // use coarse location 2187 } else { 2188 notifyLocation = lastLocation; // use fine location 2189 } 2190 if (notifyLocation != null) { 2191 Location lastLoc = r.mLastFixBroadcast; 2192 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) { 2193 if (lastLoc == null) { 2194 lastLoc = new Location(notifyLocation); 2195 r.mLastFixBroadcast = lastLoc; 2196 } else { 2197 lastLoc.set(notifyLocation); 2198 } 2199 if (!receiver.callLocationChangedLocked(notifyLocation)) { 2200 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 2201 receiverDead = true; 2202 } 2203 r.mRequest.decrementNumUpdates(); 2204 } 2205 } 2206 2207 long prevStatusUpdateTime = r.mLastStatusBroadcast; 2208 if ((newStatusUpdateTime > prevStatusUpdateTime) && 2209 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 2210 2211 r.mLastStatusBroadcast = newStatusUpdateTime; 2212 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 2213 receiverDead = true; 2214 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 2215 } 2216 } 2217 2218 // track expired records 2219 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) { 2220 if (deadUpdateRecords == null) { 2221 deadUpdateRecords = new ArrayList<UpdateRecord>(); 2222 } 2223 deadUpdateRecords.add(r); 2224 } 2225 // track dead receivers 2226 if (receiverDead) { 2227 if (deadReceivers == null) { 2228 deadReceivers = new ArrayList<Receiver>(); 2229 } 2230 if (!deadReceivers.contains(receiver)) { 2231 deadReceivers.add(receiver); 2232 } 2233 } 2234 } 2235 2236 // remove dead records and receivers outside the loop 2237 if (deadReceivers != null) { 2238 for (Receiver receiver : deadReceivers) { 2239 removeUpdatesLocked(receiver); 2240 } 2241 } 2242 if (deadUpdateRecords != null) { 2243 for (UpdateRecord r : deadUpdateRecords) { 2244 r.disposeLocked(true); 2245 } 2246 applyRequirementsLocked(provider); 2247 } 2248 } 2249 2250 private class LocationWorkerHandler extends Handler { 2251 public LocationWorkerHandler(Looper looper) { 2252 super(looper, null, true); 2253 } 2254 2255 @Override 2256 public void handleMessage(Message msg) { 2257 switch (msg.what) { 2258 case MSG_LOCATION_CHANGED: 2259 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 2260 break; 2261 } 2262 } 2263 } 2264 2265 private boolean isMockProvider(String provider) { 2266 synchronized (mLock) { 2267 return mMockProviders.containsKey(provider); 2268 } 2269 } 2270 2271 private void handleLocationChanged(Location location, boolean passive) { 2272 // create a working copy of the incoming Location so that the service can modify it without 2273 // disturbing the caller's copy 2274 Location myLocation = new Location(location); 2275 String provider = myLocation.getProvider(); 2276 2277 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this 2278 // bit if location did not come from a mock provider because passive/fused providers can 2279 // forward locations from mock providers, and should not grant them legitimacy in doing so. 2280 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) { 2281 myLocation.setIsFromMockProvider(true); 2282 } 2283 2284 synchronized (mLock) { 2285 if (isAllowedByCurrentUserSettingsLocked(provider)) { 2286 if (!passive) { 2287 // notify passive provider of the new location 2288 mPassiveProvider.updateLocation(myLocation); 2289 } 2290 handleLocationChangedLocked(myLocation, passive); 2291 } 2292 } 2293 } 2294 2295 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 2296 @Override 2297 public void onPackageDisappeared(String packageName, int reason) { 2298 // remove all receivers associated with this package name 2299 synchronized (mLock) { 2300 ArrayList<Receiver> deadReceivers = null; 2301 2302 for (Receiver receiver : mReceivers.values()) { 2303 if (receiver.mPackageName.equals(packageName)) { 2304 if (deadReceivers == null) { 2305 deadReceivers = new ArrayList<Receiver>(); 2306 } 2307 deadReceivers.add(receiver); 2308 } 2309 } 2310 2311 // perform removal outside of mReceivers loop 2312 if (deadReceivers != null) { 2313 for (Receiver receiver : deadReceivers) { 2314 removeUpdatesLocked(receiver); 2315 } 2316 } 2317 } 2318 } 2319 }; 2320 2321 // Geocoder 2322 2323 @Override 2324 public boolean geocoderIsPresent() { 2325 return mGeocodeProvider != null; 2326 } 2327 2328 @Override 2329 public String getFromLocation(double latitude, double longitude, int maxResults, 2330 GeocoderParams params, List<Address> addrs) { 2331 if (mGeocodeProvider != null) { 2332 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 2333 params, addrs); 2334 } 2335 return null; 2336 } 2337 2338 2339 @Override 2340 public String getFromLocationName(String locationName, 2341 double lowerLeftLatitude, double lowerLeftLongitude, 2342 double upperRightLatitude, double upperRightLongitude, int maxResults, 2343 GeocoderParams params, List<Address> addrs) { 2344 2345 if (mGeocodeProvider != null) { 2346 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 2347 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 2348 maxResults, params, addrs); 2349 } 2350 return null; 2351 } 2352 2353 // Mock Providers 2354 2355 private void checkMockPermissionsSafe() { 2356 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 2357 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 2358 if (!allowMocks) { 2359 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 2360 } 2361 2362 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 2363 PackageManager.PERMISSION_GRANTED) { 2364 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 2365 } 2366 } 2367 2368 @Override 2369 public void addTestProvider(String name, ProviderProperties properties) { 2370 checkMockPermissionsSafe(); 2371 2372 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 2373 throw new IllegalArgumentException("Cannot mock the passive location provider"); 2374 } 2375 2376 long identity = Binder.clearCallingIdentity(); 2377 synchronized (mLock) { 2378 // remove the real provider if we are replacing GPS or network provider 2379 if (LocationManager.GPS_PROVIDER.equals(name) 2380 || LocationManager.NETWORK_PROVIDER.equals(name) 2381 || LocationManager.FUSED_PROVIDER.equals(name)) { 2382 LocationProviderInterface p = mProvidersByName.get(name); 2383 if (p != null) { 2384 removeProviderLocked(p); 2385 } 2386 } 2387 addTestProviderLocked(name, properties); 2388 updateProvidersLocked(); 2389 } 2390 Binder.restoreCallingIdentity(identity); 2391 } 2392 2393 private void addTestProviderLocked(String name, ProviderProperties properties) { 2394 if (mProvidersByName.get(name) != null) { 2395 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 2396 } 2397 MockProvider provider = new MockProvider(name, this, properties); 2398 addProviderLocked(provider); 2399 mMockProviders.put(name, provider); 2400 mLastLocation.put(name, null); 2401 mLastLocationCoarseInterval.put(name, null); 2402 } 2403 2404 @Override 2405 public void removeTestProvider(String provider) { 2406 checkMockPermissionsSafe(); 2407 synchronized (mLock) { 2408 2409 // These methods can't be called after removing the test provider, so first make sure 2410 // we don't leave anything dangling. 2411 clearTestProviderEnabled(provider); 2412 clearTestProviderLocation(provider); 2413 clearTestProviderStatus(provider); 2414 2415 MockProvider mockProvider = mMockProviders.remove(provider); 2416 if (mockProvider == null) { 2417 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2418 } 2419 long identity = Binder.clearCallingIdentity(); 2420 removeProviderLocked(mProvidersByName.get(provider)); 2421 2422 // reinstate real provider if available 2423 LocationProviderInterface realProvider = mRealProviders.get(provider); 2424 if (realProvider != null) { 2425 addProviderLocked(realProvider); 2426 } 2427 mLastLocation.put(provider, null); 2428 mLastLocationCoarseInterval.put(provider, null); 2429 updateProvidersLocked(); 2430 Binder.restoreCallingIdentity(identity); 2431 } 2432 } 2433 2434 @Override 2435 public void setTestProviderLocation(String provider, Location loc) { 2436 checkMockPermissionsSafe(); 2437 synchronized (mLock) { 2438 MockProvider mockProvider = mMockProviders.get(provider); 2439 if (mockProvider == null) { 2440 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2441 } 2442 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 2443 long identity = Binder.clearCallingIdentity(); 2444 mockProvider.setLocation(loc); 2445 Binder.restoreCallingIdentity(identity); 2446 } 2447 } 2448 2449 @Override 2450 public void clearTestProviderLocation(String provider) { 2451 checkMockPermissionsSafe(); 2452 synchronized (mLock) { 2453 MockProvider mockProvider = mMockProviders.get(provider); 2454 if (mockProvider == null) { 2455 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2456 } 2457 mockProvider.clearLocation(); 2458 } 2459 } 2460 2461 @Override 2462 public void setTestProviderEnabled(String provider, boolean enabled) { 2463 checkMockPermissionsSafe(); 2464 synchronized (mLock) { 2465 MockProvider mockProvider = mMockProviders.get(provider); 2466 if (mockProvider == null) { 2467 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2468 } 2469 long identity = Binder.clearCallingIdentity(); 2470 if (enabled) { 2471 mockProvider.enable(); 2472 mEnabledProviders.add(provider); 2473 mDisabledProviders.remove(provider); 2474 } else { 2475 mockProvider.disable(); 2476 mEnabledProviders.remove(provider); 2477 mDisabledProviders.add(provider); 2478 } 2479 updateProvidersLocked(); 2480 Binder.restoreCallingIdentity(identity); 2481 } 2482 } 2483 2484 @Override 2485 public void clearTestProviderEnabled(String provider) { 2486 checkMockPermissionsSafe(); 2487 synchronized (mLock) { 2488 MockProvider mockProvider = mMockProviders.get(provider); 2489 if (mockProvider == null) { 2490 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2491 } 2492 long identity = Binder.clearCallingIdentity(); 2493 mEnabledProviders.remove(provider); 2494 mDisabledProviders.remove(provider); 2495 updateProvidersLocked(); 2496 Binder.restoreCallingIdentity(identity); 2497 } 2498 } 2499 2500 @Override 2501 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 2502 checkMockPermissionsSafe(); 2503 synchronized (mLock) { 2504 MockProvider mockProvider = mMockProviders.get(provider); 2505 if (mockProvider == null) { 2506 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2507 } 2508 mockProvider.setStatus(status, extras, updateTime); 2509 } 2510 } 2511 2512 @Override 2513 public void clearTestProviderStatus(String provider) { 2514 checkMockPermissionsSafe(); 2515 synchronized (mLock) { 2516 MockProvider mockProvider = mMockProviders.get(provider); 2517 if (mockProvider == null) { 2518 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2519 } 2520 mockProvider.clearStatus(); 2521 } 2522 } 2523 2524 private void log(String log) { 2525 if (Log.isLoggable(TAG, Log.VERBOSE)) { 2526 Slog.d(TAG, log); 2527 } 2528 } 2529 2530 @Override 2531 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2532 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2533 != PackageManager.PERMISSION_GRANTED) { 2534 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2535 + Binder.getCallingPid() 2536 + ", uid=" + Binder.getCallingUid()); 2537 return; 2538 } 2539 2540 synchronized (mLock) { 2541 pw.println("Current Location Manager state:"); 2542 pw.println(" Location Listeners:"); 2543 for (Receiver receiver : mReceivers.values()) { 2544 pw.println(" " + receiver); 2545 } 2546 pw.println(" Active Records by Provider:"); 2547 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2548 pw.println(" " + entry.getKey() + ":"); 2549 for (UpdateRecord record : entry.getValue()) { 2550 pw.println(" " + record); 2551 } 2552 } 2553 pw.println(" Historical Records by Provider:"); 2554 for (Map.Entry<PackageProviderKey, PackageStatistics> entry 2555 : mRequestStatistics.statistics.entrySet()) { 2556 PackageProviderKey key = entry.getKey(); 2557 PackageStatistics stats = entry.getValue(); 2558 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats); 2559 } 2560 pw.println(" Last Known Locations:"); 2561 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2562 String provider = entry.getKey(); 2563 Location location = entry.getValue(); 2564 pw.println(" " + provider + ": " + location); 2565 } 2566 2567 pw.println(" Last Known Locations Coarse Intervals:"); 2568 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) { 2569 String provider = entry.getKey(); 2570 Location location = entry.getValue(); 2571 pw.println(" " + provider + ": " + location); 2572 } 2573 2574 mGeofenceManager.dump(pw); 2575 2576 if (mEnabledProviders.size() > 0) { 2577 pw.println(" Enabled Providers:"); 2578 for (String i : mEnabledProviders) { 2579 pw.println(" " + i); 2580 } 2581 2582 } 2583 if (mDisabledProviders.size() > 0) { 2584 pw.println(" Disabled Providers:"); 2585 for (String i : mDisabledProviders) { 2586 pw.println(" " + i); 2587 } 2588 } 2589 pw.append(" "); 2590 mBlacklist.dump(pw); 2591 if (mMockProviders.size() > 0) { 2592 pw.println(" Mock Providers:"); 2593 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2594 i.getValue().dump(pw, " "); 2595 } 2596 } 2597 2598 pw.append(" fudger: "); 2599 mLocationFudger.dump(fd, pw, args); 2600 2601 if (args.length > 0 && "short".equals(args[0])) { 2602 return; 2603 } 2604 for (LocationProviderInterface provider: mProviders) { 2605 pw.print(provider.getName() + " Internal State"); 2606 if (provider instanceof LocationProviderProxy) { 2607 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2608 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2609 } 2610 pw.println(":"); 2611 provider.dump(fd, pw, args); 2612 } 2613 } 2614 } 2615} 2616