LocationManagerService.java revision adc1cf46045ae756d3a9ccbccf6b0f894e4c1edd
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 @Override 1976 public boolean isProviderEnabled(String provider) { 1977 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, 1978 // so we discourage its use 1979 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1980 1981 int uid = Binder.getCallingUid(); 1982 long identity = Binder.clearCallingIdentity(); 1983 try { 1984 synchronized (mLock) { 1985 LocationProviderInterface p = mProvidersByName.get(provider); 1986 if (p == null) return false; 1987 1988 return isAllowedByUserSettingsLocked(provider, uid); 1989 } 1990 } finally { 1991 Binder.restoreCallingIdentity(identity); 1992 } 1993 } 1994 1995 /** 1996 * Returns "true" if the UID belongs to a bound location provider. 1997 * 1998 * @param uid the uid 1999 * @return true if uid belongs to a bound location provider 2000 */ 2001 private boolean isUidALocationProvider(int uid) { 2002 if (uid == Process.SYSTEM_UID) { 2003 return true; 2004 } 2005 if (mGeocodeProvider != null) { 2006 if (doesUidHavePackage(uid, mGeocodeProvider.getConnectedPackageName())) return true; 2007 } 2008 for (LocationProviderProxy proxy : mProxyProviders) { 2009 if (doesUidHavePackage(uid, proxy.getConnectedPackageName())) return true; 2010 } 2011 return false; 2012 } 2013 2014 private void checkCallerIsProvider() { 2015 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 2016 == PackageManager.PERMISSION_GRANTED) { 2017 return; 2018 } 2019 2020 // Previously we only used the INSTALL_LOCATION_PROVIDER 2021 // check. But that is system or signature 2022 // protection level which is not flexible enough for 2023 // providers installed oustide the system image. So 2024 // also allow providers with a UID matching the 2025 // currently bound package name 2026 2027 if (isUidALocationProvider(Binder.getCallingUid())) { 2028 return; 2029 } 2030 2031 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 2032 "or UID of a currently bound location provider"); 2033 } 2034 2035 /** 2036 * Returns true if the given package belongs to the given uid. 2037 */ 2038 private boolean doesUidHavePackage(int uid, String packageName) { 2039 if (packageName == null) { 2040 return false; 2041 } 2042 String[] packageNames = mPackageManager.getPackagesForUid(uid); 2043 if (packageNames == null) { 2044 return false; 2045 } 2046 for (String name : packageNames) { 2047 if (packageName.equals(name)) { 2048 return true; 2049 } 2050 } 2051 return false; 2052 } 2053 2054 @Override 2055 public void reportLocation(Location location, boolean passive) { 2056 checkCallerIsProvider(); 2057 2058 if (!location.isComplete()) { 2059 Log.w(TAG, "Dropping incomplete location: " + location); 2060 return; 2061 } 2062 2063 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 2064 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 2065 m.arg1 = (passive ? 1 : 0); 2066 mLocationHandler.sendMessageAtFrontOfQueue(m); 2067 } 2068 2069 2070 private static boolean shouldBroadcastSafe( 2071 Location loc, Location lastLoc, UpdateRecord record, long now) { 2072 // Always broadcast the first update 2073 if (lastLoc == null) { 2074 return true; 2075 } 2076 2077 // Check whether sufficient time has passed 2078 long minTime = record.mRequest.getFastestInterval(); 2079 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) 2080 / NANOS_PER_MILLI; 2081 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 2082 return false; 2083 } 2084 2085 // Check whether sufficient distance has been traveled 2086 double minDistance = record.mRequest.getSmallestDisplacement(); 2087 if (minDistance > 0.0) { 2088 if (loc.distanceTo(lastLoc) <= minDistance) { 2089 return false; 2090 } 2091 } 2092 2093 // Check whether sufficient number of udpates is left 2094 if (record.mRequest.getNumUpdates() <= 0) { 2095 return false; 2096 } 2097 2098 // Check whether the expiry date has passed 2099 if (record.mRequest.getExpireAt() < now) { 2100 return false; 2101 } 2102 2103 return true; 2104 } 2105 2106 private void handleLocationChangedLocked(Location location, boolean passive) { 2107 if (D) Log.d(TAG, "incoming location: " + location); 2108 2109 long now = SystemClock.elapsedRealtime(); 2110 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 2111 2112 // Skip if the provider is unknown. 2113 LocationProviderInterface p = mProvidersByName.get(provider); 2114 if (p == null) return; 2115 2116 // Update last known locations 2117 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2118 Location lastNoGPSLocation = null; 2119 Location lastLocation = mLastLocation.get(provider); 2120 if (lastLocation == null) { 2121 lastLocation = new Location(provider); 2122 mLastLocation.put(provider, lastLocation); 2123 } else { 2124 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2125 if (noGPSLocation == null && lastNoGPSLocation != null) { 2126 // New location has no no-GPS location: adopt last no-GPS location. This is set 2127 // directly into location because we do not want to notify COARSE clients. 2128 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 2129 } 2130 } 2131 lastLocation.set(location); 2132 2133 // Update last known coarse interval location if enough time has passed. 2134 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider); 2135 if (lastLocationCoarseInterval == null) { 2136 lastLocationCoarseInterval = new Location(location); 2137 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval); 2138 } 2139 long timeDiffNanos = location.getElapsedRealtimeNanos() 2140 - lastLocationCoarseInterval.getElapsedRealtimeNanos(); 2141 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) { 2142 lastLocationCoarseInterval.set(location); 2143 } 2144 // Don't ever return a coarse location that is more recent than the allowed update 2145 // interval (i.e. don't allow an app to keep registering and unregistering for 2146 // location updates to overcome the minimum interval). 2147 noGPSLocation = 2148 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 2149 2150 // Skip if there are no UpdateRecords for this provider. 2151 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 2152 if (records == null || records.size() == 0) return; 2153 2154 // Fetch coarse location 2155 Location coarseLocation = null; 2156 if (noGPSLocation != null) { 2157 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 2158 } 2159 2160 // Fetch latest status update time 2161 long newStatusUpdateTime = p.getStatusUpdateTime(); 2162 2163 // Get latest status 2164 Bundle extras = new Bundle(); 2165 int status = p.getStatus(extras); 2166 2167 ArrayList<Receiver> deadReceivers = null; 2168 ArrayList<UpdateRecord> deadUpdateRecords = null; 2169 2170 // Broadcast location or status to all listeners 2171 for (UpdateRecord r : records) { 2172 Receiver receiver = r.mReceiver; 2173 boolean receiverDead = false; 2174 2175 int receiverUserId = UserHandle.getUserId(receiver.mUid); 2176 if (!isCurrentProfile(receiverUserId) && !isUidALocationProvider(receiver.mUid)) { 2177 if (D) { 2178 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 2179 " (current user: " + mCurrentUserId + ", app: " + 2180 receiver.mPackageName + ")"); 2181 } 2182 continue; 2183 } 2184 2185 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 2186 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 2187 receiver.mPackageName); 2188 continue; 2189 } 2190 2191 if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName, 2192 receiver.mAllowedResolutionLevel)) { 2193 if (D) Log.d(TAG, "skipping loc update for no op app: " + 2194 receiver.mPackageName); 2195 continue; 2196 } 2197 2198 Location notifyLocation = null; 2199 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2200 notifyLocation = coarseLocation; // use coarse location 2201 } else { 2202 notifyLocation = lastLocation; // use fine location 2203 } 2204 if (notifyLocation != null) { 2205 Location lastLoc = r.mLastFixBroadcast; 2206 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) { 2207 if (lastLoc == null) { 2208 lastLoc = new Location(notifyLocation); 2209 r.mLastFixBroadcast = lastLoc; 2210 } else { 2211 lastLoc.set(notifyLocation); 2212 } 2213 if (!receiver.callLocationChangedLocked(notifyLocation)) { 2214 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 2215 receiverDead = true; 2216 } 2217 r.mRequest.decrementNumUpdates(); 2218 } 2219 } 2220 2221 long prevStatusUpdateTime = r.mLastStatusBroadcast; 2222 if ((newStatusUpdateTime > prevStatusUpdateTime) && 2223 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 2224 2225 r.mLastStatusBroadcast = newStatusUpdateTime; 2226 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 2227 receiverDead = true; 2228 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 2229 } 2230 } 2231 2232 // track expired records 2233 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) { 2234 if (deadUpdateRecords == null) { 2235 deadUpdateRecords = new ArrayList<UpdateRecord>(); 2236 } 2237 deadUpdateRecords.add(r); 2238 } 2239 // track dead receivers 2240 if (receiverDead) { 2241 if (deadReceivers == null) { 2242 deadReceivers = new ArrayList<Receiver>(); 2243 } 2244 if (!deadReceivers.contains(receiver)) { 2245 deadReceivers.add(receiver); 2246 } 2247 } 2248 } 2249 2250 // remove dead records and receivers outside the loop 2251 if (deadReceivers != null) { 2252 for (Receiver receiver : deadReceivers) { 2253 removeUpdatesLocked(receiver); 2254 } 2255 } 2256 if (deadUpdateRecords != null) { 2257 for (UpdateRecord r : deadUpdateRecords) { 2258 r.disposeLocked(true); 2259 } 2260 applyRequirementsLocked(provider); 2261 } 2262 } 2263 2264 private class LocationWorkerHandler extends Handler { 2265 public LocationWorkerHandler(Looper looper) { 2266 super(looper, null, true); 2267 } 2268 2269 @Override 2270 public void handleMessage(Message msg) { 2271 switch (msg.what) { 2272 case MSG_LOCATION_CHANGED: 2273 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 2274 break; 2275 } 2276 } 2277 } 2278 2279 private boolean isMockProvider(String provider) { 2280 synchronized (mLock) { 2281 return mMockProviders.containsKey(provider); 2282 } 2283 } 2284 2285 private void handleLocationChanged(Location location, boolean passive) { 2286 // create a working copy of the incoming Location so that the service can modify it without 2287 // disturbing the caller's copy 2288 Location myLocation = new Location(location); 2289 String provider = myLocation.getProvider(); 2290 2291 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this 2292 // bit if location did not come from a mock provider because passive/fused providers can 2293 // forward locations from mock providers, and should not grant them legitimacy in doing so. 2294 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) { 2295 myLocation.setIsFromMockProvider(true); 2296 } 2297 2298 synchronized (mLock) { 2299 if (isAllowedByCurrentUserSettingsLocked(provider)) { 2300 if (!passive) { 2301 // notify passive provider of the new location 2302 mPassiveProvider.updateLocation(myLocation); 2303 } 2304 handleLocationChangedLocked(myLocation, passive); 2305 } 2306 } 2307 } 2308 2309 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 2310 @Override 2311 public void onPackageDisappeared(String packageName, int reason) { 2312 // remove all receivers associated with this package name 2313 synchronized (mLock) { 2314 ArrayList<Receiver> deadReceivers = null; 2315 2316 for (Receiver receiver : mReceivers.values()) { 2317 if (receiver.mPackageName.equals(packageName)) { 2318 if (deadReceivers == null) { 2319 deadReceivers = new ArrayList<Receiver>(); 2320 } 2321 deadReceivers.add(receiver); 2322 } 2323 } 2324 2325 // perform removal outside of mReceivers loop 2326 if (deadReceivers != null) { 2327 for (Receiver receiver : deadReceivers) { 2328 removeUpdatesLocked(receiver); 2329 } 2330 } 2331 } 2332 } 2333 }; 2334 2335 // Geocoder 2336 2337 @Override 2338 public boolean geocoderIsPresent() { 2339 return mGeocodeProvider != null; 2340 } 2341 2342 @Override 2343 public String getFromLocation(double latitude, double longitude, int maxResults, 2344 GeocoderParams params, List<Address> addrs) { 2345 if (mGeocodeProvider != null) { 2346 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 2347 params, addrs); 2348 } 2349 return null; 2350 } 2351 2352 2353 @Override 2354 public String getFromLocationName(String locationName, 2355 double lowerLeftLatitude, double lowerLeftLongitude, 2356 double upperRightLatitude, double upperRightLongitude, int maxResults, 2357 GeocoderParams params, List<Address> addrs) { 2358 2359 if (mGeocodeProvider != null) { 2360 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 2361 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 2362 maxResults, params, addrs); 2363 } 2364 return null; 2365 } 2366 2367 // Mock Providers 2368 2369 private boolean canCallerAccessMockLocation(String opPackageName) { 2370 return mAppOps.noteOp(AppOpsManager.OP_MOCK_LOCATION, Binder.getCallingUid(), 2371 opPackageName) == AppOpsManager.MODE_ALLOWED; 2372 } 2373 2374 @Override 2375 public void addTestProvider(String name, ProviderProperties properties, String opPackageName) { 2376 if (!canCallerAccessMockLocation(opPackageName)) { 2377 return; 2378 } 2379 2380 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 2381 throw new IllegalArgumentException("Cannot mock the passive location provider"); 2382 } 2383 2384 long identity = Binder.clearCallingIdentity(); 2385 synchronized (mLock) { 2386 // remove the real provider if we are replacing GPS or network provider 2387 if (LocationManager.GPS_PROVIDER.equals(name) 2388 || LocationManager.NETWORK_PROVIDER.equals(name) 2389 || LocationManager.FUSED_PROVIDER.equals(name)) { 2390 LocationProviderInterface p = mProvidersByName.get(name); 2391 if (p != null) { 2392 removeProviderLocked(p); 2393 } 2394 } 2395 addTestProviderLocked(name, properties); 2396 updateProvidersLocked(); 2397 } 2398 Binder.restoreCallingIdentity(identity); 2399 } 2400 2401 private void addTestProviderLocked(String name, ProviderProperties properties) { 2402 if (mProvidersByName.get(name) != null) { 2403 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 2404 } 2405 MockProvider provider = new MockProvider(name, this, properties); 2406 addProviderLocked(provider); 2407 mMockProviders.put(name, provider); 2408 mLastLocation.put(name, null); 2409 mLastLocationCoarseInterval.put(name, null); 2410 } 2411 2412 @Override 2413 public void removeTestProvider(String provider, String opPackageName) { 2414 if (!canCallerAccessMockLocation(opPackageName)) { 2415 return; 2416 } 2417 2418 synchronized (mLock) { 2419 2420 // These methods can't be called after removing the test provider, so first make sure 2421 // we don't leave anything dangling. 2422 clearTestProviderEnabled(provider, opPackageName); 2423 clearTestProviderLocation(provider, opPackageName); 2424 clearTestProviderStatus(provider, opPackageName); 2425 2426 MockProvider mockProvider = mMockProviders.remove(provider); 2427 if (mockProvider == null) { 2428 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2429 } 2430 long identity = Binder.clearCallingIdentity(); 2431 removeProviderLocked(mProvidersByName.get(provider)); 2432 2433 // reinstate real provider if available 2434 LocationProviderInterface realProvider = mRealProviders.get(provider); 2435 if (realProvider != null) { 2436 addProviderLocked(realProvider); 2437 } 2438 mLastLocation.put(provider, null); 2439 mLastLocationCoarseInterval.put(provider, null); 2440 updateProvidersLocked(); 2441 Binder.restoreCallingIdentity(identity); 2442 } 2443 } 2444 2445 @Override 2446 public void setTestProviderLocation(String provider, Location loc, String opPackageName) { 2447 if (!canCallerAccessMockLocation(opPackageName)) { 2448 return; 2449 } 2450 2451 synchronized (mLock) { 2452 MockProvider mockProvider = mMockProviders.get(provider); 2453 if (mockProvider == null) { 2454 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2455 } 2456 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 2457 long identity = Binder.clearCallingIdentity(); 2458 mockProvider.setLocation(loc); 2459 Binder.restoreCallingIdentity(identity); 2460 } 2461 } 2462 2463 @Override 2464 public void clearTestProviderLocation(String provider, String opPackageName) { 2465 if (!canCallerAccessMockLocation(opPackageName)) { 2466 return; 2467 } 2468 2469 synchronized (mLock) { 2470 MockProvider mockProvider = mMockProviders.get(provider); 2471 if (mockProvider == null) { 2472 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2473 } 2474 mockProvider.clearLocation(); 2475 } 2476 } 2477 2478 @Override 2479 public void setTestProviderEnabled(String provider, boolean enabled, String opPackageName) { 2480 if (!canCallerAccessMockLocation(opPackageName)) { 2481 return; 2482 } 2483 2484 synchronized (mLock) { 2485 MockProvider mockProvider = mMockProviders.get(provider); 2486 if (mockProvider == null) { 2487 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2488 } 2489 long identity = Binder.clearCallingIdentity(); 2490 if (enabled) { 2491 mockProvider.enable(); 2492 mEnabledProviders.add(provider); 2493 mDisabledProviders.remove(provider); 2494 } else { 2495 mockProvider.disable(); 2496 mEnabledProviders.remove(provider); 2497 mDisabledProviders.add(provider); 2498 } 2499 updateProvidersLocked(); 2500 Binder.restoreCallingIdentity(identity); 2501 } 2502 } 2503 2504 @Override 2505 public void clearTestProviderEnabled(String provider, String opPackageName) { 2506 if (!canCallerAccessMockLocation(opPackageName)) { 2507 return; 2508 } 2509 2510 synchronized (mLock) { 2511 MockProvider mockProvider = mMockProviders.get(provider); 2512 if (mockProvider == null) { 2513 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2514 } 2515 long identity = Binder.clearCallingIdentity(); 2516 mEnabledProviders.remove(provider); 2517 mDisabledProviders.remove(provider); 2518 updateProvidersLocked(); 2519 Binder.restoreCallingIdentity(identity); 2520 } 2521 } 2522 2523 @Override 2524 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime, 2525 String opPackageName) { 2526 if (!canCallerAccessMockLocation(opPackageName)) { 2527 return; 2528 } 2529 2530 synchronized (mLock) { 2531 MockProvider mockProvider = mMockProviders.get(provider); 2532 if (mockProvider == null) { 2533 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2534 } 2535 mockProvider.setStatus(status, extras, updateTime); 2536 } 2537 } 2538 2539 @Override 2540 public void clearTestProviderStatus(String provider, String opPackageName) { 2541 if (!canCallerAccessMockLocation(opPackageName)) { 2542 return; 2543 } 2544 2545 synchronized (mLock) { 2546 MockProvider mockProvider = mMockProviders.get(provider); 2547 if (mockProvider == null) { 2548 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2549 } 2550 mockProvider.clearStatus(); 2551 } 2552 } 2553 2554 private void log(String log) { 2555 if (Log.isLoggable(TAG, Log.VERBOSE)) { 2556 Slog.d(TAG, log); 2557 } 2558 } 2559 2560 @Override 2561 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2562 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2563 != PackageManager.PERMISSION_GRANTED) { 2564 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2565 + Binder.getCallingPid() 2566 + ", uid=" + Binder.getCallingUid()); 2567 return; 2568 } 2569 2570 synchronized (mLock) { 2571 pw.println("Current Location Manager state:"); 2572 pw.println(" Location Listeners:"); 2573 for (Receiver receiver : mReceivers.values()) { 2574 pw.println(" " + receiver); 2575 } 2576 pw.println(" Active Records by Provider:"); 2577 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2578 pw.println(" " + entry.getKey() + ":"); 2579 for (UpdateRecord record : entry.getValue()) { 2580 pw.println(" " + record); 2581 } 2582 } 2583 pw.println(" Historical Records by Provider:"); 2584 for (Map.Entry<PackageProviderKey, PackageStatistics> entry 2585 : mRequestStatistics.statistics.entrySet()) { 2586 PackageProviderKey key = entry.getKey(); 2587 PackageStatistics stats = entry.getValue(); 2588 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats); 2589 } 2590 pw.println(" Last Known Locations:"); 2591 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2592 String provider = entry.getKey(); 2593 Location location = entry.getValue(); 2594 pw.println(" " + provider + ": " + location); 2595 } 2596 2597 pw.println(" Last Known Locations Coarse Intervals:"); 2598 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) { 2599 String provider = entry.getKey(); 2600 Location location = entry.getValue(); 2601 pw.println(" " + provider + ": " + location); 2602 } 2603 2604 mGeofenceManager.dump(pw); 2605 2606 if (mEnabledProviders.size() > 0) { 2607 pw.println(" Enabled Providers:"); 2608 for (String i : mEnabledProviders) { 2609 pw.println(" " + i); 2610 } 2611 2612 } 2613 if (mDisabledProviders.size() > 0) { 2614 pw.println(" Disabled Providers:"); 2615 for (String i : mDisabledProviders) { 2616 pw.println(" " + i); 2617 } 2618 } 2619 pw.append(" "); 2620 mBlacklist.dump(pw); 2621 if (mMockProviders.size() > 0) { 2622 pw.println(" Mock Providers:"); 2623 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2624 i.getValue().dump(pw, " "); 2625 } 2626 } 2627 2628 pw.append(" fudger: "); 2629 mLocationFudger.dump(fd, pw, args); 2630 2631 if (args.length > 0 && "short".equals(args[0])) { 2632 return; 2633 } 2634 for (LocationProviderInterface provider: mProviders) { 2635 pw.print(provider.getName() + " Internal State"); 2636 if (provider instanceof LocationProviderProxy) { 2637 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2638 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2639 } 2640 pw.println(":"); 2641 provider.dump(fd, pw, args); 2642 } 2643 } 2644 } 2645} 2646