LocationManagerService.java revision 56e675b3a1c351de34de68a149762d3ad1b308c5
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 p.switchUser(userId); 409 } 410 mCurrentUserId = userId; 411 updateProvidersLocked(); 412 } 413 } 414 415 /** 416 * A wrapper class holding either an ILocationListener or a PendingIntent to receive 417 * location updates. 418 */ 419 private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { 420 final int mUid; // uid of receiver 421 final int mPid; // pid of receiver 422 final String mPackageName; // package name of receiver 423 final int mAllowedResolutionLevel; // resolution level allowed to receiver 424 425 final ILocationListener mListener; 426 final PendingIntent mPendingIntent; 427 final Object mKey; 428 429 final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); 430 431 int mPendingBroadcasts; 432 433 Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid, 434 String packageName) { 435 mListener = listener; 436 mPendingIntent = intent; 437 if (listener != null) { 438 mKey = listener.asBinder(); 439 } else { 440 mKey = intent; 441 } 442 mAllowedResolutionLevel = getAllowedResolutionLevel(pid, uid); 443 mUid = uid; 444 mPid = pid; 445 mPackageName = packageName; 446 } 447 448 @Override 449 public boolean equals(Object otherObj) { 450 if (otherObj instanceof Receiver) { 451 return mKey.equals(((Receiver)otherObj).mKey); 452 } 453 return false; 454 } 455 456 @Override 457 public int hashCode() { 458 return mKey.hashCode(); 459 } 460 461 @Override 462 public String toString() { 463 StringBuilder s = new StringBuilder(); 464 s.append("Reciever["); 465 s.append(Integer.toHexString(System.identityHashCode(this))); 466 if (mListener != null) { 467 s.append(" listener"); 468 } else { 469 s.append(" intent"); 470 } 471 for (String p : mUpdateRecords.keySet()) { 472 s.append(" ").append(mUpdateRecords.get(p).toString()); 473 } 474 s.append("]"); 475 return s.toString(); 476 } 477 478 public boolean isListener() { 479 return mListener != null; 480 } 481 482 public boolean isPendingIntent() { 483 return mPendingIntent != null; 484 } 485 486 public ILocationListener getListener() { 487 if (mListener != null) { 488 return mListener; 489 } 490 throw new IllegalStateException("Request for non-existent listener"); 491 } 492 493 public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { 494 if (mListener != null) { 495 try { 496 synchronized (this) { 497 // synchronize to ensure incrementPendingBroadcastsLocked() 498 // is called before decrementPendingBroadcasts() 499 mListener.onStatusChanged(provider, status, extras); 500 // call this after broadcasting so we do not increment 501 // if we throw an exeption. 502 incrementPendingBroadcastsLocked(); 503 } 504 } catch (RemoteException e) { 505 return false; 506 } 507 } else { 508 Intent statusChanged = new Intent(); 509 statusChanged.putExtras(extras); 510 statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); 511 try { 512 synchronized (this) { 513 // synchronize to ensure incrementPendingBroadcastsLocked() 514 // is called before decrementPendingBroadcasts() 515 mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler, 516 getResolutionPermission(mAllowedResolutionLevel)); 517 // call this after broadcasting so we do not increment 518 // if we throw an exeption. 519 incrementPendingBroadcastsLocked(); 520 } 521 } catch (PendingIntent.CanceledException e) { 522 return false; 523 } 524 } 525 return true; 526 } 527 528 public boolean callLocationChangedLocked(Location location) { 529 if (mListener != null) { 530 try { 531 synchronized (this) { 532 // synchronize to ensure incrementPendingBroadcastsLocked() 533 // is called before decrementPendingBroadcasts() 534 mListener.onLocationChanged(location); 535 // call this after broadcasting so we do not increment 536 // if we throw an exeption. 537 incrementPendingBroadcastsLocked(); 538 } 539 } catch (RemoteException e) { 540 return false; 541 } 542 } else { 543 Intent locationChanged = new Intent(); 544 locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); 545 try { 546 synchronized (this) { 547 // synchronize to ensure incrementPendingBroadcastsLocked() 548 // is called before decrementPendingBroadcasts() 549 mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler, 550 getResolutionPermission(mAllowedResolutionLevel)); 551 // call this after broadcasting so we do not increment 552 // if we throw an exeption. 553 incrementPendingBroadcastsLocked(); 554 } 555 } catch (PendingIntent.CanceledException e) { 556 return false; 557 } 558 } 559 return true; 560 } 561 562 public boolean callProviderEnabledLocked(String provider, boolean enabled) { 563 if (mListener != null) { 564 try { 565 synchronized (this) { 566 // synchronize to ensure incrementPendingBroadcastsLocked() 567 // is called before decrementPendingBroadcasts() 568 if (enabled) { 569 mListener.onProviderEnabled(provider); 570 } else { 571 mListener.onProviderDisabled(provider); 572 } 573 // call this after broadcasting so we do not increment 574 // if we throw an exeption. 575 incrementPendingBroadcastsLocked(); 576 } 577 } catch (RemoteException e) { 578 return false; 579 } 580 } else { 581 Intent providerIntent = new Intent(); 582 providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); 583 try { 584 synchronized (this) { 585 // synchronize to ensure incrementPendingBroadcastsLocked() 586 // is called before decrementPendingBroadcasts() 587 mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler, 588 getResolutionPermission(mAllowedResolutionLevel)); 589 // call this after broadcasting so we do not increment 590 // if we throw an exeption. 591 incrementPendingBroadcastsLocked(); 592 } 593 } catch (PendingIntent.CanceledException e) { 594 return false; 595 } 596 } 597 return true; 598 } 599 600 @Override 601 public void binderDied() { 602 if (D) Log.d(TAG, "Location listener died"); 603 604 synchronized (mLock) { 605 removeUpdatesLocked(this); 606 } 607 synchronized (this) { 608 if (mPendingBroadcasts > 0) { 609 LocationManagerService.this.decrementPendingBroadcasts(); 610 mPendingBroadcasts = 0; 611 } 612 } 613 } 614 615 @Override 616 public void onSendFinished(PendingIntent pendingIntent, Intent intent, 617 int resultCode, String resultData, Bundle resultExtras) { 618 synchronized (this) { 619 decrementPendingBroadcastsLocked(); 620 } 621 } 622 623 // this must be called while synchronized by caller in a synchronized block 624 // containing the sending of the broadcaset 625 private void incrementPendingBroadcastsLocked() { 626 if (mPendingBroadcasts++ == 0) { 627 LocationManagerService.this.incrementPendingBroadcasts(); 628 } 629 } 630 631 private void decrementPendingBroadcastsLocked() { 632 if (--mPendingBroadcasts == 0) { 633 LocationManagerService.this.decrementPendingBroadcasts(); 634 } 635 } 636 } 637 638 @Override 639 public void locationCallbackFinished(ILocationListener listener) { 640 //Do not use getReceiver here as that will add the ILocationListener to 641 //the receiver list if it is not found. If it is not found then the 642 //LocationListener was removed when it had a pending broadcast and should 643 //not be added back. 644 IBinder binder = listener.asBinder(); 645 Receiver receiver = mReceivers.get(binder); 646 if (receiver != null) { 647 synchronized (receiver) { 648 // so wakelock calls will succeed 649 long identity = Binder.clearCallingIdentity(); 650 receiver.decrementPendingBroadcastsLocked(); 651 Binder.restoreCallingIdentity(identity); 652 } 653 } 654 } 655 656 private void addProviderLocked(LocationProviderInterface provider) { 657 mProviders.add(provider); 658 mProvidersByName.put(provider.getName(), provider); 659 } 660 661 private void removeProviderLocked(LocationProviderInterface provider) { 662 provider.disable(); 663 mProviders.remove(provider); 664 mProvidersByName.remove(provider.getName()); 665 } 666 667 668 private boolean isAllowedBySettingsLocked(String provider, int userId) { 669 if (userId != mCurrentUserId) { 670 return false; 671 } 672 if (mEnabledProviders.contains(provider)) { 673 return true; 674 } 675 if (mDisabledProviders.contains(provider)) { 676 return false; 677 } 678 // Use system settings 679 ContentResolver resolver = mContext.getContentResolver(); 680 681 return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId); 682 } 683 684 /** 685 * Returns the permission string associated with the specified resolution level. 686 * 687 * @param resolutionLevel the resolution level 688 * @return the permission string 689 */ 690 private String getResolutionPermission(int resolutionLevel) { 691 switch (resolutionLevel) { 692 case RESOLUTION_LEVEL_FINE: 693 return android.Manifest.permission.ACCESS_FINE_LOCATION; 694 case RESOLUTION_LEVEL_COARSE: 695 return android.Manifest.permission.ACCESS_COARSE_LOCATION; 696 default: 697 return null; 698 } 699 } 700 701 /** 702 * Returns the resolution level allowed to the given PID/UID pair. 703 * 704 * @param pid the PID 705 * @param uid the UID 706 * @return resolution level allowed to the pid/uid pair 707 */ 708 private int getAllowedResolutionLevel(int pid, int uid) { 709 if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, 710 pid, uid) == PackageManager.PERMISSION_GRANTED) { 711 return RESOLUTION_LEVEL_FINE; 712 } else if (mContext.checkPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, 713 pid, uid) == PackageManager.PERMISSION_GRANTED) { 714 return RESOLUTION_LEVEL_COARSE; 715 } else { 716 return RESOLUTION_LEVEL_NONE; 717 } 718 } 719 720 /** 721 * Returns the resolution level allowed to the caller 722 * 723 * @return resolution level allowed to caller 724 */ 725 private int getCallerAllowedResolutionLevel() { 726 return getAllowedResolutionLevel(Binder.getCallingPid(), Binder.getCallingUid()); 727 } 728 729 /** 730 * Throw SecurityException if specified resolution level is insufficient to use geofences. 731 * 732 * @param allowedResolutionLevel resolution level allowed to caller 733 */ 734 private void checkResolutionLevelIsSufficientForGeofenceUse(int allowedResolutionLevel) { 735 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 736 throw new SecurityException("Geofence usage requires ACCESS_FINE_LOCATION permission"); 737 } 738 } 739 740 /** 741 * Return the minimum resolution level required to use the specified location provider. 742 * 743 * @param provider the name of the location provider 744 * @return minimum resolution level required for provider 745 */ 746 private int getMinimumResolutionLevelForProviderUse(String provider) { 747 if (LocationManager.GPS_PROVIDER.equals(provider) || 748 LocationManager.PASSIVE_PROVIDER.equals(provider)) { 749 // gps and passive providers require FINE permission 750 return RESOLUTION_LEVEL_FINE; 751 } else if (LocationManager.NETWORK_PROVIDER.equals(provider) || 752 LocationManager.FUSED_PROVIDER.equals(provider)) { 753 // network and fused providers are ok with COARSE or FINE 754 return RESOLUTION_LEVEL_COARSE; 755 } else { 756 // mock providers 757 LocationProviderInterface lp = mMockProviders.get(provider); 758 if (lp != null) { 759 ProviderProperties properties = lp.getProperties(); 760 if (properties != null) { 761 if (properties.mRequiresSatellite) { 762 // provider requiring satellites require FINE permission 763 return RESOLUTION_LEVEL_FINE; 764 } else if (properties.mRequiresNetwork || properties.mRequiresCell) { 765 // provider requiring network and or cell require COARSE or FINE 766 return RESOLUTION_LEVEL_COARSE; 767 } 768 } 769 } 770 } 771 return RESOLUTION_LEVEL_FINE; // if in doubt, require FINE 772 } 773 774 /** 775 * Throw SecurityException if specified resolution level is insufficient to use the named 776 * location provider. 777 * 778 * @param allowedResolutionLevel resolution level allowed to caller 779 * @param providerName the name of the location provider 780 */ 781 private void checkResolutionLevelIsSufficientForProviderUse(int allowedResolutionLevel, 782 String providerName) { 783 int requiredResolutionLevel = getMinimumResolutionLevelForProviderUse(providerName); 784 if (allowedResolutionLevel < requiredResolutionLevel) { 785 switch (requiredResolutionLevel) { 786 case RESOLUTION_LEVEL_FINE: 787 throw new SecurityException("\"" + providerName + "\" location provider " + 788 "requires ACCESS_FINE_LOCATION permission."); 789 case RESOLUTION_LEVEL_COARSE: 790 throw new SecurityException("\"" + providerName + "\" location provider " + 791 "requires ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission."); 792 default: 793 throw new SecurityException("Insufficient permission for \"" + providerName + 794 "\" location provider."); 795 } 796 } 797 } 798 799 /** 800 * Returns all providers by name, including passive, but excluding 801 * fused, also including ones that are not permitted to 802 * be accessed by the calling activity or are currently disabled. 803 */ 804 @Override 805 public List<String> getAllProviders() { 806 ArrayList<String> out; 807 synchronized (mLock) { 808 out = new ArrayList<String>(mProviders.size()); 809 for (LocationProviderInterface provider : mProviders) { 810 String name = provider.getName(); 811 if (LocationManager.FUSED_PROVIDER.equals(name)) { 812 continue; 813 } 814 out.add(name); 815 } 816 } 817 818 if (D) Log.d(TAG, "getAllProviders()=" + out); 819 return out; 820 } 821 822 /** 823 * Return all providers by name, that match criteria and are optionally 824 * enabled. 825 * Can return passive provider, but never returns fused provider. 826 */ 827 @Override 828 public List<String> getProviders(Criteria criteria, boolean enabledOnly) { 829 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 830 ArrayList<String> out; 831 int callingUserId = UserHandle.getCallingUserId(); 832 long identity = Binder.clearCallingIdentity(); 833 try { 834 synchronized (mLock) { 835 out = new ArrayList<String>(mProviders.size()); 836 for (LocationProviderInterface provider : mProviders) { 837 String name = provider.getName(); 838 if (LocationManager.FUSED_PROVIDER.equals(name)) { 839 continue; 840 } 841 if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) { 842 if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) { 843 continue; 844 } 845 if (criteria != null && !LocationProvider.propertiesMeetCriteria( 846 name, provider.getProperties(), criteria)) { 847 continue; 848 } 849 out.add(name); 850 } 851 } 852 } 853 } finally { 854 Binder.restoreCallingIdentity(identity); 855 } 856 857 if (D) Log.d(TAG, "getProviders()=" + out); 858 return out; 859 } 860 861 /** 862 * Return the name of the best provider given a Criteria object. 863 * This method has been deprecated from the public API, 864 * and the whole LocationProvider (including #meetsCriteria) 865 * has been deprecated as well. So this method now uses 866 * some simplified logic. 867 */ 868 @Override 869 public String getBestProvider(Criteria criteria, boolean enabledOnly) { 870 String result = null; 871 872 List<String> providers = getProviders(criteria, enabledOnly); 873 if (!providers.isEmpty()) { 874 result = pickBest(providers); 875 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 876 return result; 877 } 878 providers = getProviders(null, enabledOnly); 879 if (!providers.isEmpty()) { 880 result = pickBest(providers); 881 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 882 return result; 883 } 884 885 if (D) Log.d(TAG, "getBestProvider(" + criteria + ", " + enabledOnly + ")=" + result); 886 return null; 887 } 888 889 private String pickBest(List<String> providers) { 890 if (providers.contains(LocationManager.GPS_PROVIDER)) { 891 return LocationManager.GPS_PROVIDER; 892 } else if (providers.contains(LocationManager.NETWORK_PROVIDER)) { 893 return LocationManager.NETWORK_PROVIDER; 894 } else { 895 return providers.get(0); 896 } 897 } 898 899 @Override 900 public boolean providerMeetsCriteria(String provider, Criteria criteria) { 901 LocationProviderInterface p = mProvidersByName.get(provider); 902 if (p == null) { 903 throw new IllegalArgumentException("provider=" + provider); 904 } 905 906 boolean result = LocationProvider.propertiesMeetCriteria( 907 p.getName(), p.getProperties(), criteria); 908 if (D) Log.d(TAG, "providerMeetsCriteria(" + provider + ", " + criteria + ")=" + result); 909 return result; 910 } 911 912 private void updateProvidersLocked() { 913 boolean changesMade = false; 914 for (int i = mProviders.size() - 1; i >= 0; i--) { 915 LocationProviderInterface p = mProviders.get(i); 916 boolean isEnabled = p.isEnabled(); 917 String name = p.getName(); 918 boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId); 919 if (isEnabled && !shouldBeEnabled) { 920 updateProviderListenersLocked(name, false, mCurrentUserId); 921 changesMade = true; 922 } else if (!isEnabled && shouldBeEnabled) { 923 updateProviderListenersLocked(name, true, mCurrentUserId); 924 changesMade = true; 925 } 926 } 927 if (changesMade) { 928 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION), 929 UserHandle.ALL); 930 } 931 } 932 933 private void updateProviderListenersLocked(String provider, boolean enabled, int userId) { 934 int listeners = 0; 935 936 LocationProviderInterface p = mProvidersByName.get(provider); 937 if (p == null) return; 938 939 ArrayList<Receiver> deadReceivers = null; 940 941 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 942 if (records != null) { 943 final int N = records.size(); 944 for (int i = 0; i < N; i++) { 945 UpdateRecord record = records.get(i); 946 if (UserHandle.getUserId(record.mReceiver.mUid) == userId) { 947 // Sends a notification message to the receiver 948 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { 949 if (deadReceivers == null) { 950 deadReceivers = new ArrayList<Receiver>(); 951 } 952 deadReceivers.add(record.mReceiver); 953 } 954 listeners++; 955 } 956 } 957 } 958 959 if (deadReceivers != null) { 960 for (int i = deadReceivers.size() - 1; i >= 0; i--) { 961 removeUpdatesLocked(deadReceivers.get(i)); 962 } 963 } 964 965 if (enabled) { 966 p.enable(); 967 if (listeners > 0) { 968 applyRequirementsLocked(provider); 969 } 970 } else { 971 p.disable(); 972 } 973 } 974 975 private void applyRequirementsLocked(String provider) { 976 LocationProviderInterface p = mProvidersByName.get(provider); 977 if (p == null) return; 978 979 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 980 WorkSource worksource = new WorkSource(); 981 ProviderRequest providerRequest = new ProviderRequest(); 982 983 if (records != null) { 984 for (UpdateRecord record : records) { 985 if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { 986 LocationRequest locationRequest = record.mRequest; 987 providerRequest.locationRequests.add(locationRequest); 988 if (locationRequest.getInterval() < providerRequest.interval) { 989 providerRequest.reportLocation = true; 990 providerRequest.interval = locationRequest.getInterval(); 991 } 992 } 993 } 994 995 if (providerRequest.reportLocation) { 996 // calculate who to blame for power 997 // This is somewhat arbitrary. We pick a threshold interval 998 // that is slightly higher that the minimum interval, and 999 // spread the blame across all applications with a request 1000 // under that threshold. 1001 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; 1002 for (UpdateRecord record : records) { 1003 if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { 1004 LocationRequest locationRequest = record.mRequest; 1005 if (locationRequest.getInterval() <= thresholdInterval) { 1006 worksource.add(record.mReceiver.mUid); 1007 } 1008 } 1009 } 1010 } 1011 } 1012 1013 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); 1014 p.setRequest(providerRequest, worksource); 1015 } 1016 1017 private class UpdateRecord { 1018 final String mProvider; 1019 final LocationRequest mRequest; 1020 final Receiver mReceiver; 1021 Location mLastFixBroadcast; 1022 long mLastStatusBroadcast; 1023 1024 /** 1025 * Note: must be constructed with lock held. 1026 */ 1027 UpdateRecord(String provider, LocationRequest request, Receiver receiver) { 1028 mProvider = provider; 1029 mRequest = request; 1030 mReceiver = receiver; 1031 1032 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1033 if (records == null) { 1034 records = new ArrayList<UpdateRecord>(); 1035 mRecordsByProvider.put(provider, records); 1036 } 1037 if (!records.contains(this)) { 1038 records.add(this); 1039 } 1040 } 1041 1042 /** 1043 * Method to be called when a record will no longer be used. Calling this multiple times 1044 * must have the same effect as calling it once. 1045 */ 1046 void disposeLocked(boolean removeReceiver) { 1047 // remove from mRecordsByProvider 1048 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); 1049 if (globalRecords != null) { 1050 globalRecords.remove(this); 1051 } 1052 1053 if (!removeReceiver) return; // the caller will handle the rest 1054 1055 // remove from Receiver#mUpdateRecords 1056 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords; 1057 if (receiverRecords != null) { 1058 receiverRecords.remove(this.mProvider); 1059 1060 // and also remove the Receiver if it has no more update records 1061 if (removeReceiver && receiverRecords.size() == 0) { 1062 removeUpdatesLocked(mReceiver); 1063 } 1064 } 1065 } 1066 1067 @Override 1068 public String toString() { 1069 StringBuilder s = new StringBuilder(); 1070 s.append("UpdateRecord["); 1071 s.append(mProvider); 1072 s.append(' ').append(mReceiver.mPackageName).append('('); 1073 s.append(mReceiver.mUid).append(')'); 1074 s.append(' ').append(mRequest); 1075 s.append(']'); 1076 return s.toString(); 1077 } 1078 } 1079 1080 private Receiver getReceiver(ILocationListener listener, int pid, int uid, String packageName) { 1081 IBinder binder = listener.asBinder(); 1082 Receiver receiver = mReceivers.get(binder); 1083 if (receiver == null) { 1084 receiver = new Receiver(listener, null, pid, uid, packageName); 1085 mReceivers.put(binder, receiver); 1086 1087 try { 1088 receiver.getListener().asBinder().linkToDeath(receiver, 0); 1089 } catch (RemoteException e) { 1090 Slog.e(TAG, "linkToDeath failed:", e); 1091 return null; 1092 } 1093 } 1094 return receiver; 1095 } 1096 1097 private Receiver getReceiver(PendingIntent intent, int pid, int uid, String packageName) { 1098 Receiver receiver = mReceivers.get(intent); 1099 if (receiver == null) { 1100 receiver = new Receiver(null, intent, pid, uid, packageName); 1101 mReceivers.put(intent, receiver); 1102 } 1103 return receiver; 1104 } 1105 1106 /** 1107 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution 1108 * and consistency requirements. 1109 * 1110 * @param request the LocationRequest from which to create a sanitized version 1111 * @param shouldBeCoarse whether the sanitized version should be held to coarse resolution 1112 * constraints 1113 * @param fastestCoarseIntervalMS minimum interval allowed for coarse resolution 1114 * @return a version of request that meets the given resolution and consistency requirements 1115 * @hide 1116 */ 1117 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) { 1118 LocationRequest sanitizedRequest = new LocationRequest(request); 1119 if (resolutionLevel < RESOLUTION_LEVEL_FINE) { 1120 switch (sanitizedRequest.getQuality()) { 1121 case LocationRequest.ACCURACY_FINE: 1122 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK); 1123 break; 1124 case LocationRequest.POWER_HIGH: 1125 sanitizedRequest.setQuality(LocationRequest.POWER_LOW); 1126 break; 1127 } 1128 // throttle 1129 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1130 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS); 1131 } 1132 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1133 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS); 1134 } 1135 } 1136 // make getFastestInterval() the minimum of interval and fastest interval 1137 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) { 1138 request.setFastestInterval(request.getInterval()); 1139 } 1140 return sanitizedRequest; 1141 } 1142 1143 private void checkPackageName(String packageName) { 1144 if (packageName == null) { 1145 throw new SecurityException("invalid package name: " + packageName); 1146 } 1147 int uid = Binder.getCallingUid(); 1148 String[] packages = mPackageManager.getPackagesForUid(uid); 1149 if (packages == null) { 1150 throw new SecurityException("invalid UID " + uid); 1151 } 1152 for (String pkg : packages) { 1153 if (packageName.equals(pkg)) return; 1154 } 1155 throw new SecurityException("invalid package name: " + packageName); 1156 } 1157 1158 private void checkPendingIntent(PendingIntent intent) { 1159 if (intent == null) { 1160 throw new IllegalArgumentException("invalid pending intent: " + intent); 1161 } 1162 } 1163 1164 private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent, 1165 int pid, int uid, String packageName) { 1166 if (intent == null && listener == null) { 1167 throw new IllegalArgumentException("need eiter listener or intent"); 1168 } else if (intent != null && listener != null) { 1169 throw new IllegalArgumentException("cannot register both listener and intent"); 1170 } else if (intent != null) { 1171 checkPendingIntent(intent); 1172 return getReceiver(intent, pid, uid, packageName); 1173 } else { 1174 return getReceiver(listener, pid, uid, packageName); 1175 } 1176 } 1177 1178 @Override 1179 public void requestLocationUpdates(LocationRequest request, ILocationListener listener, 1180 PendingIntent intent, String packageName) { 1181 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1182 checkPackageName(packageName); 1183 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1184 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1185 request.getProvider()); 1186 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1187 1188 final int pid = Binder.getCallingPid(); 1189 final int uid = Binder.getCallingUid(); 1190 Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName); 1191 1192 // providers may use public location API's, need to clear identity 1193 long identity = Binder.clearCallingIdentity(); 1194 try { 1195 synchronized (mLock) { 1196 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName); 1197 } 1198 } finally { 1199 Binder.restoreCallingIdentity(identity); 1200 } 1201 } 1202 1203 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, 1204 int pid, int uid, String packageName) { 1205 // Figure out the provider. Either its explicitly request (legacy use cases), or 1206 // use the fused provider 1207 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1208 String name = request.getProvider(); 1209 if (name == null) { 1210 throw new IllegalArgumentException("provider name must not be null"); 1211 } 1212 LocationProviderInterface provider = mProvidersByName.get(name); 1213 if (provider == null) { 1214 throw new IllegalArgumentException("provider doesn't exisit: " + provider); 1215 } 1216 1217 Log.i(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) + " " + 1218 name + " " + request + " from " + packageName + "(" + uid + ")"); 1219 1220 UpdateRecord record = new UpdateRecord(name, request, receiver); 1221 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record); 1222 if (oldRecord != null) { 1223 oldRecord.disposeLocked(false); 1224 } 1225 1226 boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid)); 1227 if (isProviderEnabled) { 1228 applyRequirementsLocked(name); 1229 } else { 1230 // Notify the listener that updates are currently disabled 1231 receiver.callProviderEnabledLocked(name, false); 1232 } 1233 } 1234 1235 @Override 1236 public void removeUpdates(ILocationListener listener, PendingIntent intent, 1237 String packageName) { 1238 checkPackageName(packageName); 1239 1240 final int pid = Binder.getCallingPid(); 1241 final int uid = Binder.getCallingUid(); 1242 Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName); 1243 1244 // providers may use public location API's, need to clear identity 1245 long identity = Binder.clearCallingIdentity(); 1246 try { 1247 synchronized (mLock) { 1248 removeUpdatesLocked(receiver); 1249 } 1250 } finally { 1251 Binder.restoreCallingIdentity(identity); 1252 } 1253 } 1254 1255 private void removeUpdatesLocked(Receiver receiver) { 1256 Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver))); 1257 1258 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 1259 receiver.getListener().asBinder().unlinkToDeath(receiver, 0); 1260 synchronized (receiver) { 1261 if (receiver.mPendingBroadcasts > 0) { 1262 decrementPendingBroadcasts(); 1263 receiver.mPendingBroadcasts = 0; 1264 } 1265 } 1266 } 1267 1268 // Record which providers were associated with this listener 1269 HashSet<String> providers = new HashSet<String>(); 1270 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords; 1271 if (oldRecords != null) { 1272 // Call dispose() on the obsolete update records. 1273 for (UpdateRecord record : oldRecords.values()) { 1274 record.disposeLocked(false); 1275 } 1276 // Accumulate providers 1277 providers.addAll(oldRecords.keySet()); 1278 } 1279 1280 // update provider 1281 for (String provider : providers) { 1282 // If provider is already disabled, don't need to do anything 1283 if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) { 1284 continue; 1285 } 1286 1287 applyRequirementsLocked(provider); 1288 } 1289 } 1290 1291 @Override 1292 public Location getLastLocation(LocationRequest request, String packageName) { 1293 if (D) Log.d(TAG, "getLastLocation: " + request); 1294 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1295 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1296 checkPackageName(packageName); 1297 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1298 request.getProvider()); 1299 // no need to sanitize this request, as only the provider name is used 1300 1301 long identity = Binder.clearCallingIdentity(); 1302 try { 1303 if (mBlacklist.isBlacklisted(packageName)) { 1304 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + 1305 packageName); 1306 return null; 1307 } 1308 1309 synchronized (mLock) { 1310 // Figure out the provider. Either its explicitly request (deprecated API's), 1311 // or use the fused provider 1312 String name = request.getProvider(); 1313 if (name == null) name = LocationManager.FUSED_PROVIDER; 1314 LocationProviderInterface provider = mProvidersByName.get(name); 1315 if (provider == null) return null; 1316 1317 if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null; 1318 1319 Location location = mLastLocation.get(name); 1320 if (location == null) { 1321 return null; 1322 } 1323 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1324 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1325 if (noGPSLocation != null) { 1326 return mLocationFudger.getOrCreate(noGPSLocation); 1327 } 1328 } else { 1329 return location; 1330 } 1331 } 1332 return null; 1333 } finally { 1334 Binder.restoreCallingIdentity(identity); 1335 } 1336 } 1337 1338 @Override 1339 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, 1340 String packageName) { 1341 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1342 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1343 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel); 1344 checkPendingIntent(intent); 1345 checkPackageName(packageName); 1346 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1347 request.getProvider()); 1348 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1349 1350 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent); 1351 1352 // geo-fence manager uses the public location API, need to clear identity 1353 int uid = Binder.getCallingUid(); 1354 if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) { 1355 // temporary measure until geofences work for secondary users 1356 Log.w(TAG, "proximity alerts are currently available only to the primary user"); 1357 return; 1358 } 1359 long identity = Binder.clearCallingIdentity(); 1360 try { 1361 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, uid, packageName); 1362 } finally { 1363 Binder.restoreCallingIdentity(identity); 1364 } 1365 } 1366 1367 @Override 1368 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { 1369 checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel()); 1370 checkPendingIntent(intent); 1371 checkPackageName(packageName); 1372 1373 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); 1374 1375 // geo-fence manager uses the public location API, need to clear identity 1376 long identity = Binder.clearCallingIdentity(); 1377 try { 1378 mGeofenceManager.removeFence(geofence, intent); 1379 } finally { 1380 Binder.restoreCallingIdentity(identity); 1381 } 1382 } 1383 1384 1385 @Override 1386 public boolean addGpsStatusListener(IGpsStatusListener listener) { 1387 if (mGpsStatusProvider == null) { 1388 return false; 1389 } 1390 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1391 LocationManager.GPS_PROVIDER); 1392 1393 try { 1394 mGpsStatusProvider.addGpsStatusListener(listener); 1395 } catch (RemoteException e) { 1396 Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e); 1397 return false; 1398 } 1399 return true; 1400 } 1401 1402 @Override 1403 public void removeGpsStatusListener(IGpsStatusListener listener) { 1404 synchronized (mLock) { 1405 try { 1406 mGpsStatusProvider.removeGpsStatusListener(listener); 1407 } catch (Exception e) { 1408 Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e); 1409 } 1410 } 1411 } 1412 1413 @Override 1414 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 1415 if (provider == null) { 1416 // throw NullPointerException to remain compatible with previous implementation 1417 throw new NullPointerException(); 1418 } 1419 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1420 provider); 1421 1422 // and check for ACCESS_LOCATION_EXTRA_COMMANDS 1423 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 1424 != PackageManager.PERMISSION_GRANTED)) { 1425 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 1426 } 1427 1428 synchronized (mLock) { 1429 LocationProviderInterface p = mProvidersByName.get(provider); 1430 if (p == null) return false; 1431 1432 return p.sendExtraCommand(command, extras); 1433 } 1434 } 1435 1436 @Override 1437 public boolean sendNiResponse(int notifId, int userResponse) { 1438 if (Binder.getCallingUid() != Process.myUid()) { 1439 throw new SecurityException( 1440 "calling sendNiResponse from outside of the system is not allowed"); 1441 } 1442 try { 1443 return mNetInitiatedListener.sendNiResponse(notifId, userResponse); 1444 } catch (RemoteException e) { 1445 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); 1446 return false; 1447 } 1448 } 1449 1450 /** 1451 * @return null if the provider does not exist 1452 * @throws SecurityException if the provider is not allowed to be 1453 * accessed by the caller 1454 */ 1455 @Override 1456 public ProviderProperties getProviderProperties(String provider) { 1457 if (mProvidersByName.get(provider) == null) { 1458 return null; 1459 } 1460 1461 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1462 provider); 1463 1464 LocationProviderInterface p; 1465 synchronized (mLock) { 1466 p = mProvidersByName.get(provider); 1467 } 1468 1469 if (p == null) return null; 1470 return p.getProperties(); 1471 } 1472 1473 @Override 1474 public boolean isProviderEnabled(String provider) { 1475 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1476 provider); 1477 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1478 1479 long identity = Binder.clearCallingIdentity(); 1480 try { 1481 synchronized (mLock) { 1482 LocationProviderInterface p = mProvidersByName.get(provider); 1483 if (p == null) return false; 1484 1485 return isAllowedBySettingsLocked(provider, mCurrentUserId); 1486 } 1487 } finally { 1488 Binder.restoreCallingIdentity(identity); 1489 } 1490 } 1491 1492 private void checkCallerIsProvider() { 1493 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 1494 == PackageManager.PERMISSION_GRANTED) { 1495 return; 1496 } 1497 1498 // Previously we only used the INSTALL_LOCATION_PROVIDER 1499 // check. But that is system or signature 1500 // protection level which is not flexible enough for 1501 // providers installed oustide the system image. So 1502 // also allow providers with a UID matching the 1503 // currently bound package name 1504 1505 int uid = Binder.getCallingUid(); 1506 1507 if (mGeocodeProvider != null) { 1508 if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return; 1509 } 1510 for (LocationProviderProxy proxy : mProxyProviders) { 1511 if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return; 1512 } 1513 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 1514 "or UID of a currently bound location provider"); 1515 } 1516 1517 private boolean doesPackageHaveUid(int uid, String packageName) { 1518 if (packageName == null) { 1519 return false; 1520 } 1521 try { 1522 ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0); 1523 if (appInfo.uid != uid) { 1524 return false; 1525 } 1526 } catch (NameNotFoundException e) { 1527 return false; 1528 } 1529 return true; 1530 } 1531 1532 @Override 1533 public void reportLocation(Location location, boolean passive) { 1534 checkCallerIsProvider(); 1535 1536 if (!location.isComplete()) { 1537 Log.w(TAG, "Dropping incomplete location: " + location); 1538 return; 1539 } 1540 1541 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 1542 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 1543 m.arg1 = (passive ? 1 : 0); 1544 mLocationHandler.sendMessageAtFrontOfQueue(m); 1545 } 1546 1547 1548 private static boolean shouldBroadcastSafe( 1549 Location loc, Location lastLoc, UpdateRecord record, long now) { 1550 // Always broadcast the first update 1551 if (lastLoc == null) { 1552 return true; 1553 } 1554 1555 // Check whether sufficient time has passed 1556 long minTime = record.mRequest.getFastestInterval(); 1557 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L; 1558 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 1559 return false; 1560 } 1561 1562 // Check whether sufficient distance has been traveled 1563 double minDistance = record.mRequest.getSmallestDisplacement(); 1564 if (minDistance > 0.0) { 1565 if (loc.distanceTo(lastLoc) <= minDistance) { 1566 return false; 1567 } 1568 } 1569 1570 // Check whether sufficient number of udpates is left 1571 if (record.mRequest.getNumUpdates() <= 0) { 1572 return false; 1573 } 1574 1575 // Check whether the expiry date has passed 1576 if (record.mRequest.getExpireAt() < now) { 1577 return false; 1578 } 1579 1580 return true; 1581 } 1582 1583 private void handleLocationChangedLocked(Location location, boolean passive) { 1584 if (D) Log.d(TAG, "incoming location: " + location); 1585 1586 long now = SystemClock.elapsedRealtime(); 1587 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 1588 1589 // Skip if the provider is unknown. 1590 LocationProviderInterface p = mProvidersByName.get(provider); 1591 if (p == null) return; 1592 1593 // Update last known locations 1594 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1595 Location lastNoGPSLocation = null; 1596 Location lastLocation = mLastLocation.get(provider); 1597 if (lastLocation == null) { 1598 lastLocation = new Location(provider); 1599 mLastLocation.put(provider, lastLocation); 1600 } else { 1601 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1602 if (noGPSLocation == null && lastNoGPSLocation != null) { 1603 // New location has no no-GPS location: adopt last no-GPS location. This is set 1604 // directly into location because we do not want to notify COARSE clients. 1605 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 1606 } 1607 } 1608 lastLocation.set(location); 1609 1610 // Skip if there are no UpdateRecords for this provider. 1611 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1612 if (records == null || records.size() == 0) return; 1613 1614 // Fetch coarse location 1615 Location coarseLocation = null; 1616 if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) { 1617 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 1618 } 1619 1620 // Fetch latest status update time 1621 long newStatusUpdateTime = p.getStatusUpdateTime(); 1622 1623 // Get latest status 1624 Bundle extras = new Bundle(); 1625 int status = p.getStatus(extras); 1626 1627 ArrayList<Receiver> deadReceivers = null; 1628 ArrayList<UpdateRecord> deadUpdateRecords = null; 1629 1630 // Broadcast location or status to all listeners 1631 for (UpdateRecord r : records) { 1632 Receiver receiver = r.mReceiver; 1633 boolean receiverDead = false; 1634 1635 int receiverUserId = UserHandle.getUserId(receiver.mUid); 1636 if (receiverUserId != mCurrentUserId) { 1637 if (D) { 1638 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 1639 " (current user: " + mCurrentUserId + ", app: " + 1640 receiver.mPackageName + ")"); 1641 } 1642 continue; 1643 } 1644 1645 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 1646 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 1647 receiver.mPackageName); 1648 continue; 1649 } 1650 1651 Location notifyLocation = null; 1652 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1653 notifyLocation = coarseLocation; // use coarse location 1654 } else { 1655 notifyLocation = lastLocation; // use fine location 1656 } 1657 if (notifyLocation != null) { 1658 Location lastLoc = r.mLastFixBroadcast; 1659 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) { 1660 if (lastLoc == null) { 1661 lastLoc = new Location(notifyLocation); 1662 r.mLastFixBroadcast = lastLoc; 1663 } else { 1664 lastLoc.set(notifyLocation); 1665 } 1666 if (!receiver.callLocationChangedLocked(notifyLocation)) { 1667 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 1668 receiverDead = true; 1669 } 1670 r.mRequest.decrementNumUpdates(); 1671 } 1672 } 1673 1674 long prevStatusUpdateTime = r.mLastStatusBroadcast; 1675 if ((newStatusUpdateTime > prevStatusUpdateTime) && 1676 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 1677 1678 r.mLastStatusBroadcast = newStatusUpdateTime; 1679 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 1680 receiverDead = true; 1681 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 1682 } 1683 } 1684 1685 // track expired records 1686 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) { 1687 if (deadUpdateRecords == null) { 1688 deadUpdateRecords = new ArrayList<UpdateRecord>(); 1689 } 1690 deadUpdateRecords.add(r); 1691 } 1692 // track dead receivers 1693 if (receiverDead) { 1694 if (deadReceivers == null) { 1695 deadReceivers = new ArrayList<Receiver>(); 1696 } 1697 if (!deadReceivers.contains(receiver)) { 1698 deadReceivers.add(receiver); 1699 } 1700 } 1701 } 1702 1703 // remove dead records and receivers outside the loop 1704 if (deadReceivers != null) { 1705 for (Receiver receiver : deadReceivers) { 1706 removeUpdatesLocked(receiver); 1707 } 1708 } 1709 if (deadUpdateRecords != null) { 1710 for (UpdateRecord r : deadUpdateRecords) { 1711 r.disposeLocked(true); 1712 } 1713 } 1714 } 1715 1716 private class LocationWorkerHandler extends Handler { 1717 @Override 1718 public void handleMessage(Message msg) { 1719 switch (msg.what) { 1720 case MSG_LOCATION_CHANGED: 1721 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 1722 break; 1723 } 1724 } 1725 } 1726 1727 private void handleLocationChanged(Location location, boolean passive) { 1728 String provider = location.getProvider(); 1729 1730 if (!passive) { 1731 // notify passive provider of the new location 1732 mPassiveProvider.updateLocation(location); 1733 } 1734 1735 synchronized (mLock) { 1736 if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { 1737 handleLocationChangedLocked(location, passive); 1738 } 1739 } 1740 } 1741 1742 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 1743 @Override 1744 public void onPackageDisappeared(String packageName, int reason) { 1745 // remove all receivers associated with this package name 1746 synchronized (mLock) { 1747 ArrayList<Receiver> deadReceivers = null; 1748 1749 for (Receiver receiver : mReceivers.values()) { 1750 if (receiver.mPackageName.equals(packageName)) { 1751 if (deadReceivers == null) { 1752 deadReceivers = new ArrayList<Receiver>(); 1753 } 1754 deadReceivers.add(receiver); 1755 } 1756 } 1757 1758 // perform removal outside of mReceivers loop 1759 if (deadReceivers != null) { 1760 for (Receiver receiver : deadReceivers) { 1761 removeUpdatesLocked(receiver); 1762 } 1763 } 1764 } 1765 } 1766 }; 1767 1768 // Wake locks 1769 1770 private void incrementPendingBroadcasts() { 1771 synchronized (mWakeLock) { 1772 if (mPendingBroadcasts++ == 0) { 1773 try { 1774 mWakeLock.acquire(); 1775 log("Acquired wakelock"); 1776 } catch (Exception e) { 1777 // This is to catch a runtime exception thrown when we try to release an 1778 // already released lock. 1779 Slog.e(TAG, "exception in acquireWakeLock()", e); 1780 } 1781 } 1782 } 1783 } 1784 1785 private void decrementPendingBroadcasts() { 1786 synchronized (mWakeLock) { 1787 if (--mPendingBroadcasts == 0) { 1788 try { 1789 // Release wake lock 1790 if (mWakeLock.isHeld()) { 1791 mWakeLock.release(); 1792 log("Released wakelock"); 1793 } else { 1794 log("Can't release wakelock again!"); 1795 } 1796 } catch (Exception e) { 1797 // This is to catch a runtime exception thrown when we try to release an 1798 // already released lock. 1799 Slog.e(TAG, "exception in releaseWakeLock()", e); 1800 } 1801 } 1802 } 1803 } 1804 1805 // Geocoder 1806 1807 @Override 1808 public boolean geocoderIsPresent() { 1809 return mGeocodeProvider != null; 1810 } 1811 1812 @Override 1813 public String getFromLocation(double latitude, double longitude, int maxResults, 1814 GeocoderParams params, List<Address> addrs) { 1815 if (mGeocodeProvider != null) { 1816 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 1817 params, addrs); 1818 } 1819 return null; 1820 } 1821 1822 1823 @Override 1824 public String getFromLocationName(String locationName, 1825 double lowerLeftLatitude, double lowerLeftLongitude, 1826 double upperRightLatitude, double upperRightLongitude, int maxResults, 1827 GeocoderParams params, List<Address> addrs) { 1828 1829 if (mGeocodeProvider != null) { 1830 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 1831 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 1832 maxResults, params, addrs); 1833 } 1834 return null; 1835 } 1836 1837 // Mock Providers 1838 1839 private void checkMockPermissionsSafe() { 1840 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 1841 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 1842 if (!allowMocks) { 1843 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 1844 } 1845 1846 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 1847 PackageManager.PERMISSION_GRANTED) { 1848 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 1849 } 1850 } 1851 1852 @Override 1853 public void addTestProvider(String name, ProviderProperties properties) { 1854 checkMockPermissionsSafe(); 1855 1856 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 1857 throw new IllegalArgumentException("Cannot mock the passive location provider"); 1858 } 1859 1860 long identity = Binder.clearCallingIdentity(); 1861 synchronized (mLock) { 1862 MockProvider provider = new MockProvider(name, this, properties); 1863 // remove the real provider if we are replacing GPS or network provider 1864 if (LocationManager.GPS_PROVIDER.equals(name) 1865 || LocationManager.NETWORK_PROVIDER.equals(name) 1866 || LocationManager.FUSED_PROVIDER.equals(name)) { 1867 LocationProviderInterface p = mProvidersByName.get(name); 1868 if (p != null) { 1869 removeProviderLocked(p); 1870 } 1871 } 1872 if (mProvidersByName.get(name) != null) { 1873 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 1874 } 1875 addProviderLocked(provider); 1876 mMockProviders.put(name, provider); 1877 mLastLocation.put(name, null); 1878 updateProvidersLocked(); 1879 } 1880 Binder.restoreCallingIdentity(identity); 1881 } 1882 1883 @Override 1884 public void removeTestProvider(String provider) { 1885 checkMockPermissionsSafe(); 1886 synchronized (mLock) { 1887 MockProvider mockProvider = mMockProviders.get(provider); 1888 if (mockProvider == null) { 1889 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1890 } 1891 long identity = Binder.clearCallingIdentity(); 1892 removeProviderLocked(mProvidersByName.get(provider)); 1893 mMockProviders.remove(mockProvider); 1894 1895 // reinstate real provider if available 1896 LocationProviderInterface realProvider = mRealProviders.get(provider); 1897 if (realProvider != null) { 1898 addProviderLocked(realProvider); 1899 } 1900 mLastLocation.put(provider, null); 1901 updateProvidersLocked(); 1902 Binder.restoreCallingIdentity(identity); 1903 } 1904 } 1905 1906 @Override 1907 public void setTestProviderLocation(String provider, Location loc) { 1908 checkMockPermissionsSafe(); 1909 synchronized (mLock) { 1910 MockProvider mockProvider = mMockProviders.get(provider); 1911 if (mockProvider == null) { 1912 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1913 } 1914 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 1915 long identity = Binder.clearCallingIdentity(); 1916 mockProvider.setLocation(loc); 1917 Binder.restoreCallingIdentity(identity); 1918 } 1919 } 1920 1921 @Override 1922 public void clearTestProviderLocation(String provider) { 1923 checkMockPermissionsSafe(); 1924 synchronized (mLock) { 1925 MockProvider mockProvider = mMockProviders.get(provider); 1926 if (mockProvider == null) { 1927 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1928 } 1929 mockProvider.clearLocation(); 1930 } 1931 } 1932 1933 @Override 1934 public void setTestProviderEnabled(String provider, boolean enabled) { 1935 checkMockPermissionsSafe(); 1936 synchronized (mLock) { 1937 MockProvider mockProvider = mMockProviders.get(provider); 1938 if (mockProvider == null) { 1939 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1940 } 1941 long identity = Binder.clearCallingIdentity(); 1942 if (enabled) { 1943 mockProvider.enable(); 1944 mEnabledProviders.add(provider); 1945 mDisabledProviders.remove(provider); 1946 } else { 1947 mockProvider.disable(); 1948 mEnabledProviders.remove(provider); 1949 mDisabledProviders.add(provider); 1950 } 1951 updateProvidersLocked(); 1952 Binder.restoreCallingIdentity(identity); 1953 } 1954 } 1955 1956 @Override 1957 public void clearTestProviderEnabled(String provider) { 1958 checkMockPermissionsSafe(); 1959 synchronized (mLock) { 1960 MockProvider mockProvider = mMockProviders.get(provider); 1961 if (mockProvider == null) { 1962 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1963 } 1964 long identity = Binder.clearCallingIdentity(); 1965 mEnabledProviders.remove(provider); 1966 mDisabledProviders.remove(provider); 1967 updateProvidersLocked(); 1968 Binder.restoreCallingIdentity(identity); 1969 } 1970 } 1971 1972 @Override 1973 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 1974 checkMockPermissionsSafe(); 1975 synchronized (mLock) { 1976 MockProvider mockProvider = mMockProviders.get(provider); 1977 if (mockProvider == null) { 1978 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1979 } 1980 mockProvider.setStatus(status, extras, updateTime); 1981 } 1982 } 1983 1984 @Override 1985 public void clearTestProviderStatus(String provider) { 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.clearStatus(); 1993 } 1994 } 1995 1996 private void log(String log) { 1997 if (Log.isLoggable(TAG, Log.VERBOSE)) { 1998 Slog.d(TAG, log); 1999 } 2000 } 2001 2002 @Override 2003 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2004 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2005 != PackageManager.PERMISSION_GRANTED) { 2006 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2007 + Binder.getCallingPid() 2008 + ", uid=" + Binder.getCallingUid()); 2009 return; 2010 } 2011 2012 synchronized (mLock) { 2013 pw.println("Current Location Manager state:"); 2014 pw.println(" Location Listeners:"); 2015 for (Receiver receiver : mReceivers.values()) { 2016 pw.println(" " + receiver); 2017 } 2018 pw.println(" Records by Provider:"); 2019 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2020 pw.println(" " + entry.getKey() + ":"); 2021 for (UpdateRecord record : entry.getValue()) { 2022 pw.println(" " + record); 2023 } 2024 } 2025 pw.println(" Last Known Locations:"); 2026 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2027 String provider = entry.getKey(); 2028 Location location = entry.getValue(); 2029 pw.println(" " + provider + ": " + location); 2030 } 2031 2032 mGeofenceManager.dump(pw); 2033 2034 if (mEnabledProviders.size() > 0) { 2035 pw.println(" Enabled Providers:"); 2036 for (String i : mEnabledProviders) { 2037 pw.println(" " + i); 2038 } 2039 2040 } 2041 if (mDisabledProviders.size() > 0) { 2042 pw.println(" Disabled Providers:"); 2043 for (String i : mDisabledProviders) { 2044 pw.println(" " + i); 2045 } 2046 } 2047 pw.append(" "); 2048 mBlacklist.dump(pw); 2049 if (mMockProviders.size() > 0) { 2050 pw.println(" Mock Providers:"); 2051 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2052 i.getValue().dump(pw, " "); 2053 } 2054 } 2055 2056 pw.append(" fudger: "); 2057 mLocationFudger.dump(fd, pw, args); 2058 2059 if (args.length > 0 && "short".equals(args[0])) { 2060 return; 2061 } 2062 for (LocationProviderInterface provider: mProviders) { 2063 pw.print(provider.getName() + " Internal State"); 2064 if (provider instanceof LocationProviderProxy) { 2065 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2066 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2067 } 2068 pw.println(":"); 2069 provider.dump(fd, pw, args); 2070 } 2071 } 2072 } 2073} 2074