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