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