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