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