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