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