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