LocationManagerService.java revision 5241a4cb55b4015549242ac7d8aa5c99e5f157e5
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 mReceivers.put(binder, receiver); 1459 1460 try { 1461 receiver.getListener().asBinder().linkToDeath(receiver, 0); 1462 } catch (RemoteException e) { 1463 Slog.e(TAG, "linkToDeath failed:", e); 1464 return null; 1465 } 1466 } 1467 return receiver; 1468 } 1469 1470 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName, 1471 WorkSource workSource, boolean hideFromAppOps) { 1472 Receiver receiver = mReceivers.get(intent); 1473 if (receiver == null) { 1474 receiver = new Receiver(null, intent, pid, uid, packageName, workSource, 1475 hideFromAppOps); 1476 mReceivers.put(intent, receiver); 1477 } 1478 return receiver; 1479 } 1480 1481 /** 1482 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution 1483 * and consistency requirements. 1484 * 1485 * @param request the LocationRequest from which to create a sanitized version 1486 * @return a version of request that meets the given resolution and consistency requirements 1487 * @hide 1488 */ 1489 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) { 1490 LocationRequest sanitizedRequest = new LocationRequest(request); 1491 if (resolutionLevel < RESOLUTION_LEVEL_FINE) { 1492 switch (sanitizedRequest.getQuality()) { 1493 case LocationRequest.ACCURACY_FINE: 1494 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK); 1495 break; 1496 case LocationRequest.POWER_HIGH: 1497 sanitizedRequest.setQuality(LocationRequest.POWER_LOW); 1498 break; 1499 } 1500 // throttle 1501 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1502 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS); 1503 } 1504 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1505 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS); 1506 } 1507 } 1508 // make getFastestInterval() the minimum of interval and fastest interval 1509 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) { 1510 request.setFastestInterval(request.getInterval()); 1511 } 1512 return sanitizedRequest; 1513 } 1514 1515 private void checkPackageName(String packageName) { 1516 if (packageName == null) { 1517 throw new SecurityException("invalid package name: " + packageName); 1518 } 1519 int uid = Binder.getCallingUid(); 1520 String[] packages = mPackageManager.getPackagesForUid(uid); 1521 if (packages == null) { 1522 throw new SecurityException("invalid UID " + uid); 1523 } 1524 for (String pkg : packages) { 1525 if (packageName.equals(pkg)) return; 1526 } 1527 throw new SecurityException("invalid package name: " + packageName); 1528 } 1529 1530 private void checkPendingIntent(PendingIntent intent) { 1531 if (intent == null) { 1532 throw new IllegalArgumentException("invalid pending intent: " + intent); 1533 } 1534 } 1535 1536 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent, 1537 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) { 1538 if (intent == null && listener == null) { 1539 throw new IllegalArgumentException("need either listener or intent"); 1540 } else if (intent != null && listener != null) { 1541 throw new IllegalArgumentException("cannot register both listener and intent"); 1542 } else if (intent != null) { 1543 checkPendingIntent(intent); 1544 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps); 1545 } else { 1546 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps); 1547 } 1548 } 1549 1550 @Override 1551 public void requestLocationUpdates(LocationRequest request, ILocationListener listener, 1552 PendingIntent intent, String packageName) { 1553 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1554 checkPackageName(packageName); 1555 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1556 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1557 request.getProvider()); 1558 WorkSource workSource = request.getWorkSource(); 1559 if (workSource != null && workSource.size() > 0) { 1560 checkDeviceStatsAllowed(); 1561 } 1562 boolean hideFromAppOps = request.getHideFromAppOps(); 1563 if (hideFromAppOps) { 1564 checkUpdateAppOpsAllowed(); 1565 } 1566 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1567 1568 final int pid = Binder.getCallingPid(); 1569 final int uid = Binder.getCallingUid(); 1570 // providers may use public location API's, need to clear identity 1571 long identity = Binder.clearCallingIdentity(); 1572 try { 1573 // We don't check for MODE_IGNORED here; we will do that when we go to deliver 1574 // a location. 1575 checkLocationAccess(uid, packageName, allowedResolutionLevel); 1576 1577 synchronized (mLock) { 1578 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid, 1579 packageName, workSource, hideFromAppOps); 1580 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName); 1581 } 1582 } finally { 1583 Binder.restoreCallingIdentity(identity); 1584 } 1585 } 1586 1587 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, 1588 int pid, int uid, String packageName) { 1589 // Figure out the provider. Either its explicitly request (legacy use cases), or 1590 // use the fused provider 1591 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1592 String name = request.getProvider(); 1593 if (name == null) { 1594 throw new IllegalArgumentException("provider name must not be null"); 1595 } 1596 1597 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) 1598 + " " + name + " " + request + " from " + packageName + "(" + uid + ")"); 1599 LocationProviderInterface provider = mProvidersByName.get(name); 1600 if (provider == null) { 1601 throw new IllegalArgumentException("provider doesn't exist: " + name); 1602 } 1603 1604 UpdateRecord record = new UpdateRecord(name, request, receiver); 1605 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record); 1606 if (oldRecord != null) { 1607 oldRecord.disposeLocked(false); 1608 } 1609 1610 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid); 1611 if (isProviderEnabled) { 1612 applyRequirementsLocked(name); 1613 } else { 1614 // Notify the listener that updates are currently disabled 1615 receiver.callProviderEnabledLocked(name, false); 1616 } 1617 // Update the monitoring here just in case multiple location requests were added to the 1618 // same receiver (this request may be high power and the initial might not have been). 1619 receiver.updateMonitoring(true); 1620 } 1621 1622 @Override 1623 public void removeUpdates(ILocationListener listener, PendingIntent intent, 1624 String packageName) { 1625 checkPackageName(packageName); 1626 1627 final int pid = Binder.getCallingPid(); 1628 final int uid = Binder.getCallingUid(); 1629 1630 synchronized (mLock) { 1631 WorkSource workSource = null; 1632 boolean hideFromAppOps = false; 1633 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid, 1634 packageName, workSource, hideFromAppOps); 1635 1636 // providers may use public location API's, need to clear identity 1637 long identity = Binder.clearCallingIdentity(); 1638 try { 1639 removeUpdatesLocked(receiver); 1640 } finally { 1641 Binder.restoreCallingIdentity(identity); 1642 } 1643 } 1644 } 1645 1646 private void removeUpdatesLocked(Receiver receiver) { 1647 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver))); 1648 1649 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 1650 receiver.getListener().asBinder().unlinkToDeath(receiver, 0); 1651 synchronized (receiver) { 1652 receiver.clearPendingBroadcastsLocked(); 1653 } 1654 } 1655 1656 receiver.updateMonitoring(false); 1657 1658 // Record which providers were associated with this listener 1659 HashSet<String> providers = new HashSet<String>(); 1660 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords; 1661 if (oldRecords != null) { 1662 // Call dispose() on the obsolete update records. 1663 for (UpdateRecord record : oldRecords.values()) { 1664 // Update statistics for historical location requests by package/provider 1665 record.disposeLocked(false); 1666 } 1667 // Accumulate providers 1668 providers.addAll(oldRecords.keySet()); 1669 } 1670 1671 // update provider 1672 for (String provider : providers) { 1673 // If provider is already disabled, don't need to do anything 1674 if (!isAllowedByCurrentUserSettingsLocked(provider)) { 1675 continue; 1676 } 1677 1678 applyRequirementsLocked(provider); 1679 } 1680 } 1681 1682 private void applyAllProviderRequirementsLocked() { 1683 for (LocationProviderInterface p : mProviders) { 1684 // If provider is already disabled, don't need to do anything 1685 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) { 1686 continue; 1687 } 1688 1689 applyRequirementsLocked(p.getName()); 1690 } 1691 } 1692 1693 @Override 1694 public Location getLastLocation(LocationRequest request, String packageName) { 1695 if (D) Log.d(TAG, "getLastLocation: " + request); 1696 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1697 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1698 checkPackageName(packageName); 1699 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1700 request.getProvider()); 1701 // no need to sanitize this request, as only the provider name is used 1702 1703 final int uid = Binder.getCallingUid(); 1704 final long identity = Binder.clearCallingIdentity(); 1705 try { 1706 if (mBlacklist.isBlacklisted(packageName)) { 1707 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + 1708 packageName); 1709 return null; 1710 } 1711 1712 if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) { 1713 if (D) Log.d(TAG, "not returning last loc for no op app: " + 1714 packageName); 1715 return null; 1716 } 1717 1718 synchronized (mLock) { 1719 // Figure out the provider. Either its explicitly request (deprecated API's), 1720 // or use the fused provider 1721 String name = request.getProvider(); 1722 if (name == null) name = LocationManager.FUSED_PROVIDER; 1723 LocationProviderInterface provider = mProvidersByName.get(name); 1724 if (provider == null) return null; 1725 1726 if (!isAllowedByUserSettingsLocked(name, uid)) return null; 1727 1728 Location location; 1729 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1730 // Make sure that an app with coarse permissions can't get frequent location 1731 // updates by calling LocationManager.getLastKnownLocation repeatedly. 1732 location = mLastLocationCoarseInterval.get(name); 1733 } else { 1734 location = mLastLocation.get(name); 1735 } 1736 if (location == null) { 1737 return null; 1738 } 1739 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1740 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1741 if (noGPSLocation != null) { 1742 return new Location(mLocationFudger.getOrCreate(noGPSLocation)); 1743 } 1744 } else { 1745 return new Location(location); 1746 } 1747 } 1748 return null; 1749 } finally { 1750 Binder.restoreCallingIdentity(identity); 1751 } 1752 } 1753 1754 @Override 1755 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, 1756 String packageName) { 1757 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1758 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1759 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel); 1760 checkPendingIntent(intent); 1761 checkPackageName(packageName); 1762 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1763 request.getProvider()); 1764 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1765 1766 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent); 1767 1768 // geo-fence manager uses the public location API, need to clear identity 1769 int uid = Binder.getCallingUid(); 1770 if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) { 1771 // temporary measure until geofences work for secondary users 1772 Log.w(TAG, "proximity alerts are currently available only to the primary user"); 1773 return; 1774 } 1775 long identity = Binder.clearCallingIdentity(); 1776 try { 1777 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel, 1778 uid, packageName); 1779 } finally { 1780 Binder.restoreCallingIdentity(identity); 1781 } 1782 } 1783 1784 @Override 1785 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { 1786 checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel()); 1787 checkPendingIntent(intent); 1788 checkPackageName(packageName); 1789 1790 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); 1791 1792 // geo-fence manager uses the public location API, need to clear identity 1793 long identity = Binder.clearCallingIdentity(); 1794 try { 1795 mGeofenceManager.removeFence(geofence, intent); 1796 } finally { 1797 Binder.restoreCallingIdentity(identity); 1798 } 1799 } 1800 1801 1802 @Override 1803 public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) { 1804 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1805 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1806 LocationManager.GPS_PROVIDER); 1807 1808 final int uid = Binder.getCallingUid(); 1809 final long ident = Binder.clearCallingIdentity(); 1810 try { 1811 if (!checkLocationAccess(uid, packageName, allowedResolutionLevel)) { 1812 return false; 1813 } 1814 } finally { 1815 Binder.restoreCallingIdentity(ident); 1816 } 1817 1818 if (mGpsStatusProvider == null) { 1819 return false; 1820 } 1821 1822 try { 1823 mGpsStatusProvider.addGpsStatusListener(listener); 1824 } catch (RemoteException e) { 1825 Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e); 1826 return false; 1827 } 1828 return true; 1829 } 1830 1831 @Override 1832 public void removeGpsStatusListener(IGpsStatusListener listener) { 1833 synchronized (mLock) { 1834 try { 1835 mGpsStatusProvider.removeGpsStatusListener(listener); 1836 } catch (Exception e) { 1837 Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e); 1838 } 1839 } 1840 } 1841 1842 @Override 1843 public boolean addGpsMeasurementsListener( 1844 IGpsMeasurementsListener listener, 1845 String packageName) { 1846 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1847 checkResolutionLevelIsSufficientForProviderUse( 1848 allowedResolutionLevel, 1849 LocationManager.GPS_PROVIDER); 1850 1851 int uid = Binder.getCallingUid(); 1852 long identity = Binder.clearCallingIdentity(); 1853 boolean hasLocationAccess; 1854 try { 1855 hasLocationAccess = checkLocationAccess(uid, packageName, allowedResolutionLevel); 1856 } finally { 1857 Binder.restoreCallingIdentity(identity); 1858 } 1859 1860 if (!hasLocationAccess || mGpsMeasurementsProvider == null) { 1861 return false; 1862 } 1863 return mGpsMeasurementsProvider.addListener(listener); 1864 } 1865 1866 @Override 1867 public void removeGpsMeasurementsListener(IGpsMeasurementsListener listener) { 1868 if (mGpsMeasurementsProvider != null) { 1869 mGpsMeasurementsProvider.removeListener(listener); 1870 } 1871 } 1872 1873 @Override 1874 public boolean addGpsNavigationMessageListener( 1875 IGpsNavigationMessageListener listener, 1876 String packageName) { 1877 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1878 checkResolutionLevelIsSufficientForProviderUse( 1879 allowedResolutionLevel, 1880 LocationManager.GPS_PROVIDER); 1881 1882 int uid = Binder.getCallingUid(); 1883 long identity = Binder.clearCallingIdentity(); 1884 boolean hasLocationAccess; 1885 try { 1886 hasLocationAccess = checkLocationAccess(uid, packageName, allowedResolutionLevel); 1887 } finally { 1888 Binder.restoreCallingIdentity(identity); 1889 } 1890 1891 if (!hasLocationAccess || mGpsNavigationMessageProvider == null) { 1892 return false; 1893 } 1894 return mGpsNavigationMessageProvider.addListener(listener); 1895 } 1896 1897 @Override 1898 public void removeGpsNavigationMessageListener(IGpsNavigationMessageListener listener) { 1899 if (mGpsNavigationMessageProvider != null) { 1900 mGpsNavigationMessageProvider.removeListener(listener); 1901 } 1902 } 1903 1904 @Override 1905 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 1906 if (provider == null) { 1907 // throw NullPointerException to remain compatible with previous implementation 1908 throw new NullPointerException(); 1909 } 1910 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1911 provider); 1912 1913 // and check for ACCESS_LOCATION_EXTRA_COMMANDS 1914 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 1915 != PackageManager.PERMISSION_GRANTED)) { 1916 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 1917 } 1918 1919 synchronized (mLock) { 1920 LocationProviderInterface p = mProvidersByName.get(provider); 1921 if (p == null) return false; 1922 1923 return p.sendExtraCommand(command, extras); 1924 } 1925 } 1926 1927 @Override 1928 public boolean sendNiResponse(int notifId, int userResponse) { 1929 if (Binder.getCallingUid() != Process.myUid()) { 1930 throw new SecurityException( 1931 "calling sendNiResponse from outside of the system is not allowed"); 1932 } 1933 try { 1934 return mNetInitiatedListener.sendNiResponse(notifId, userResponse); 1935 } catch (RemoteException e) { 1936 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); 1937 return false; 1938 } 1939 } 1940 1941 /** 1942 * @return null if the provider does not exist 1943 * @throws SecurityException if the provider is not allowed to be 1944 * accessed by the caller 1945 */ 1946 @Override 1947 public ProviderProperties getProviderProperties(String provider) { 1948 if (mProvidersByName.get(provider) == null) { 1949 return null; 1950 } 1951 1952 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1953 provider); 1954 1955 LocationProviderInterface p; 1956 synchronized (mLock) { 1957 p = mProvidersByName.get(provider); 1958 } 1959 1960 if (p == null) return null; 1961 return p.getProperties(); 1962 } 1963 1964 @Override 1965 public boolean isProviderEnabled(String provider) { 1966 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, 1967 // so we discourage its use 1968 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1969 1970 int uid = Binder.getCallingUid(); 1971 long identity = Binder.clearCallingIdentity(); 1972 try { 1973 synchronized (mLock) { 1974 LocationProviderInterface p = mProvidersByName.get(provider); 1975 if (p == null) return false; 1976 1977 return isAllowedByUserSettingsLocked(provider, uid); 1978 } 1979 } finally { 1980 Binder.restoreCallingIdentity(identity); 1981 } 1982 } 1983 1984 /** 1985 * Returns "true" if the UID belongs to a bound location provider. 1986 * 1987 * @param uid the uid 1988 * @return true if uid belongs to a bound location provider 1989 */ 1990 private boolean isUidALocationProvider(int uid) { 1991 if (uid == Process.SYSTEM_UID) { 1992 return true; 1993 } 1994 if (mGeocodeProvider != null) { 1995 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true; 1996 } 1997 for (LocationProviderProxy proxy : mProxyProviders) { 1998 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true; 1999 } 2000 return false; 2001 } 2002 2003 private void checkCallerIsProvider() { 2004 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 2005 == PackageManager.PERMISSION_GRANTED) { 2006 return; 2007 } 2008 2009 // Previously we only used the INSTALL_LOCATION_PROVIDER 2010 // check. But that is system or signature 2011 // protection level which is not flexible enough for 2012 // providers installed oustide the system image. So 2013 // also allow providers with a UID matching the 2014 // currently bound package name 2015 2016 if (isUidALocationProvider(Binder.getCallingUid())) { 2017 return; 2018 } 2019 2020 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 2021 "or UID of a currently bound location provider"); 2022 } 2023 2024 /** 2025 * Returns true if the given package belongs to the given uid. 2026 */ 2027 private boolean doesUidHavePackage(int uid, String packageName) { 2028 if (packageName == null) { 2029 return false; 2030 } 2031 String[] packageNames = mPackageManager.getPackagesForUid(uid); 2032 if (packageNames == null) { 2033 return false; 2034 } 2035 for (String name : packageNames) { 2036 if (packageName.equals(name)) { 2037 return true; 2038 } 2039 } 2040 return false; 2041 } 2042 2043 @Override 2044 public void reportLocation(Location location, boolean passive) { 2045 checkCallerIsProvider(); 2046 2047 if (!location.isComplete()) { 2048 Log.w(TAG, "Dropping incomplete location: " + location); 2049 return; 2050 } 2051 2052 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 2053 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 2054 m.arg1 = (passive ? 1 : 0); 2055 mLocationHandler.sendMessageAtFrontOfQueue(m); 2056 } 2057 2058 2059 private static boolean shouldBroadcastSafe( 2060 Location loc, Location lastLoc, UpdateRecord record, long now) { 2061 // Always broadcast the first update 2062 if (lastLoc == null) { 2063 return true; 2064 } 2065 2066 // Check whether sufficient time has passed 2067 long minTime = record.mRequest.getFastestInterval(); 2068 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) 2069 / NANOS_PER_MILLI; 2070 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 2071 return false; 2072 } 2073 2074 // Check whether sufficient distance has been traveled 2075 double minDistance = record.mRequest.getSmallestDisplacement(); 2076 if (minDistance > 0.0) { 2077 if (loc.distanceTo(lastLoc) <= minDistance) { 2078 return false; 2079 } 2080 } 2081 2082 // Check whether sufficient number of udpates is left 2083 if (record.mRequest.getNumUpdates() <= 0) { 2084 return false; 2085 } 2086 2087 // Check whether the expiry date has passed 2088 if (record.mRequest.getExpireAt() < now) { 2089 return false; 2090 } 2091 2092 return true; 2093 } 2094 2095 private void handleLocationChangedLocked(Location location, boolean passive) { 2096 if (D) Log.d(TAG, "incoming location: " + location); 2097 2098 long now = SystemClock.elapsedRealtime(); 2099 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 2100 2101 // Skip if the provider is unknown. 2102 LocationProviderInterface p = mProvidersByName.get(provider); 2103 if (p == null) return; 2104 2105 // Update last known locations 2106 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2107 Location lastNoGPSLocation = null; 2108 Location lastLocation = mLastLocation.get(provider); 2109 if (lastLocation == null) { 2110 lastLocation = new Location(provider); 2111 mLastLocation.put(provider, lastLocation); 2112 } else { 2113 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2114 if (noGPSLocation == null && lastNoGPSLocation != null) { 2115 // New location has no no-GPS location: adopt last no-GPS location. This is set 2116 // directly into location because we do not want to notify COARSE clients. 2117 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 2118 } 2119 } 2120 lastLocation.set(location); 2121 2122 // Update last known coarse interval location if enough time has passed. 2123 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider); 2124 if (lastLocationCoarseInterval == null) { 2125 lastLocationCoarseInterval = new Location(location); 2126 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval); 2127 } 2128 long timeDiffNanos = location.getElapsedRealtimeNanos() 2129 - lastLocationCoarseInterval.getElapsedRealtimeNanos(); 2130 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) { 2131 lastLocationCoarseInterval.set(location); 2132 } 2133 // Don't ever return a coarse location that is more recent than the allowed update 2134 // interval (i.e. don't allow an app to keep registering and unregistering for 2135 // location updates to overcome the minimum interval). 2136 noGPSLocation = 2137 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2138 2139 // Skip if there are no UpdateRecords for this provider. 2140 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 2141 if (records == null || records.size() == 0) return; 2142 2143 // Fetch coarse location 2144 Location coarseLocation = null; 2145 if (noGPSLocation != null) { 2146 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 2147 } 2148 2149 // Fetch latest status update time 2150 long newStatusUpdateTime = p.getStatusUpdateTime(); 2151 2152 // Get latest status 2153 Bundle extras = new Bundle(); 2154 int status = p.getStatus(extras); 2155 2156 ArrayList<Receiver> deadReceivers = null; 2157 ArrayList<UpdateRecord> deadUpdateRecords = null; 2158 2159 // Broadcast location or status to all listeners 2160 for (UpdateRecord r : records) { 2161 Receiver receiver = r.mReceiver; 2162 boolean receiverDead = false; 2163 2164 int receiverUserId = UserHandle.getUserId(receiver.mUid); 2165 if (!isCurrentProfile(receiverUserId) && !isUidALocationProvider(receiver.mUid)) { 2166 if (D) { 2167 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 2168 " (current user: " + mCurrentUserId + ", app: " + 2169 receiver.mPackageName + ")"); 2170 } 2171 continue; 2172 } 2173 2174 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 2175 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 2176 receiver.mPackageName); 2177 continue; 2178 } 2179 2180 if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName, 2181 receiver.mAllowedResolutionLevel)) { 2182 if (D) Log.d(TAG, "skipping loc update for no op app: " + 2183 receiver.mPackageName); 2184 continue; 2185 } 2186 2187 Location notifyLocation = null; 2188 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2189 notifyLocation = coarseLocation; // use coarse location 2190 } else { 2191 notifyLocation = lastLocation; // use fine location 2192 } 2193 if (notifyLocation != null) { 2194 Location lastLoc = r.mLastFixBroadcast; 2195 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) { 2196 if (lastLoc == null) { 2197 lastLoc = new Location(notifyLocation); 2198 r.mLastFixBroadcast = lastLoc; 2199 } else { 2200 lastLoc.set(notifyLocation); 2201 } 2202 if (!receiver.callLocationChangedLocked(notifyLocation)) { 2203 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 2204 receiverDead = true; 2205 } 2206 r.mRequest.decrementNumUpdates(); 2207 } 2208 } 2209 2210 long prevStatusUpdateTime = r.mLastStatusBroadcast; 2211 if ((newStatusUpdateTime > prevStatusUpdateTime) && 2212 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 2213 2214 r.mLastStatusBroadcast = newStatusUpdateTime; 2215 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 2216 receiverDead = true; 2217 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 2218 } 2219 } 2220 2221 // track expired records 2222 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) { 2223 if (deadUpdateRecords == null) { 2224 deadUpdateRecords = new ArrayList<UpdateRecord>(); 2225 } 2226 deadUpdateRecords.add(r); 2227 } 2228 // track dead receivers 2229 if (receiverDead) { 2230 if (deadReceivers == null) { 2231 deadReceivers = new ArrayList<Receiver>(); 2232 } 2233 if (!deadReceivers.contains(receiver)) { 2234 deadReceivers.add(receiver); 2235 } 2236 } 2237 } 2238 2239 // remove dead records and receivers outside the loop 2240 if (deadReceivers != null) { 2241 for (Receiver receiver : deadReceivers) { 2242 removeUpdatesLocked(receiver); 2243 } 2244 } 2245 if (deadUpdateRecords != null) { 2246 for (UpdateRecord r : deadUpdateRecords) { 2247 r.disposeLocked(true); 2248 } 2249 applyRequirementsLocked(provider); 2250 } 2251 } 2252 2253 private class LocationWorkerHandler extends Handler { 2254 public LocationWorkerHandler(Looper looper) { 2255 super(looper, null, true); 2256 } 2257 2258 @Override 2259 public void handleMessage(Message msg) { 2260 switch (msg.what) { 2261 case MSG_LOCATION_CHANGED: 2262 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 2263 break; 2264 } 2265 } 2266 } 2267 2268 private boolean isMockProvider(String provider) { 2269 synchronized (mLock) { 2270 return mMockProviders.containsKey(provider); 2271 } 2272 } 2273 2274 private void handleLocationChanged(Location location, boolean passive) { 2275 // create a working copy of the incoming Location so that the service can modify it without 2276 // disturbing the caller's copy 2277 Location myLocation = new Location(location); 2278 String provider = myLocation.getProvider(); 2279 2280 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this 2281 // bit if location did not come from a mock provider because passive/fused providers can 2282 // forward locations from mock providers, and should not grant them legitimacy in doing so. 2283 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) { 2284 myLocation.setIsFromMockProvider(true); 2285 } 2286 2287 synchronized (mLock) { 2288 if (isAllowedByCurrentUserSettingsLocked(provider)) { 2289 if (!passive) { 2290 // notify passive provider of the new location 2291 mPassiveProvider.updateLocation(myLocation); 2292 } 2293 handleLocationChangedLocked(myLocation, passive); 2294 } 2295 } 2296 } 2297 2298 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 2299 @Override 2300 public void onPackageDisappeared(String packageName, int reason) { 2301 // remove all receivers associated with this package name 2302 synchronized (mLock) { 2303 ArrayList<Receiver> deadReceivers = null; 2304 2305 for (Receiver receiver : mReceivers.values()) { 2306 if (receiver.mPackageName.equals(packageName)) { 2307 if (deadReceivers == null) { 2308 deadReceivers = new ArrayList<Receiver>(); 2309 } 2310 deadReceivers.add(receiver); 2311 } 2312 } 2313 2314 // perform removal outside of mReceivers loop 2315 if (deadReceivers != null) { 2316 for (Receiver receiver : deadReceivers) { 2317 removeUpdatesLocked(receiver); 2318 } 2319 } 2320 } 2321 } 2322 }; 2323 2324 // Geocoder 2325 2326 @Override 2327 public boolean geocoderIsPresent() { 2328 return mGeocodeProvider != null; 2329 } 2330 2331 @Override 2332 public String getFromLocation(double latitude, double longitude, int maxResults, 2333 GeocoderParams params, List<Address> addrs) { 2334 if (mGeocodeProvider != null) { 2335 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 2336 params, addrs); 2337 } 2338 return null; 2339 } 2340 2341 2342 @Override 2343 public String getFromLocationName(String locationName, 2344 double lowerLeftLatitude, double lowerLeftLongitude, 2345 double upperRightLatitude, double upperRightLongitude, int maxResults, 2346 GeocoderParams params, List<Address> addrs) { 2347 2348 if (mGeocodeProvider != null) { 2349 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 2350 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 2351 maxResults, params, addrs); 2352 } 2353 return null; 2354 } 2355 2356 // Mock Providers 2357 2358 private void checkMockPermissionsSafe() { 2359 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 2360 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 2361 if (!allowMocks) { 2362 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 2363 } 2364 2365 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 2366 PackageManager.PERMISSION_GRANTED) { 2367 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 2368 } 2369 } 2370 2371 @Override 2372 public void addTestProvider(String name, ProviderProperties properties) { 2373 checkMockPermissionsSafe(); 2374 2375 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 2376 throw new IllegalArgumentException("Cannot mock the passive location provider"); 2377 } 2378 2379 long identity = Binder.clearCallingIdentity(); 2380 synchronized (mLock) { 2381 // remove the real provider if we are replacing GPS or network provider 2382 if (LocationManager.GPS_PROVIDER.equals(name) 2383 || LocationManager.NETWORK_PROVIDER.equals(name) 2384 || LocationManager.FUSED_PROVIDER.equals(name)) { 2385 LocationProviderInterface p = mProvidersByName.get(name); 2386 if (p != null) { 2387 removeProviderLocked(p); 2388 } 2389 } 2390 addTestProviderLocked(name, properties); 2391 updateProvidersLocked(); 2392 } 2393 Binder.restoreCallingIdentity(identity); 2394 } 2395 2396 private void addTestProviderLocked(String name, ProviderProperties properties) { 2397 if (mProvidersByName.get(name) != null) { 2398 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 2399 } 2400 MockProvider provider = new MockProvider(name, this, properties); 2401 addProviderLocked(provider); 2402 mMockProviders.put(name, provider); 2403 mLastLocation.put(name, null); 2404 mLastLocationCoarseInterval.put(name, null); 2405 } 2406 2407 @Override 2408 public void removeTestProvider(String provider) { 2409 checkMockPermissionsSafe(); 2410 synchronized (mLock) { 2411 2412 // These methods can't be called after removing the test provider, so first make sure 2413 // we don't leave anything dangling. 2414 clearTestProviderEnabled(provider); 2415 clearTestProviderLocation(provider); 2416 clearTestProviderStatus(provider); 2417 2418 MockProvider mockProvider = mMockProviders.remove(provider); 2419 if (mockProvider == null) { 2420 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2421 } 2422 long identity = Binder.clearCallingIdentity(); 2423 removeProviderLocked(mProvidersByName.get(provider)); 2424 2425 // reinstate real provider if available 2426 LocationProviderInterface realProvider = mRealProviders.get(provider); 2427 if (realProvider != null) { 2428 addProviderLocked(realProvider); 2429 } 2430 mLastLocation.put(provider, null); 2431 mLastLocationCoarseInterval.put(provider, null); 2432 updateProvidersLocked(); 2433 Binder.restoreCallingIdentity(identity); 2434 } 2435 } 2436 2437 @Override 2438 public void setTestProviderLocation(String provider, Location loc) { 2439 checkMockPermissionsSafe(); 2440 synchronized (mLock) { 2441 MockProvider mockProvider = mMockProviders.get(provider); 2442 if (mockProvider == null) { 2443 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2444 } 2445 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 2446 long identity = Binder.clearCallingIdentity(); 2447 mockProvider.setLocation(loc); 2448 Binder.restoreCallingIdentity(identity); 2449 } 2450 } 2451 2452 @Override 2453 public void clearTestProviderLocation(String provider) { 2454 checkMockPermissionsSafe(); 2455 synchronized (mLock) { 2456 MockProvider mockProvider = mMockProviders.get(provider); 2457 if (mockProvider == null) { 2458 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2459 } 2460 mockProvider.clearLocation(); 2461 } 2462 } 2463 2464 @Override 2465 public void setTestProviderEnabled(String provider, boolean enabled) { 2466 checkMockPermissionsSafe(); 2467 synchronized (mLock) { 2468 MockProvider mockProvider = mMockProviders.get(provider); 2469 if (mockProvider == null) { 2470 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2471 } 2472 long identity = Binder.clearCallingIdentity(); 2473 if (enabled) { 2474 mockProvider.enable(); 2475 mEnabledProviders.add(provider); 2476 mDisabledProviders.remove(provider); 2477 } else { 2478 mockProvider.disable(); 2479 mEnabledProviders.remove(provider); 2480 mDisabledProviders.add(provider); 2481 } 2482 updateProvidersLocked(); 2483 Binder.restoreCallingIdentity(identity); 2484 } 2485 } 2486 2487 @Override 2488 public void clearTestProviderEnabled(String provider) { 2489 checkMockPermissionsSafe(); 2490 synchronized (mLock) { 2491 MockProvider mockProvider = mMockProviders.get(provider); 2492 if (mockProvider == null) { 2493 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2494 } 2495 long identity = Binder.clearCallingIdentity(); 2496 mEnabledProviders.remove(provider); 2497 mDisabledProviders.remove(provider); 2498 updateProvidersLocked(); 2499 Binder.restoreCallingIdentity(identity); 2500 } 2501 } 2502 2503 @Override 2504 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 2505 checkMockPermissionsSafe(); 2506 synchronized (mLock) { 2507 MockProvider mockProvider = mMockProviders.get(provider); 2508 if (mockProvider == null) { 2509 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2510 } 2511 mockProvider.setStatus(status, extras, updateTime); 2512 } 2513 } 2514 2515 @Override 2516 public void clearTestProviderStatus(String provider) { 2517 checkMockPermissionsSafe(); 2518 synchronized (mLock) { 2519 MockProvider mockProvider = mMockProviders.get(provider); 2520 if (mockProvider == null) { 2521 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2522 } 2523 mockProvider.clearStatus(); 2524 } 2525 } 2526 2527 private void log(String log) { 2528 if (Log.isLoggable(TAG, Log.VERBOSE)) { 2529 Slog.d(TAG, log); 2530 } 2531 } 2532 2533 @Override 2534 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2535 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2536 != PackageManager.PERMISSION_GRANTED) { 2537 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2538 + Binder.getCallingPid() 2539 + ", uid=" + Binder.getCallingUid()); 2540 return; 2541 } 2542 2543 synchronized (mLock) { 2544 pw.println("Current Location Manager state:"); 2545 pw.println(" Location Listeners:"); 2546 for (Receiver receiver : mReceivers.values()) { 2547 pw.println(" " + receiver); 2548 } 2549 pw.println(" Active Records by Provider:"); 2550 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2551 pw.println(" " + entry.getKey() + ":"); 2552 for (UpdateRecord record : entry.getValue()) { 2553 pw.println(" " + record); 2554 } 2555 } 2556 pw.println(" Historical Records by Provider:"); 2557 for (Map.Entry<PackageProviderKey, PackageStatistics> entry 2558 : mRequestStatistics.statistics.entrySet()) { 2559 PackageProviderKey key = entry.getKey(); 2560 PackageStatistics stats = entry.getValue(); 2561 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats); 2562 } 2563 pw.println(" Last Known Locations:"); 2564 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2565 String provider = entry.getKey(); 2566 Location location = entry.getValue(); 2567 pw.println(" " + provider + ": " + location); 2568 } 2569 2570 pw.println(" Last Known Locations Coarse Intervals:"); 2571 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) { 2572 String provider = entry.getKey(); 2573 Location location = entry.getValue(); 2574 pw.println(" " + provider + ": " + location); 2575 } 2576 2577 mGeofenceManager.dump(pw); 2578 2579 if (mEnabledProviders.size() > 0) { 2580 pw.println(" Enabled Providers:"); 2581 for (String i : mEnabledProviders) { 2582 pw.println(" " + i); 2583 } 2584 2585 } 2586 if (mDisabledProviders.size() > 0) { 2587 pw.println(" Disabled Providers:"); 2588 for (String i : mDisabledProviders) { 2589 pw.println(" " + i); 2590 } 2591 } 2592 pw.append(" "); 2593 mBlacklist.dump(pw); 2594 if (mMockProviders.size() > 0) { 2595 pw.println(" Mock Providers:"); 2596 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2597 i.getValue().dump(pw, " "); 2598 } 2599 } 2600 2601 pw.append(" fudger: "); 2602 mLocationFudger.dump(fd, pw, args); 2603 2604 if (args.length > 0 && "short".equals(args[0])) { 2605 return; 2606 } 2607 for (LocationProviderInterface provider: mProviders) { 2608 pw.print(provider.getName() + " Internal State"); 2609 if (provider instanceof LocationProviderProxy) { 2610 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2611 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2612 } 2613 pw.println(":"); 2614 provider.dump(fd, pw, args); 2615 } 2616 } 2617 } 2618} 2619