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