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