LocationManagerService.java revision e5601ce9bfa4effbddb84186f0fe1bfe4ad50301
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.app.PendingIntent; 20import android.content.BroadcastReceiver; 21import android.content.ContentResolver; 22import android.content.Context; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.content.pm.ApplicationInfo; 26import android.content.pm.PackageInfo; 27import android.content.pm.PackageManager; 28import android.content.pm.PackageManager.NameNotFoundException; 29import android.content.pm.ResolveInfo; 30import android.content.pm.Signature; 31import android.content.res.Resources; 32import android.database.ContentObserver; 33import android.location.Address; 34import android.location.Criteria; 35import android.location.GeocoderParams; 36import android.location.Geofence; 37import android.location.IGpsStatusListener; 38import android.location.IGpsStatusProvider; 39import android.location.ILocationListener; 40import android.location.ILocationManager; 41import android.location.INetInitiatedListener; 42import android.location.Location; 43import android.location.LocationManager; 44import android.location.LocationProvider; 45import android.location.LocationRequest; 46import android.os.Binder; 47import android.os.Bundle; 48import android.os.Handler; 49import android.os.IBinder; 50import android.os.Looper; 51import android.os.Message; 52import android.os.PowerManager; 53import android.os.Process; 54import android.os.RemoteException; 55import android.os.SystemClock; 56import android.os.UserHandle; 57import android.os.WorkSource; 58import android.provider.Settings; 59import android.util.Log; 60import android.util.Slog; 61 62import com.android.internal.content.PackageMonitor; 63import com.android.internal.location.ProviderProperties; 64import com.android.internal.location.ProviderRequest; 65import com.android.server.location.GeocoderProxy; 66import com.android.server.location.GeofenceManager; 67import com.android.server.location.GpsLocationProvider; 68import com.android.server.location.LocationBlacklist; 69import com.android.server.location.LocationFudger; 70import com.android.server.location.LocationProviderInterface; 71import com.android.server.location.LocationProviderProxy; 72import com.android.server.location.MockProvider; 73import com.android.server.location.PassiveProvider; 74 75import java.io.FileDescriptor; 76import java.io.PrintWriter; 77import java.util.ArrayList; 78import java.util.Arrays; 79import java.util.HashMap; 80import java.util.HashSet; 81import java.util.List; 82import java.util.Map; 83import java.util.Set; 84 85/** 86 * The service class that manages LocationProviders and issues location 87 * updates and alerts. 88 */ 89public class LocationManagerService extends ILocationManager.Stub implements Runnable { 90 private static final String TAG = "LocationManagerService"; 91 public static final boolean D = false; 92 93 private static final String WAKELOCK_KEY = TAG; 94 private static final String THREAD_NAME = TAG; 95 96 // Location resolution level: no location data whatsoever 97 private static final int RESOLUTION_LEVEL_NONE = 0; 98 // Location resolution level: coarse location data only 99 private static final int RESOLUTION_LEVEL_COARSE = 1; 100 // Location resolution level: fine location data 101 private static final int RESOLUTION_LEVEL_FINE = 2; 102 103 private static final String ACCESS_MOCK_LOCATION = 104 android.Manifest.permission.ACCESS_MOCK_LOCATION; 105 private static final String ACCESS_LOCATION_EXTRA_COMMANDS = 106 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS; 107 private static final String INSTALL_LOCATION_PROVIDER = 108 android.Manifest.permission.INSTALL_LOCATION_PROVIDER; 109 110 private static final String NETWORK_LOCATION_SERVICE_ACTION = 111 "com.android.location.service.v2.NetworkLocationProvider"; 112 private static final String FUSED_LOCATION_SERVICE_ACTION = 113 "com.android.location.service.FusedLocationProvider"; 114 115 private static final int MSG_LOCATION_CHANGED = 1; 116 117 // Location Providers may sometimes deliver location updates 118 // slightly faster that requested - provide grace period so 119 // we don't unnecessarily filter events that are otherwise on 120 // time 121 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100; 122 123 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest(); 124 125 private final Context mContext; 126 127 // used internally for synchronization 128 private final Object mLock = new Object(); 129 130 // --- fields below are final after init() --- 131 private LocationFudger mLocationFudger; 132 private GeofenceManager mGeofenceManager; 133 private PowerManager.WakeLock mWakeLock; 134 private PackageManager mPackageManager; 135 private GeocoderProxy mGeocodeProvider; 136 private IGpsStatusProvider mGpsStatusProvider; 137 private INetInitiatedListener mNetInitiatedListener; 138 private LocationWorkerHandler mLocationHandler; 139 private PassiveProvider mPassiveProvider; // track passive provider for special cases 140 private LocationBlacklist mBlacklist; 141 142 // --- fields below are protected by mWakeLock --- 143 private int mPendingBroadcasts; 144 145 // --- fields below are protected by mLock --- 146 // Set of providers that are explicitly enabled 147 private final Set<String> mEnabledProviders = new HashSet<String>(); 148 149 // Set of providers that are explicitly disabled 150 private final Set<String> mDisabledProviders = new HashSet<String>(); 151 152 // Mock (test) providers 153 private final HashMap<String, MockProvider> mMockProviders = 154 new HashMap<String, MockProvider>(); 155 156 // all receivers 157 private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>(); 158 159 // currently installed providers (with mocks replacing real providers) 160 private final ArrayList<LocationProviderInterface> mProviders = 161 new ArrayList<LocationProviderInterface>(); 162 163 // real providers, saved here when mocked out 164 private final HashMap<String, LocationProviderInterface> mRealProviders = 165 new HashMap<String, LocationProviderInterface>(); 166 167 // mapping from provider name to provider 168 private final HashMap<String, LocationProviderInterface> mProvidersByName = 169 new HashMap<String, LocationProviderInterface>(); 170 171 // mapping from provider name to all its UpdateRecords 172 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider = 173 new HashMap<String, ArrayList<UpdateRecord>>(); 174 175 // mapping from provider name to last known location 176 private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>(); 177 178 // all providers that operate over proxy, for authorizing incoming location 179 private final ArrayList<LocationProviderProxy> mProxyProviders = 180 new ArrayList<LocationProviderProxy>(); 181 182 // current active user on the device - other users are denied location data 183 private int mCurrentUserId = UserHandle.USER_OWNER; 184 185 public LocationManagerService(Context context) { 186 super(); 187 mContext = context; 188 189 if (D) Log.d(TAG, "Constructed"); 190 191 // most startup is deferred until systemReady() 192 } 193 194 public void systemReady() { 195 Thread thread = new Thread(null, this, THREAD_NAME); 196 thread.start(); 197 } 198 199 @Override 200 public void run() { 201 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); 202 Looper.prepare(); 203 mLocationHandler = new LocationWorkerHandler(); 204 init(); 205 Looper.loop(); 206 } 207 208 private void init() { 209 if (D) Log.d(TAG, "init()"); 210 211 PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 212 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 213 mPackageManager = mContext.getPackageManager(); 214 215 mBlacklist = new LocationBlacklist(mContext, mLocationHandler); 216 mBlacklist.init(); 217 mLocationFudger = new LocationFudger(mContext, mLocationHandler); 218 219 synchronized (mLock) { 220 loadProvidersLocked(); 221 } 222 223 mGeofenceManager = new GeofenceManager(mContext, mBlacklist); 224 225 // listen for settings changes 226 mContext.getContentResolver().registerContentObserver( 227 Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true, 228 new ContentObserver(mLocationHandler) { 229 @Override 230 public void onChange(boolean selfChange) { 231 synchronized (mLock) { 232 updateProvidersLocked(); 233 } 234 } 235 }, UserHandle.USER_ALL); 236 mPackageMonitor.register(mContext, Looper.myLooper(), true); 237 238 // listen for user change 239 IntentFilter intentFilter = new IntentFilter(); 240 intentFilter.addAction(Intent.ACTION_USER_SWITCHED); 241 242 mContext.registerReceiverAsUser(new BroadcastReceiver() { 243 @Override 244 public void onReceive(Context context, Intent intent) { 245 String action = intent.getAction(); 246 if (Intent.ACTION_USER_SWITCHED.equals(action)) { 247 switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0)); 248 } 249 } 250 }, UserHandle.ALL, intentFilter, null, null); 251 252 updateProvidersLocked(); 253 } 254 255 private void ensureFallbackFusedProviderPresentLocked(ArrayList<String> pkgs) { 256 PackageManager pm = mContext.getPackageManager(); 257 String systemPackageName = mContext.getPackageName(); 258 ArrayList<HashSet<Signature>> sigSets = ServiceWatcher.getSignatureSets(mContext, pkgs); 259 260 List<ResolveInfo> rInfos = pm.queryIntentServicesAsUser( 261 new Intent(FUSED_LOCATION_SERVICE_ACTION), 262 PackageManager.GET_META_DATA, mCurrentUserId); 263 for (ResolveInfo rInfo : rInfos) { 264 String packageName = rInfo.serviceInfo.packageName; 265 266 // Check that the signature is in the list of supported sigs. If it's not in 267 // this list the standard provider binding logic won't bind to it. 268 try { 269 PackageInfo pInfo; 270 pInfo = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); 271 if (!ServiceWatcher.isSignatureMatch(pInfo.signatures, sigSets)) { 272 Log.w(TAG, packageName + " resolves service " + FUSED_LOCATION_SERVICE_ACTION + 273 ", but has wrong signature, ignoring"); 274 continue; 275 } 276 } catch (NameNotFoundException e) { 277 Log.e(TAG, "missing package: " + packageName); 278 continue; 279 } 280 281 // Get the version info 282 if (rInfo.serviceInfo.metaData == null) { 283 Log.w(TAG, "Found fused provider without metadata: " + packageName); 284 continue; 285 } 286 287 int version = rInfo.serviceInfo.metaData.getInt( 288 ServiceWatcher.EXTRA_SERVICE_VERSION, -1); 289 if (version == 0) { 290 // This should be the fallback fused location provider. 291 292 // Make sure it's in the system partition. 293 if ((rInfo.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { 294 if (D) Log.d(TAG, "Fallback candidate not in /system: " + packageName); 295 continue; 296 } 297 298 // Check that the fallback is signed the same as the OS 299 // as a proxy for coreApp="true" 300 if (pm.checkSignatures(systemPackageName, packageName) 301 != PackageManager.SIGNATURE_MATCH) { 302 if (D) Log.d(TAG, "Fallback candidate not signed the same as system: " 303 + packageName); 304 continue; 305 } 306 307 // Found a valid fallback. 308 if (D) Log.d(TAG, "Found fallback provider: " + packageName); 309 return; 310 } else { 311 if (D) Log.d(TAG, "Fallback candidate not version 0: " + packageName); 312 } 313 } 314 315 throw new IllegalStateException("Unable to find a fused location provider that is in the " 316 + "system partition with version 0 and signed with the platform certificate. " 317 + "Such a package is needed to provide a default fused location provider in the " 318 + "event that no other fused location provider has been installed or is currently " 319 + "available. For example, coreOnly boot mode when decrypting the data " 320 + "partition. The fallback must also be marked coreApp=\"true\" in the manifest"); 321 } 322 323 private void loadProvidersLocked() { 324 // create a passive location provider, which is always enabled 325 PassiveProvider passiveProvider = new PassiveProvider(this); 326 addProviderLocked(passiveProvider); 327 mEnabledProviders.add(passiveProvider.getName()); 328 mPassiveProvider = passiveProvider; 329 330 if (GpsLocationProvider.isSupported()) { 331 // Create a gps location provider 332 GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this); 333 mGpsStatusProvider = gpsProvider.getGpsStatusProvider(); 334 mNetInitiatedListener = gpsProvider.getNetInitiatedListener(); 335 addProviderLocked(gpsProvider); 336 mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider); 337 } 338 339 /* 340 Load package name(s) containing location provider support. 341 These packages can contain services implementing location providers: 342 Geocoder Provider, Network Location Provider, and 343 Fused Location Provider. They will each be searched for 344 service components implementing these providers. 345 The location framework also has support for installation 346 of new location providers at run-time. The new package does not 347 have to be explicitly listed here, however it must have a signature 348 that matches the signature of at least one package on this list. 349 */ 350 Resources resources = mContext.getResources(); 351 ArrayList<String> providerPackageNames = new ArrayList<String>(); 352 String[] pkgs = resources.getStringArray( 353 com.android.internal.R.array.config_locationProviderPackageNames); 354 if (D) Log.d(TAG, "certificates for location providers pulled from: " + 355 Arrays.toString(pkgs)); 356 if (pkgs != null) providerPackageNames.addAll(Arrays.asList(pkgs)); 357 358 ensureFallbackFusedProviderPresentLocked(providerPackageNames); 359 360 // bind to network provider 361 LocationProviderProxy networkProvider = LocationProviderProxy.createAndBind( 362 mContext, 363 LocationManager.NETWORK_PROVIDER, 364 NETWORK_LOCATION_SERVICE_ACTION, 365 providerPackageNames, mLocationHandler, mCurrentUserId); 366 if (networkProvider != null) { 367 mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider); 368 mProxyProviders.add(networkProvider); 369 addProviderLocked(networkProvider); 370 } else { 371 Slog.w(TAG, "no network location provider found"); 372 } 373 374 // bind to fused provider 375 LocationProviderProxy fusedLocationProvider = LocationProviderProxy.createAndBind( 376 mContext, 377 LocationManager.FUSED_PROVIDER, 378 FUSED_LOCATION_SERVICE_ACTION, 379 providerPackageNames, mLocationHandler, mCurrentUserId); 380 if (fusedLocationProvider != null) { 381 addProviderLocked(fusedLocationProvider); 382 mProxyProviders.add(fusedLocationProvider); 383 mEnabledProviders.add(fusedLocationProvider.getName()); 384 mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider); 385 } else { 386 Slog.e(TAG, "no fused location provider found", 387 new IllegalStateException("Location service needs a fused location provider")); 388 } 389 390 // bind to geocoder provider 391 mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames, 392 mCurrentUserId); 393 if (mGeocodeProvider == null) { 394 Slog.e(TAG, "no geocoder provider found"); 395 } 396 } 397 398 /** 399 * Called when the device's active user changes. 400 * @param userId the new active user's UserId 401 */ 402 private void switchUser(int userId) { 403 mBlacklist.switchUser(userId); 404 synchronized (mLock) { 405 mLastLocation.clear(); 406 for (LocationProviderInterface p : mProviders) { 407 updateProviderListenersLocked(p.getName(), false, mCurrentUserId); 408 if (!LocationManager.FUSED_PROVIDER.equals(p.getName())) { 409 p.switchUser(userId); 410 } 411 } 412 mCurrentUserId = userId; 413 updateProvidersLocked(); 414 } 415 } 416 417 /** 418 * A wrapper class holding either an ILocationListener or a PendingIntent to receive 419 * location updates. 420 */ 421 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { 422 final int mUid; // uid of receiver 423 final int mPid; // pid of receiver 424 final String mPackageName; // package name of receiver 425 final int mAllowedResolutionLevel; // resolution level allowed to receiver 426 427 final ILocationListener mListener; 428 final PendingIntent mPendingIntent; 429 final Object mKey; 430 431 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); 432 433 int mPendingBroadcasts; 434 435 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid, 436 String packageName) { 437 mListener = listener; 438 mPendingIntent = intent; 439 if (listener != null) { 440 mKey = listener.asBinder(); 441 } else { 442 mKey = intent; 443 } 444 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid); 445 mUid = uid; 446 mPid = pid; 447 mPackageName = packageName; 448 } 449 450 @Override 451 public boolean equals(Object otherObj) { 452 if (otherObj instanceof Receiver) { 453 return mKey.equals(((Receiver)otherObj).mKey); 454 } 455 return false; 456 } 457 458 @Override 459 public int hashCode() { 460 return mKey.hashCode(); 461 } 462 463 @Override 464 public String toString() { 465 StringBuilder s = new StringBuilder(); 466 s.append("Reciever["); 467 s.append(Integer.toHexString(System.identityHashCode(this))); 468 if (mListener != null) { 469 s.append(" listener"); 470 } else { 471 s.append(" intent"); 472 } 473 for (String p : mUpdateRecords.keySet()) { 474 s.append(" ").append(mUpdateRecords.get(p).toString()); 475 } 476 s.append("]"); 477 return s.toString(); 478 } 479 480 public boolean isListener() { 481 return mListener != null; 482 } 483 484 public boolean isPendingIntent() { 485 return mPendingIntent != null; 486 } 487 488 public ILocationListener getListener() { 489 if (mListener != null) { 490 return mListener; 491 } 492 throw new IllegalStateException("Request for non-existent listener"); 493 } 494 495 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { 496 if (mListener != null) { 497 try { 498 synchronized (this) { 499 // synchronize to ensure incrementPendingBroadcastsLocked() 500 // is called before decrementPendingBroadcasts() 501 mListener.onStatusChanged(provider, status, extras); 502 // call this after broadcasting so we do not increment 503 // if we throw an exeption. 504 incrementPendingBroadcastsLocked(); 505 } 506 } catch (RemoteException e) { 507 return false; 508 } 509 } else { 510 Intent statusChanged = new Intent(); 511 statusChanged.putExtras(extras); 512 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); 513 try { 514 synchronized (this) { 515 // synchronize to ensure incrementPendingBroadcastsLocked() 516 // is called before decrementPendingBroadcasts() 517 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler, 518 getResolutionPermission(mAllowedResolutionLevel)); 519 // call this after broadcasting so we do not increment 520 // if we throw an exeption. 521 incrementPendingBroadcastsLocked(); 522 } 523 } catch (PendingIntent.CanceledException e) { 524 return false; 525 } 526 } 527 return true; 528 } 529 530 public boolean callLocationChangedLocked(Location location) { 531 if (mListener != null) { 532 try { 533 synchronized (this) { 534 // synchronize to ensure incrementPendingBroadcastsLocked() 535 // is called before decrementPendingBroadcasts() 536 mListener.onLocationChanged(location); 537 // call this after broadcasting so we do not increment 538 // if we throw an exeption. 539 incrementPendingBroadcastsLocked(); 540 } 541 } catch (RemoteException e) { 542 return false; 543 } 544 } else { 545 Intent locationChanged = new Intent(); 546 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); 547 try { 548 synchronized (this) { 549 // synchronize to ensure incrementPendingBroadcastsLocked() 550 // is called before decrementPendingBroadcasts() 551 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler, 552 getResolutionPermission(mAllowedResolutionLevel)); 553 // call this after broadcasting so we do not increment 554 // if we throw an exeption. 555 incrementPendingBroadcastsLocked(); 556 } 557 } catch (PendingIntent.CanceledException e) { 558 return false; 559 } 560 } 561 return true; 562 } 563 564 public boolean callProviderEnabledLocked(String provider, boolean enabled) { 565 if (mListener != null) { 566 try { 567 synchronized (this) { 568 // synchronize to ensure incrementPendingBroadcastsLocked() 569 // is called before decrementPendingBroadcasts() 570 if (enabled) { 571 mListener.onProviderEnabled(provider); 572 } else { 573 mListener.onProviderDisabled(provider); 574 } 575 // call this after broadcasting so we do not increment 576 // if we throw an exeption. 577 incrementPendingBroadcastsLocked(); 578 } 579 } catch (RemoteException e) { 580 return false; 581 } 582 } else { 583 Intent providerIntent = new Intent(); 584 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); 585 try { 586 synchronized (this) { 587 // synchronize to ensure incrementPendingBroadcastsLocked() 588 // is called before decrementPendingBroadcasts() 589 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler, 590 getResolutionPermission(mAllowedResolutionLevel)); 591 // call this after broadcasting so we do not increment 592 // if we throw an exeption. 593 incrementPendingBroadcastsLocked(); 594 } 595 } catch (PendingIntent.CanceledException e) { 596 return false; 597 } 598 } 599 return true; 600 } 601 602 @Override 603 public void binderDied() { 604 if (D) Log.d(TAG, "Location listener died"); 605 606 synchronized (mLock) { 607 removeUpdatesLocked(this); 608 } 609 synchronized (this) { 610 if (mPendingBroadcasts > 0) { 611 LocationManagerService.this.decrementPendingBroadcasts(); 612 mPendingBroadcasts = 0; 613 } 614 } 615 } 616 617 @Override 618 public void onSendFinished(PendingIntent pendingIntent, Intent intent, 619 int resultCode, String resultData, Bundle resultExtras) { 620 synchronized (this) { 621 decrementPendingBroadcastsLocked(); 622 } 623 } 624 625 // this must be called while synchronized by caller in a synchronized block 626 // containing the sending of the broadcaset 627 private void incrementPendingBroadcastsLocked() { 628 if (mPendingBroadcasts++ == 0) { 629 LocationManagerService.this.incrementPendingBroadcasts(); 630 } 631 } 632 633 private void decrementPendingBroadcastsLocked() { 634 if (--mPendingBroadcasts == 0) { 635 LocationManagerService.this.decrementPendingBroadcasts(); 636 } 637 } 638 } 639 640 @Override 641 public void locationCallbackFinished(ILocationListener listener) { 642 //Do not use getReceiver here as that will add the ILocationListener to 643 //the receiver list if it is not found. If it is not found then the 644 //LocationListener was removed when it had a pending broadcast and should 645 //not be added back. 646 IBinder binder = listener.asBinder(); 647 Receiver receiver = mReceivers.get(binder); 648 if (receiver != null) { 649 synchronized (receiver) { 650 // so wakelock calls will succeed 651 long identity = Binder.clearCallingIdentity(); 652 receiver.decrementPendingBroadcastsLocked(); 653 Binder.restoreCallingIdentity(identity); 654 } 655 } 656 } 657 658 private void addProviderLocked(LocationProviderInterface provider) { 659 mProviders.add(provider); 660 mProvidersByName.put(provider.getName(), provider); 661 } 662 663 private void removeProviderLocked(LocationProviderInterface provider) { 664 provider.disable(); 665 mProviders.remove(provider); 666 mProvidersByName.remove(provider.getName()); 667 } 668 669 /** 670 * Returns true if the specified UID is SYSTEM_UID or matches the current user. 671 * 672 * @param uid the uid 673 * @return true if uid is SYSTEM_UID or matches the current user 674 */ 675 private boolean isCurrentUserOrSystemLocked(int uid) { 676 return uid == Process.SYSTEM_UID || UserHandle.getUserId(uid) == mCurrentUserId; 677 } 678 679 /** 680 * Returns the first UID in the current user's range. 681 * 682 * @return the first UID in the current user's range 683 */ 684 private int getCurrentUidBaseLocked() { 685 return UserHandle.getUid(mCurrentUserId, 0); 686 } 687 688 private boolean isAllowedBySettingsLocked(String provider, int uid) { 689 if (!isCurrentUserOrSystemLocked(uid)) { 690 return false; 691 } 692 if (mEnabledProviders.contains(provider)) { 693 return true; 694 } 695 if (mDisabledProviders.contains(provider)) { 696 return false; 697 } 698 if (uid == Process.SYSTEM_UID) { 699 return true; 700 } 701 702 // Use system settings 703 ContentResolver resolver = mContext.getContentResolver(); 704 705 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId); 706 } 707 708 /** 709 * Returns the permission string associated with the specified resolution level. 710 * 711 * @param resolutionLevel the resolution level 712 * @return the permission string 713 */ 714 private String getResolutionPermission(int resolutionLevel) { 715 switch (resolutionLevel) { 716 case RESOLUTION_LEVEL_FINE: 717 return android.Manifest.permission.ACCESS_FINE_LOCATION; 718 case RESOLUTION_LEVEL_COARSE: 719 return android.Manifest.permission.ACCESS_COARSE_LOCATION; 720 default: 721 return null; 722 } 723 } 724 725 /** 726 * Returns the resolution level allowed to the given PID/UID pair. 727 * 728 * @param pid the PID 729 * @param uid the UID 730 * @return resolution level allowed to the pid/uid pair 731 */ 732 private int getAllowedResolutionLevel(int pid, int uid) { 733 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, 734 pid, uid) == PackageManager.PERMISSION_GRANTED) { 735 return RESOLUTION_LEVEL_FINE; 736 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, 737 pid, uid) == PackageManager.PERMISSION_GRANTED) { 738 return RESOLUTION_LEVEL_COARSE; 739 } else { 740 return RESOLUTION_LEVEL_NONE; 741 } 742 } 743 744 /** 745 * Returns the resolution level allowed to the caller 746 * 747 * @return resolution level allowed to caller 748 */ 749 private int getCallerAllowedResolutionLevel() { 750 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid()); 751 } 752 753 /** 754 * Throw SecurityException if specified resolution level is insufficient to use geofences. 755 * 756 * @param allowedResolutionLevel resolution level allowed to caller 757 */ 758 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) { 759 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 760 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission"); 761 } 762 } 763 764 /** 765 * Return the minimum resolution level required to use the specified location provider. 766 * 767 * @param provider the name of the location provider 768 * @return minimum resolution level required for provider 769 */ 770 private int getMinimumResolutionLevelForProviderUse(String provider) { 771 if (LocationManager.GPS_PROVIDER.equals(provider) || 772 LocationManager.PASSIVE_PROVIDER.equals(provider)) { 773 // gps and passive providers require FINE permission 774 return RESOLUTION_LEVEL_FINE; 775 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) || 776 LocationManager.FUSED_PROVIDER.equals(provider)) { 777 // network and fused providers are ok with COARSE or FINE 778 return RESOLUTION_LEVEL_COARSE; 779 } else { 780 // mock providers 781 LocationProviderInterface lp = mMockProviders.get(provider); 782 if (lp != null) { 783 ProviderProperties properties = lp.getProperties(); 784 if (properties != null) { 785 if (properties.mRequiresSatellite) { 786 // provider requiring satellites require FINE permission 787 return RESOLUTION_LEVEL_FINE; 788 } else if (properties.mRequiresNetwork || properties.mRequiresCell) { 789 // provider requiring network and or cell require COARSE or FINE 790 return RESOLUTION_LEVEL_COARSE; 791 } 792 } 793 } 794 } 795 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE 796 } 797 798 /** 799 * Throw SecurityException if specified resolution level is insufficient to use the named 800 * location provider. 801 * 802 * @param allowedResolutionLevel resolution level allowed to caller 803 * @param providerName the name of the location provider 804 */ 805 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel, 806 String providerName) { 807 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName); 808 if (allowedResolutionLevel < requiredResolutionLevel) { 809 switch (requiredResolutionLevel) { 810 case RESOLUTION_LEVEL_FINE: 811 throw new SecurityException("\"" + providerName + "\" location provider " + 812 "requires ACCESS_FINE_LOCATION permission."); 813 case RESOLUTION_LEVEL_COARSE: 814 throw new SecurityException("\"" + providerName + "\" location provider " + 815 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission."); 816 default: 817 throw new SecurityException("Insufficient permission for \"" + providerName + 818 "\" location provider."); 819 } 820 } 821 } 822 823 /** 824 * Returns all providers by name, including passive, but excluding 825 * fused, also including ones that are not permitted to 826 * be accessed by the calling activity or are currently disabled. 827 */ 828 @Override 829 public List<String> getAllProviders() { 830 ArrayList<String> out; 831 synchronized (mLock) { 832 out = new ArrayList<String>(mProviders.size()); 833 for (LocationProviderInterface provider : mProviders) { 834 String name = provider.getName(); 835 if (LocationManager.FUSED_PROVIDER.equals(name)) { 836 continue; 837 } 838 out.add(name); 839 } 840 } 841 842 if (D) Log.d(TAG, "getAllProviders()=" + out); 843 return out; 844 } 845 846 /** 847 * Return all providers by name, that match criteria and are optionally 848 * enabled. 849 * Can return passive provider, but never returns fused provider. 850 */ 851 @Override 852 public List<String> getProviders(Criteria criteria, boolean enabledOnly) { 853 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 854 ArrayList<String> out; 855 final int callingUid = Binder.getCallingUid(); 856 final long identity = Binder.clearCallingIdentity(); 857 try { 858 synchronized (mLock) { 859 out = new ArrayList<String>(mProviders.size()); 860 for (LocationProviderInterface provider : mProviders) { 861 String name = provider.getName(); 862 if (LocationManager.FUSED_PROVIDER.equals(name)) { 863 continue; 864 } 865 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) { 866 if (enabledOnly && !isAllowedBySettingsLocked(name, callingUid)) { 867 continue; 868 } 869 if (criteria != null && !LocationProvider.propertiesMeetCriteria( 870 name, provider.getProperties(), criteria)) { 871 continue; 872 } 873 out.add(name); 874 } 875 } 876 } 877 } finally { 878 Binder.restoreCallingIdentity(identity); 879 } 880 881 if (D) Log.d(TAG, "getProviders()=" + out); 882 return out; 883 } 884 885 /** 886 * Return the name of the best provider given a Criteria object. 887 * This method has been deprecated from the public API, 888 * and the whole LocationProvider (including #meetsCriteria) 889 * has been deprecated as well. So this method now uses 890 * some simplified logic. 891 */ 892 @Override 893 public String getBestProvider(Criteria criteria, boolean enabledOnly) { 894 String result = null; 895 896 List<String> providers = getProviders(criteria, enabledOnly); 897 if (!providers.isEmpty()) { 898 result = pickBest(providers); 899 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 900 return result; 901 } 902 providers = getProviders(null, enabledOnly); 903 if (!providers.isEmpty()) { 904 result = pickBest(providers); 905 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 906 return result; 907 } 908 909 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 910 return null; 911 } 912 913 private String pickBest(List<String> providers) { 914 if (providers.contains(LocationManager.GPS_PROVIDER)) { 915 return LocationManager.GPS_PROVIDER; 916 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) { 917 return LocationManager.NETWORK_PROVIDER; 918 } else { 919 return providers.get(0); 920 } 921 } 922 923 @Override 924 public boolean providerMeetsCriteria(String provider, Criteria criteria) { 925 LocationProviderInterface p = mProvidersByName.get(provider); 926 if (p == null) { 927 throw new IllegalArgumentException("provider=" + provider); 928 } 929 930 boolean result = LocationProvider.propertiesMeetCriteria( 931 p.getName(), p.getProperties(), criteria); 932 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result); 933 return result; 934 } 935 936 private void updateProvidersLocked() { 937 boolean changesMade = false; 938 for (int i = mProviders.size() - 1; i >= 0; i--) { 939 LocationProviderInterface p = mProviders.get(i); 940 boolean isEnabled = p.isEnabled(); 941 String name = p.getName(); 942 boolean shouldBeEnabled = isAllowedBySettingsLocked(name, getCurrentUidBaseLocked()); 943 if (isEnabled && !shouldBeEnabled) { 944 updateProviderListenersLocked(name, false, mCurrentUserId); 945 changesMade = true; 946 } else if (!isEnabled && shouldBeEnabled) { 947 updateProviderListenersLocked(name, true, mCurrentUserId); 948 changesMade = true; 949 } 950 } 951 if (changesMade) { 952 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION), 953 UserHandle.ALL); 954 } 955 } 956 957 private void updateProviderListenersLocked(String provider, boolean enabled, int userId) { 958 int listeners = 0; 959 960 LocationProviderInterface p = mProvidersByName.get(provider); 961 if (p == null) return; 962 963 ArrayList<Receiver> deadReceivers = null; 964 965 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 966 if (records != null) { 967 final int N = records.size(); 968 for (int i = 0; i < N; i++) { 969 UpdateRecord record = records.get(i); 970 if (isCurrentUserOrSystemLocked(record.mReceiver.mUid)) { 971 // Sends a notification message to the receiver 972 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { 973 if (deadReceivers == null) { 974 deadReceivers = new ArrayList<Receiver>(); 975 } 976 deadReceivers.add(record.mReceiver); 977 } 978 listeners++; 979 } 980 } 981 } 982 983 if (deadReceivers != null) { 984 for (int i = deadReceivers.size() - 1; i >= 0; i--) { 985 removeUpdatesLocked(deadReceivers.get(i)); 986 } 987 } 988 989 if (enabled) { 990 p.enable(); 991 if (listeners > 0) { 992 applyRequirementsLocked(provider); 993 } 994 } else { 995 p.disable(); 996 } 997 } 998 999 private void applyRequirementsLocked(String provider) { 1000 LocationProviderInterface p = mProvidersByName.get(provider); 1001 if (p == null) return; 1002 1003 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1004 WorkSource worksource = new WorkSource(); 1005 ProviderRequest providerRequest = new ProviderRequest(); 1006 1007 if (records != null) { 1008 for (UpdateRecord record : records) { 1009 if (isCurrentUserOrSystemLocked(record.mReceiver.mUid)) { 1010 LocationRequest locationRequest = record.mRequest; 1011 providerRequest.locationRequests.add(locationRequest); 1012 if (locationRequest.getInterval() < providerRequest.interval) { 1013 providerRequest.reportLocation = true; 1014 providerRequest.interval = locationRequest.getInterval(); 1015 } 1016 } 1017 } 1018 1019 if (providerRequest.reportLocation) { 1020 // calculate who to blame for power 1021 // This is somewhat arbitrary. We pick a threshold interval 1022 // that is slightly higher that the minimum interval, and 1023 // spread the blame across all applications with a request 1024 // under that threshold. 1025 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; 1026 for (UpdateRecord record : records) { 1027 if (isCurrentUserOrSystemLocked(record.mReceiver.mUid)) { 1028 LocationRequest locationRequest = record.mRequest; 1029 if (locationRequest.getInterval() <= thresholdInterval) { 1030 worksource.add(record.mReceiver.mUid); 1031 } 1032 } 1033 } 1034 } 1035 } 1036 1037 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); 1038 p.setRequest(providerRequest, worksource); 1039 } 1040 1041 private class UpdateRecord { 1042 final String mProvider; 1043 final LocationRequest mRequest; 1044 final Receiver mReceiver; 1045 Location mLastFixBroadcast; 1046 long mLastStatusBroadcast; 1047 1048 /** 1049 * Note: must be constructed with lock held. 1050 */ 1051 UpdateRecord(String provider, LocationRequest request, Receiver receiver) { 1052 mProvider = provider; 1053 mRequest = request; 1054 mReceiver = receiver; 1055 1056 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1057 if (records == null) { 1058 records = new ArrayList<UpdateRecord>(); 1059 mRecordsByProvider.put(provider, records); 1060 } 1061 if (!records.contains(this)) { 1062 records.add(this); 1063 } 1064 } 1065 1066 /** 1067 * Method to be called when a record will no longer be used. Calling this multiple times 1068 * must have the same effect as calling it once. 1069 */ 1070 void disposeLocked(boolean removeReceiver) { 1071 // remove from mRecordsByProvider 1072 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); 1073 if (globalRecords != null) { 1074 globalRecords.remove(this); 1075 } 1076 1077 if (!removeReceiver) return; // the caller will handle the rest 1078 1079 // remove from Receiver#mUpdateRecords 1080 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords; 1081 if (receiverRecords != null) { 1082 receiverRecords.remove(this.mProvider); 1083 1084 // and also remove the Receiver if it has no more update records 1085 if (removeReceiver && receiverRecords.size() == 0) { 1086 removeUpdatesLocked(mReceiver); 1087 } 1088 } 1089 } 1090 1091 @Override 1092 public String toString() { 1093 StringBuilder s = new StringBuilder(); 1094 s.append("UpdateRecord["); 1095 s.append(mProvider); 1096 s.append(' ').append(mReceiver.mPackageName).append('('); 1097 s.append(mReceiver.mUid).append(')'); 1098 s.append(' ').append(mRequest); 1099 s.append(']'); 1100 return s.toString(); 1101 } 1102 } 1103 1104 private Receiver getReceiver(ILocationListener listener, int pid, int uid, String packageName) { 1105 IBinder binder = listener.asBinder(); 1106 Receiver receiver = mReceivers.get(binder); 1107 if (receiver == null) { 1108 receiver = new Receiver(listener, null, pid, uid, packageName); 1109 mReceivers.put(binder, receiver); 1110 1111 try { 1112 receiver.getListener().asBinder().linkToDeath(receiver, 0); 1113 } catch (RemoteException e) { 1114 Slog.e(TAG, "linkToDeath failed:", e); 1115 return null; 1116 } 1117 } 1118 return receiver; 1119 } 1120 1121 private Receiver getReceiver(PendingIntent intent, int pid, int uid, String packageName) { 1122 Receiver receiver = mReceivers.get(intent); 1123 if (receiver == null) { 1124 receiver = new Receiver(null, intent, pid, uid, packageName); 1125 mReceivers.put(intent, receiver); 1126 } 1127 return receiver; 1128 } 1129 1130 /** 1131 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution 1132 * and consistency requirements. 1133 * 1134 * @param request the LocationRequest from which to create a sanitized version 1135 * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution 1136 * constraints 1137 * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution 1138 * @return a version of request that meets the given resolution and consistency requirements 1139 * @hide 1140 */ 1141 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) { 1142 LocationRequest sanitizedRequest = new LocationRequest(request); 1143 if (resolutionLevel < RESOLUTION_LEVEL_FINE) { 1144 switch (sanitizedRequest.getQuality()) { 1145 case LocationRequest.ACCURACY_FINE: 1146 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK); 1147 break; 1148 case LocationRequest.POWER_HIGH: 1149 sanitizedRequest.setQuality(LocationRequest.POWER_LOW); 1150 break; 1151 } 1152 // throttle 1153 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1154 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS); 1155 } 1156 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1157 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS); 1158 } 1159 } 1160 // make getFastestInterval() the minimum of interval and fastest interval 1161 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) { 1162 request.setFastestInterval(request.getInterval()); 1163 } 1164 return sanitizedRequest; 1165 } 1166 1167 private void checkPackageName(String packageName) { 1168 if (packageName == null) { 1169 throw new SecurityException("invalid package name: " + packageName); 1170 } 1171 int uid = Binder.getCallingUid(); 1172 String[] packages = mPackageManager.getPackagesForUid(uid); 1173 if (packages == null) { 1174 throw new SecurityException("invalid UID " + uid); 1175 } 1176 for (String pkg : packages) { 1177 if (packageName.equals(pkg)) return; 1178 } 1179 throw new SecurityException("invalid package name: " + packageName); 1180 } 1181 1182 private void checkPendingIntent(PendingIntent intent) { 1183 if (intent == null) { 1184 throw new IllegalArgumentException("invalid pending intent: " + intent); 1185 } 1186 } 1187 1188 private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent, 1189 int pid, int uid, String packageName) { 1190 if (intent == null && listener == null) { 1191 throw new IllegalArgumentException("need eiter listener or intent"); 1192 } else if (intent != null && listener != null) { 1193 throw new IllegalArgumentException("cannot register both listener and intent"); 1194 } else if (intent != null) { 1195 checkPendingIntent(intent); 1196 return getReceiver(intent, pid, uid, packageName); 1197 } else { 1198 return getReceiver(listener, pid, uid, packageName); 1199 } 1200 } 1201 1202 @Override 1203 public void requestLocationUpdates(LocationRequest request, ILocationListener listener, 1204 PendingIntent intent, String packageName) { 1205 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1206 checkPackageName(packageName); 1207 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1208 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1209 request.getProvider()); 1210 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1211 1212 final int pid = Binder.getCallingPid(); 1213 final int uid = Binder.getCallingUid(); 1214 Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName); 1215 1216 // providers may use public location API's, need to clear identity 1217 long identity = Binder.clearCallingIdentity(); 1218 try { 1219 synchronized (mLock) { 1220 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName); 1221 } 1222 } finally { 1223 Binder.restoreCallingIdentity(identity); 1224 } 1225 } 1226 1227 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, 1228 int pid, int uid, String packageName) { 1229 // Figure out the provider. Either its explicitly request (legacy use cases), or 1230 // use the fused provider 1231 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1232 String name = request.getProvider(); 1233 if (name == null) { 1234 throw new IllegalArgumentException("provider name must not be null"); 1235 } 1236 LocationProviderInterface provider = mProvidersByName.get(name); 1237 if (provider == null) { 1238 throw new IllegalArgumentException("provider doesn't exisit: " + provider); 1239 } 1240 1241 Log.i(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) + " " + 1242 name + " " + request + " from " + packageName + "(" + uid + ")"); 1243 1244 UpdateRecord record = new UpdateRecord(name, request, receiver); 1245 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record); 1246 if (oldRecord != null) { 1247 oldRecord.disposeLocked(false); 1248 } 1249 1250 boolean isProviderEnabled = isAllowedBySettingsLocked(name, uid); 1251 if (isProviderEnabled) { 1252 applyRequirementsLocked(name); 1253 } else { 1254 // Notify the listener that updates are currently disabled 1255 receiver.callProviderEnabledLocked(name, false); 1256 } 1257 } 1258 1259 @Override 1260 public void removeUpdates(ILocationListener listener, PendingIntent intent, 1261 String packageName) { 1262 checkPackageName(packageName); 1263 1264 final int pid = Binder.getCallingPid(); 1265 final int uid = Binder.getCallingUid(); 1266 Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName); 1267 1268 // providers may use public location API's, need to clear identity 1269 long identity = Binder.clearCallingIdentity(); 1270 try { 1271 synchronized (mLock) { 1272 removeUpdatesLocked(receiver); 1273 } 1274 } finally { 1275 Binder.restoreCallingIdentity(identity); 1276 } 1277 } 1278 1279 private void removeUpdatesLocked(Receiver receiver) { 1280 Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver))); 1281 1282 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 1283 receiver.getListener().asBinder().unlinkToDeath(receiver, 0); 1284 synchronized (receiver) { 1285 if (receiver.mPendingBroadcasts > 0) { 1286 decrementPendingBroadcasts(); 1287 receiver.mPendingBroadcasts = 0; 1288 } 1289 } 1290 } 1291 1292 // Record which providers were associated with this listener 1293 HashSet<String> providers = new HashSet<String>(); 1294 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords; 1295 if (oldRecords != null) { 1296 // Call dispose() on the obsolete update records. 1297 for (UpdateRecord record : oldRecords.values()) { 1298 record.disposeLocked(false); 1299 } 1300 // Accumulate providers 1301 providers.addAll(oldRecords.keySet()); 1302 } 1303 1304 // update provider 1305 int currentUidBase = getCurrentUidBaseLocked(); 1306 for (String provider : providers) { 1307 // If provider is already disabled, don't need to do anything 1308 if (!isAllowedBySettingsLocked(provider, currentUidBase)) { 1309 continue; 1310 } 1311 1312 applyRequirementsLocked(provider); 1313 } 1314 } 1315 1316 @Override 1317 public Location getLastLocation(LocationRequest request, String packageName) { 1318 if (D) Log.d(TAG, "getLastLocation: " + request); 1319 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1320 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1321 checkPackageName(packageName); 1322 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1323 request.getProvider()); 1324 // no need to sanitize this request, as only the provider name is used 1325 1326 final int callingUid = Binder.getCallingUid(); 1327 final long identity = Binder.clearCallingIdentity(); 1328 try { 1329 if (mBlacklist.isBlacklisted(packageName)) { 1330 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + 1331 packageName); 1332 return null; 1333 } 1334 1335 synchronized (mLock) { 1336 // Figure out the provider. Either its explicitly request (deprecated API's), 1337 // or use the fused provider 1338 String name = request.getProvider(); 1339 if (name == null) name = LocationManager.FUSED_PROVIDER; 1340 LocationProviderInterface provider = mProvidersByName.get(name); 1341 if (provider == null) return null; 1342 1343 if (!isAllowedBySettingsLocked(name, callingUid)) { 1344 return null; 1345 } 1346 1347 Location location = mLastLocation.get(name); 1348 if (location == null) { 1349 return null; 1350 } 1351 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1352 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1353 if (noGPSLocation != null) { 1354 return mLocationFudger.getOrCreate(noGPSLocation); 1355 } 1356 } else { 1357 return location; 1358 } 1359 } 1360 return null; 1361 } finally { 1362 Binder.restoreCallingIdentity(identity); 1363 } 1364 } 1365 1366 @Override 1367 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, 1368 String packageName) { 1369 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1370 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1371 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel); 1372 checkPendingIntent(intent); 1373 checkPackageName(packageName); 1374 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1375 request.getProvider()); 1376 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1377 1378 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent); 1379 1380 // geo-fence manager uses the public location API, need to clear identity 1381 int uid = Binder.getCallingUid(); 1382 long identity = Binder.clearCallingIdentity(); 1383 try { 1384 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName); 1385 } finally { 1386 Binder.restoreCallingIdentity(identity); 1387 } 1388 } 1389 1390 @Override 1391 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { 1392 checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel()); 1393 checkPendingIntent(intent); 1394 checkPackageName(packageName); 1395 1396 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); 1397 1398 // geo-fence manager uses the public location API, need to clear identity 1399 long identity = Binder.clearCallingIdentity(); 1400 try { 1401 mGeofenceManager.removeFence(geofence, intent); 1402 } finally { 1403 Binder.restoreCallingIdentity(identity); 1404 } 1405 } 1406 1407 1408 @Override 1409 public boolean addGpsStatusListener(IGpsStatusListener listener) { 1410 if (mGpsStatusProvider == null) { 1411 return false; 1412 } 1413 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1414 LocationManager.GPS_PROVIDER); 1415 1416 try { 1417 mGpsStatusProvider.addGpsStatusListener(listener); 1418 } catch (RemoteException e) { 1419 Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e); 1420 return false; 1421 } 1422 return true; 1423 } 1424 1425 @Override 1426 public void removeGpsStatusListener(IGpsStatusListener listener) { 1427 synchronized (mLock) { 1428 try { 1429 mGpsStatusProvider.removeGpsStatusListener(listener); 1430 } catch (Exception e) { 1431 Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e); 1432 } 1433 } 1434 } 1435 1436 @Override 1437 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 1438 if (provider == null) { 1439 // throw NullPointerException to remain compatible with previous implementation 1440 throw new NullPointerException(); 1441 } 1442 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1443 provider); 1444 1445 // and check for ACCESS_LOCATION_EXTRA_COMMANDS 1446 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 1447 != PackageManager.PERMISSION_GRANTED)) { 1448 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 1449 } 1450 1451 synchronized (mLock) { 1452 LocationProviderInterface p = mProvidersByName.get(provider); 1453 if (p == null) return false; 1454 1455 return p.sendExtraCommand(command, extras); 1456 } 1457 } 1458 1459 @Override 1460 public boolean sendNiResponse(int notifId, int userResponse) { 1461 if (Binder.getCallingUid() != Process.myUid()) { 1462 throw new SecurityException( 1463 "calling sendNiResponse from outside of the system is not allowed"); 1464 } 1465 try { 1466 return mNetInitiatedListener.sendNiResponse(notifId, userResponse); 1467 } catch (RemoteException e) { 1468 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); 1469 return false; 1470 } 1471 } 1472 1473 /** 1474 * @return null if the provider does not exist 1475 * @throws SecurityException if the provider is not allowed to be 1476 * accessed by the caller 1477 */ 1478 @Override 1479 public ProviderProperties getProviderProperties(String provider) { 1480 if (mProvidersByName.get(provider) == null) { 1481 return null; 1482 } 1483 1484 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1485 provider); 1486 1487 LocationProviderInterface p; 1488 synchronized (mLock) { 1489 p = mProvidersByName.get(provider); 1490 } 1491 1492 if (p == null) return null; 1493 return p.getProperties(); 1494 } 1495 1496 @Override 1497 public boolean isProviderEnabled(String provider) { 1498 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1499 provider); 1500 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1501 1502 final int callingUid = Binder.getCallingUid(); 1503 final long identity = Binder.clearCallingIdentity(); 1504 try { 1505 synchronized (mLock) { 1506 LocationProviderInterface p = mProvidersByName.get(provider); 1507 if (p == null) return false; 1508 1509 return isAllowedBySettingsLocked(provider, callingUid); 1510 } 1511 } finally { 1512 Binder.restoreCallingIdentity(identity); 1513 } 1514 } 1515 1516 private void checkCallerIsProvider() { 1517 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 1518 == PackageManager.PERMISSION_GRANTED) { 1519 return; 1520 } 1521 1522 // Previously we only used the INSTALL_LOCATION_PROVIDER 1523 // check. But that is system or signature 1524 // protection level which is not flexible enough for 1525 // providers installed oustide the system image. So 1526 // also allow providers with a UID matching the 1527 // currently bound package name 1528 1529 int uid = Binder.getCallingUid(); 1530 1531 if (mGeocodeProvider != null) { 1532 if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return; 1533 } 1534 for (LocationProviderProxy proxy : mProxyProviders) { 1535 if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return; 1536 } 1537 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 1538 "or UID of a currently bound location provider"); 1539 } 1540 1541 private boolean doesPackageHaveUid(int uid, String packageName) { 1542 if (packageName == null) { 1543 return false; 1544 } 1545 try { 1546 ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0); 1547 if (appInfo.uid != uid) { 1548 return false; 1549 } 1550 } catch (NameNotFoundException e) { 1551 return false; 1552 } 1553 return true; 1554 } 1555 1556 @Override 1557 public void reportLocation(Location location, boolean passive) { 1558 checkCallerIsProvider(); 1559 1560 if (!location.isComplete()) { 1561 Log.w(TAG, "Dropping incomplete location: " + location); 1562 return; 1563 } 1564 1565 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 1566 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 1567 m.arg1 = (passive ? 1 : 0); 1568 mLocationHandler.sendMessageAtFrontOfQueue(m); 1569 } 1570 1571 1572 private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) { 1573 // Always broadcast the first update 1574 if (lastLoc == null) { 1575 return true; 1576 } 1577 1578 // Check whether sufficient time has passed 1579 long minTime = record.mRequest.getFastestInterval(); 1580 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L; 1581 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 1582 return false; 1583 } 1584 1585 // Check whether sufficient distance has been traveled 1586 double minDistance = record.mRequest.getSmallestDisplacement(); 1587 if (minDistance > 0.0) { 1588 if (loc.distanceTo(lastLoc) <= minDistance) { 1589 return false; 1590 } 1591 } 1592 1593 return true; 1594 } 1595 1596 private void handleLocationChangedLocked(Location location, boolean passive) { 1597 if (D) Log.d(TAG, "incoming location: " + location); 1598 1599 long now = SystemClock.elapsedRealtime(); 1600 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 1601 1602 // Skip if the provider is unknown. 1603 LocationProviderInterface p = mProvidersByName.get(provider); 1604 if (p == null) return; 1605 1606 // Update last known locations 1607 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1608 Location lastNoGPSLocation = null; 1609 Location lastLocation = mLastLocation.get(provider); 1610 if (lastLocation == null) { 1611 lastLocation = new Location(provider); 1612 mLastLocation.put(provider, lastLocation); 1613 } else { 1614 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1615 if (noGPSLocation == null && lastNoGPSLocation != null) { 1616 // New location has no no-GPS location: adopt last no-GPS location. This is set 1617 // directly into location because we do not want to notify COARSE clients. 1618 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 1619 } 1620 } 1621 lastLocation.set(location); 1622 1623 // Skip if there are no UpdateRecords for this provider. 1624 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1625 if (records == null || records.size() == 0) return; 1626 1627 // Fetch coarse location 1628 Location coarseLocation = null; 1629 if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) { 1630 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 1631 } 1632 1633 // Fetch latest status update time 1634 long newStatusUpdateTime = p.getStatusUpdateTime(); 1635 1636 // Get latest status 1637 Bundle extras = new Bundle(); 1638 int status = p.getStatus(extras); 1639 1640 ArrayList<Receiver> deadReceivers = null; 1641 ArrayList<UpdateRecord> deadUpdateRecords = null; 1642 1643 // Broadcast location or status to all listeners 1644 for (UpdateRecord r : records) { 1645 Receiver receiver = r.mReceiver; 1646 boolean receiverDead = false; 1647 1648 final int receiverUid = receiver.mUid; 1649 if (!isCurrentUserOrSystemLocked(receiverUid)) { 1650 if (D) { 1651 Log.d(TAG, "skipping loc update for background uid " + receiverUid + 1652 " (current user: " + mCurrentUserId + ", app: " + 1653 receiver.mPackageName + ")"); 1654 } 1655 continue; 1656 } 1657 1658 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 1659 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 1660 receiver.mPackageName); 1661 continue; 1662 } 1663 1664 Location notifyLocation = null; 1665 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1666 notifyLocation = coarseLocation; // use coarse location 1667 } else { 1668 notifyLocation = lastLocation; // use fine location 1669 } 1670 if (notifyLocation != null) { 1671 Location lastLoc = r.mLastFixBroadcast; 1672 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r)) { 1673 if (lastLoc == null) { 1674 lastLoc = new Location(notifyLocation); 1675 r.mLastFixBroadcast = lastLoc; 1676 } else { 1677 lastLoc.set(notifyLocation); 1678 } 1679 if (!receiver.callLocationChangedLocked(notifyLocation)) { 1680 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 1681 receiverDead = true; 1682 } 1683 } 1684 } 1685 1686 long prevStatusUpdateTime = r.mLastStatusBroadcast; 1687 if ((newStatusUpdateTime > prevStatusUpdateTime) && 1688 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 1689 1690 r.mLastStatusBroadcast = newStatusUpdateTime; 1691 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 1692 receiverDead = true; 1693 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 1694 } 1695 } 1696 1697 // track expired records 1698 if (r.mRequest.getNumUpdates() == 0 || r.mRequest.getExpireAt() < now) { 1699 if (deadUpdateRecords == null) { 1700 deadUpdateRecords = new ArrayList<UpdateRecord>(); 1701 } 1702 deadUpdateRecords.add(r); 1703 } 1704 // track dead receivers 1705 if (receiverDead) { 1706 if (deadReceivers == null) { 1707 deadReceivers = new ArrayList<Receiver>(); 1708 } 1709 if (!deadReceivers.contains(receiver)) { 1710 deadReceivers.add(receiver); 1711 } 1712 } 1713 } 1714 1715 // remove dead records and receivers outside the loop 1716 if (deadReceivers != null) { 1717 for (Receiver receiver : deadReceivers) { 1718 removeUpdatesLocked(receiver); 1719 } 1720 } 1721 if (deadUpdateRecords != null) { 1722 for (UpdateRecord r : deadUpdateRecords) { 1723 r.disposeLocked(true); 1724 } 1725 } 1726 } 1727 1728 private class LocationWorkerHandler extends Handler { 1729 @Override 1730 public void handleMessage(Message msg) { 1731 switch (msg.what) { 1732 case MSG_LOCATION_CHANGED: 1733 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 1734 break; 1735 } 1736 } 1737 } 1738 1739 private void handleLocationChanged(Location location, boolean passive) { 1740 String provider = location.getProvider(); 1741 1742 if (!passive) { 1743 // notify passive provider of the new location 1744 mPassiveProvider.updateLocation(location); 1745 } 1746 1747 synchronized (mLock) { 1748 if (isAllowedBySettingsLocked(provider, getCurrentUidBaseLocked())) { 1749 handleLocationChangedLocked(location, passive); 1750 } 1751 } 1752 } 1753 1754 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 1755 @Override 1756 public void onPackageDisappeared(String packageName, int reason) { 1757 // remove all receivers associated with this package name 1758 synchronized (mLock) { 1759 ArrayList<Receiver> deadReceivers = null; 1760 1761 for (Receiver receiver : mReceivers.values()) { 1762 if (receiver.mPackageName.equals(packageName)) { 1763 if (deadReceivers == null) { 1764 deadReceivers = new ArrayList<Receiver>(); 1765 } 1766 deadReceivers.add(receiver); 1767 } 1768 } 1769 1770 // perform removal outside of mReceivers loop 1771 if (deadReceivers != null) { 1772 for (Receiver receiver : deadReceivers) { 1773 removeUpdatesLocked(receiver); 1774 } 1775 } 1776 } 1777 } 1778 }; 1779 1780 // Wake locks 1781 1782 private void incrementPendingBroadcasts() { 1783 synchronized (mWakeLock) { 1784 if (mPendingBroadcasts++ == 0) { 1785 try { 1786 mWakeLock.acquire(); 1787 log("Acquired wakelock"); 1788 } catch (Exception e) { 1789 // This is to catch a runtime exception thrown when we try to release an 1790 // already released lock. 1791 Slog.e(TAG, "exception in acquireWakeLock()", e); 1792 } 1793 } 1794 } 1795 } 1796 1797 private void decrementPendingBroadcasts() { 1798 synchronized (mWakeLock) { 1799 if (--mPendingBroadcasts == 0) { 1800 try { 1801 // Release wake lock 1802 if (mWakeLock.isHeld()) { 1803 mWakeLock.release(); 1804 log("Released wakelock"); 1805 } else { 1806 log("Can't release wakelock again!"); 1807 } 1808 } catch (Exception e) { 1809 // This is to catch a runtime exception thrown when we try to release an 1810 // already released lock. 1811 Slog.e(TAG, "exception in releaseWakeLock()", e); 1812 } 1813 } 1814 } 1815 } 1816 1817 // Geocoder 1818 1819 @Override 1820 public boolean geocoderIsPresent() { 1821 return mGeocodeProvider != null; 1822 } 1823 1824 @Override 1825 public String getFromLocation(double latitude, double longitude, int maxResults, 1826 GeocoderParams params, List<Address> addrs) { 1827 if (mGeocodeProvider != null) { 1828 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 1829 params, addrs); 1830 } 1831 return null; 1832 } 1833 1834 1835 @Override 1836 public String getFromLocationName(String locationName, 1837 double lowerLeftLatitude, double lowerLeftLongitude, 1838 double upperRightLatitude, double upperRightLongitude, int maxResults, 1839 GeocoderParams params, List<Address> addrs) { 1840 1841 if (mGeocodeProvider != null) { 1842 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 1843 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 1844 maxResults, params, addrs); 1845 } 1846 return null; 1847 } 1848 1849 // Mock Providers 1850 1851 private void checkMockPermissionsSafe() { 1852 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 1853 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 1854 if (!allowMocks) { 1855 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 1856 } 1857 1858 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 1859 PackageManager.PERMISSION_GRANTED) { 1860 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 1861 } 1862 } 1863 1864 @Override 1865 public void addTestProvider(String name, ProviderProperties properties) { 1866 checkMockPermissionsSafe(); 1867 1868 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 1869 throw new IllegalArgumentException("Cannot mock the passive location provider"); 1870 } 1871 1872 long identity = Binder.clearCallingIdentity(); 1873 synchronized (mLock) { 1874 MockProvider provider = new MockProvider(name, this, properties); 1875 // remove the real provider if we are replacing GPS or network provider 1876 if (LocationManager.GPS_PROVIDER.equals(name) 1877 || LocationManager.NETWORK_PROVIDER.equals(name) 1878 || LocationManager.FUSED_PROVIDER.equals(name)) { 1879 LocationProviderInterface p = mProvidersByName.get(name); 1880 if (p != null) { 1881 removeProviderLocked(p); 1882 } 1883 } 1884 if (mProvidersByName.get(name) != null) { 1885 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 1886 } 1887 addProviderLocked(provider); 1888 mMockProviders.put(name, provider); 1889 mLastLocation.put(name, null); 1890 updateProvidersLocked(); 1891 } 1892 Binder.restoreCallingIdentity(identity); 1893 } 1894 1895 @Override 1896 public void removeTestProvider(String provider) { 1897 checkMockPermissionsSafe(); 1898 synchronized (mLock) { 1899 MockProvider mockProvider = mMockProviders.get(provider); 1900 if (mockProvider == null) { 1901 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1902 } 1903 long identity = Binder.clearCallingIdentity(); 1904 removeProviderLocked(mProvidersByName.get(provider)); 1905 mMockProviders.remove(mockProvider); 1906 1907 // reinstate real provider if available 1908 LocationProviderInterface realProvider = mRealProviders.get(provider); 1909 if (realProvider != null) { 1910 addProviderLocked(realProvider); 1911 } 1912 mLastLocation.put(provider, null); 1913 updateProvidersLocked(); 1914 Binder.restoreCallingIdentity(identity); 1915 } 1916 } 1917 1918 @Override 1919 public void setTestProviderLocation(String provider, Location loc) { 1920 checkMockPermissionsSafe(); 1921 synchronized (mLock) { 1922 MockProvider mockProvider = mMockProviders.get(provider); 1923 if (mockProvider == null) { 1924 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1925 } 1926 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 1927 long identity = Binder.clearCallingIdentity(); 1928 mockProvider.setLocation(loc); 1929 Binder.restoreCallingIdentity(identity); 1930 } 1931 } 1932 1933 @Override 1934 public void clearTestProviderLocation(String provider) { 1935 checkMockPermissionsSafe(); 1936 synchronized (mLock) { 1937 MockProvider mockProvider = mMockProviders.get(provider); 1938 if (mockProvider == null) { 1939 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1940 } 1941 mockProvider.clearLocation(); 1942 } 1943 } 1944 1945 @Override 1946 public void setTestProviderEnabled(String provider, boolean enabled) { 1947 checkMockPermissionsSafe(); 1948 synchronized (mLock) { 1949 MockProvider mockProvider = mMockProviders.get(provider); 1950 if (mockProvider == null) { 1951 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1952 } 1953 long identity = Binder.clearCallingIdentity(); 1954 if (enabled) { 1955 mockProvider.enable(); 1956 mEnabledProviders.add(provider); 1957 mDisabledProviders.remove(provider); 1958 } else { 1959 mockProvider.disable(); 1960 mEnabledProviders.remove(provider); 1961 mDisabledProviders.add(provider); 1962 } 1963 updateProvidersLocked(); 1964 Binder.restoreCallingIdentity(identity); 1965 } 1966 } 1967 1968 @Override 1969 public void clearTestProviderEnabled(String provider) { 1970 checkMockPermissionsSafe(); 1971 synchronized (mLock) { 1972 MockProvider mockProvider = mMockProviders.get(provider); 1973 if (mockProvider == null) { 1974 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1975 } 1976 long identity = Binder.clearCallingIdentity(); 1977 mEnabledProviders.remove(provider); 1978 mDisabledProviders.remove(provider); 1979 updateProvidersLocked(); 1980 Binder.restoreCallingIdentity(identity); 1981 } 1982 } 1983 1984 @Override 1985 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 1986 checkMockPermissionsSafe(); 1987 synchronized (mLock) { 1988 MockProvider mockProvider = mMockProviders.get(provider); 1989 if (mockProvider == null) { 1990 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1991 } 1992 mockProvider.setStatus(status, extras, updateTime); 1993 } 1994 } 1995 1996 @Override 1997 public void clearTestProviderStatus(String provider) { 1998 checkMockPermissionsSafe(); 1999 synchronized (mLock) { 2000 MockProvider mockProvider = mMockProviders.get(provider); 2001 if (mockProvider == null) { 2002 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2003 } 2004 mockProvider.clearStatus(); 2005 } 2006 } 2007 2008 private void log(String log) { 2009 if (Log.isLoggable(TAG, Log.VERBOSE)) { 2010 Slog.d(TAG, log); 2011 } 2012 } 2013 2014 @Override 2015 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2016 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2017 != PackageManager.PERMISSION_GRANTED) { 2018 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2019 + Binder.getCallingPid() 2020 + ", uid=" + Binder.getCallingUid()); 2021 return; 2022 } 2023 2024 synchronized (mLock) { 2025 pw.println("Current Location Manager state:"); 2026 pw.println(" Location Listeners:"); 2027 for (Receiver receiver : mReceivers.values()) { 2028 pw.println(" " + receiver); 2029 } 2030 pw.println(" Records by Provider:"); 2031 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2032 pw.println(" " + entry.getKey() + ":"); 2033 for (UpdateRecord record : entry.getValue()) { 2034 pw.println(" " + record); 2035 } 2036 } 2037 pw.println(" Last Known Locations:"); 2038 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2039 String provider = entry.getKey(); 2040 Location location = entry.getValue(); 2041 pw.println(" " + provider + ": " + location); 2042 } 2043 2044 mGeofenceManager.dump(pw); 2045 2046 if (mEnabledProviders.size() > 0) { 2047 pw.println(" Enabled Providers:"); 2048 for (String i : mEnabledProviders) { 2049 pw.println(" " + i); 2050 } 2051 2052 } 2053 if (mDisabledProviders.size() > 0) { 2054 pw.println(" Disabled Providers:"); 2055 for (String i : mDisabledProviders) { 2056 pw.println(" " + i); 2057 } 2058 } 2059 pw.append(" "); 2060 mBlacklist.dump(pw); 2061 if (mMockProviders.size() > 0) { 2062 pw.println(" Mock Providers:"); 2063 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2064 i.getValue().dump(pw, " "); 2065 } 2066 } 2067 2068 pw.append(" fudger: "); 2069 mLocationFudger.dump(fd, pw, args); 2070 2071 if (args.length > 0 && "short".equals(args[0])) { 2072 return; 2073 } 2074 for (LocationProviderInterface provider: mProviders) { 2075 pw.print(provider.getName() + " Internal State"); 2076 if (provider instanceof LocationProviderProxy) { 2077 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2078 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2079 } 2080 pw.println(":"); 2081 provider.dump(fd, pw, args); 2082 } 2083 } 2084 } 2085} 2086