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(new Bundle(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(new Location(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, new Location(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 if (D) Log.d(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 if (D) 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 new Location(mLocationFudger.getOrCreate(noGPSLocation)); 1327 } 1328 } else { 1329 return new Location(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 applyRequirementsLocked(provider); 1714 } 1715 } 1716 1717 private class LocationWorkerHandler extends Handler { 1718 @Override 1719 public void handleMessage(Message msg) { 1720 switch (msg.what) { 1721 case MSG_LOCATION_CHANGED: 1722 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 1723 break; 1724 } 1725 } 1726 } 1727 1728 private void handleLocationChanged(Location location, boolean passive) { 1729 String provider = location.getProvider(); 1730 1731 if (!passive) { 1732 // notify passive provider of the new location 1733 mPassiveProvider.updateLocation(location); 1734 } 1735 1736 synchronized (mLock) { 1737 if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { 1738 handleLocationChangedLocked(location, passive); 1739 } 1740 } 1741 } 1742 1743 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 1744 @Override 1745 public void onPackageDisappeared(String packageName, int reason) { 1746 // remove all receivers associated with this package name 1747 synchronized (mLock) { 1748 ArrayList<Receiver> deadReceivers = null; 1749 1750 for (Receiver receiver : mReceivers.values()) { 1751 if (receiver.mPackageName.equals(packageName)) { 1752 if (deadReceivers == null) { 1753 deadReceivers = new ArrayList<Receiver>(); 1754 } 1755 deadReceivers.add(receiver); 1756 } 1757 } 1758 1759 // perform removal outside of mReceivers loop 1760 if (deadReceivers != null) { 1761 for (Receiver receiver : deadReceivers) { 1762 removeUpdatesLocked(receiver); 1763 } 1764 } 1765 } 1766 } 1767 }; 1768 1769 // Wake locks 1770 1771 private void incrementPendingBroadcasts() { 1772 synchronized (mWakeLock) { 1773 if (mPendingBroadcasts++ == 0) { 1774 try { 1775 mWakeLock.acquire(); 1776 log("Acquired wakelock"); 1777 } catch (Exception e) { 1778 // This is to catch a runtime exception thrown when we try to release an 1779 // already released lock. 1780 Slog.e(TAG, "exception in acquireWakeLock()", e); 1781 } 1782 } 1783 } 1784 } 1785 1786 private void decrementPendingBroadcasts() { 1787 synchronized (mWakeLock) { 1788 if (--mPendingBroadcasts == 0) { 1789 try { 1790 // Release wake lock 1791 if (mWakeLock.isHeld()) { 1792 mWakeLock.release(); 1793 log("Released wakelock"); 1794 } else { 1795 log("Can't release wakelock again!"); 1796 } 1797 } catch (Exception e) { 1798 // This is to catch a runtime exception thrown when we try to release an 1799 // already released lock. 1800 Slog.e(TAG, "exception in releaseWakeLock()", e); 1801 } 1802 } 1803 } 1804 } 1805 1806 // Geocoder 1807 1808 @Override 1809 public boolean geocoderIsPresent() { 1810 return mGeocodeProvider != null; 1811 } 1812 1813 @Override 1814 public String getFromLocation(double latitude, double longitude, int maxResults, 1815 GeocoderParams params, List<Address> addrs) { 1816 if (mGeocodeProvider != null) { 1817 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 1818 params, addrs); 1819 } 1820 return null; 1821 } 1822 1823 1824 @Override 1825 public String getFromLocationName(String locationName, 1826 double lowerLeftLatitude, double lowerLeftLongitude, 1827 double upperRightLatitude, double upperRightLongitude, int maxResults, 1828 GeocoderParams params, List<Address> addrs) { 1829 1830 if (mGeocodeProvider != null) { 1831 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 1832 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 1833 maxResults, params, addrs); 1834 } 1835 return null; 1836 } 1837 1838 // Mock Providers 1839 1840 private void checkMockPermissionsSafe() { 1841 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 1842 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 1843 if (!allowMocks) { 1844 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 1845 } 1846 1847 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 1848 PackageManager.PERMISSION_GRANTED) { 1849 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 1850 } 1851 } 1852 1853 @Override 1854 public void addTestProvider(String name, ProviderProperties properties) { 1855 checkMockPermissionsSafe(); 1856 1857 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 1858 throw new IllegalArgumentException("Cannot mock the passive location provider"); 1859 } 1860 1861 long identity = Binder.clearCallingIdentity(); 1862 synchronized (mLock) { 1863 MockProvider provider = new MockProvider(name, this, properties); 1864 // remove the real provider if we are replacing GPS or network provider 1865 if (LocationManager.GPS_PROVIDER.equals(name) 1866 || LocationManager.NETWORK_PROVIDER.equals(name) 1867 || LocationManager.FUSED_PROVIDER.equals(name)) { 1868 LocationProviderInterface p = mProvidersByName.get(name); 1869 if (p != null) { 1870 removeProviderLocked(p); 1871 } 1872 } 1873 if (mProvidersByName.get(name) != null) { 1874 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 1875 } 1876 addProviderLocked(provider); 1877 mMockProviders.put(name, provider); 1878 mLastLocation.put(name, null); 1879 updateProvidersLocked(); 1880 } 1881 Binder.restoreCallingIdentity(identity); 1882 } 1883 1884 @Override 1885 public void removeTestProvider(String provider) { 1886 checkMockPermissionsSafe(); 1887 synchronized (mLock) { 1888 MockProvider mockProvider = mMockProviders.get(provider); 1889 if (mockProvider == null) { 1890 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1891 } 1892 long identity = Binder.clearCallingIdentity(); 1893 removeProviderLocked(mProvidersByName.get(provider)); 1894 mMockProviders.remove(mockProvider); 1895 1896 // reinstate real provider if available 1897 LocationProviderInterface realProvider = mRealProviders.get(provider); 1898 if (realProvider != null) { 1899 addProviderLocked(realProvider); 1900 } 1901 mLastLocation.put(provider, null); 1902 updateProvidersLocked(); 1903 Binder.restoreCallingIdentity(identity); 1904 } 1905 } 1906 1907 @Override 1908 public void setTestProviderLocation(String provider, Location loc) { 1909 checkMockPermissionsSafe(); 1910 synchronized (mLock) { 1911 MockProvider mockProvider = mMockProviders.get(provider); 1912 if (mockProvider == null) { 1913 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1914 } 1915 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 1916 long identity = Binder.clearCallingIdentity(); 1917 mockProvider.setLocation(loc); 1918 Binder.restoreCallingIdentity(identity); 1919 } 1920 } 1921 1922 @Override 1923 public void clearTestProviderLocation(String provider) { 1924 checkMockPermissionsSafe(); 1925 synchronized (mLock) { 1926 MockProvider mockProvider = mMockProviders.get(provider); 1927 if (mockProvider == null) { 1928 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1929 } 1930 mockProvider.clearLocation(); 1931 } 1932 } 1933 1934 @Override 1935 public void setTestProviderEnabled(String provider, boolean enabled) { 1936 checkMockPermissionsSafe(); 1937 synchronized (mLock) { 1938 MockProvider mockProvider = mMockProviders.get(provider); 1939 if (mockProvider == null) { 1940 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1941 } 1942 long identity = Binder.clearCallingIdentity(); 1943 if (enabled) { 1944 mockProvider.enable(); 1945 mEnabledProviders.add(provider); 1946 mDisabledProviders.remove(provider); 1947 } else { 1948 mockProvider.disable(); 1949 mEnabledProviders.remove(provider); 1950 mDisabledProviders.add(provider); 1951 } 1952 updateProvidersLocked(); 1953 Binder.restoreCallingIdentity(identity); 1954 } 1955 } 1956 1957 @Override 1958 public void clearTestProviderEnabled(String provider) { 1959 checkMockPermissionsSafe(); 1960 synchronized (mLock) { 1961 MockProvider mockProvider = mMockProviders.get(provider); 1962 if (mockProvider == null) { 1963 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1964 } 1965 long identity = Binder.clearCallingIdentity(); 1966 mEnabledProviders.remove(provider); 1967 mDisabledProviders.remove(provider); 1968 updateProvidersLocked(); 1969 Binder.restoreCallingIdentity(identity); 1970 } 1971 } 1972 1973 @Override 1974 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 1975 checkMockPermissionsSafe(); 1976 synchronized (mLock) { 1977 MockProvider mockProvider = mMockProviders.get(provider); 1978 if (mockProvider == null) { 1979 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1980 } 1981 mockProvider.setStatus(status, extras, updateTime); 1982 } 1983 } 1984 1985 @Override 1986 public void clearTestProviderStatus(String provider) { 1987 checkMockPermissionsSafe(); 1988 synchronized (mLock) { 1989 MockProvider mockProvider = mMockProviders.get(provider); 1990 if (mockProvider == null) { 1991 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1992 } 1993 mockProvider.clearStatus(); 1994 } 1995 } 1996 1997 private void log(String log) { 1998 if (Log.isLoggable(TAG, Log.VERBOSE)) { 1999 Slog.d(TAG, log); 2000 } 2001 } 2002 2003 @Override 2004 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2005 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2006 != PackageManager.PERMISSION_GRANTED) { 2007 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2008 + Binder.getCallingPid() 2009 + ", uid=" + Binder.getCallingUid()); 2010 return; 2011 } 2012 2013 synchronized (mLock) { 2014 pw.println("Current Location Manager state:"); 2015 pw.println(" Location Listeners:"); 2016 for (Receiver receiver : mReceivers.values()) { 2017 pw.println(" " + receiver); 2018 } 2019 pw.println(" Records by Provider:"); 2020 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2021 pw.println(" " + entry.getKey() + ":"); 2022 for (UpdateRecord record : entry.getValue()) { 2023 pw.println(" " + record); 2024 } 2025 } 2026 pw.println(" Last Known Locations:"); 2027 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2028 String provider = entry.getKey(); 2029 Location location = entry.getValue(); 2030 pw.println(" " + provider + ": " + location); 2031 } 2032 2033 mGeofenceManager.dump(pw); 2034 2035 if (mEnabledProviders.size() > 0) { 2036 pw.println(" Enabled Providers:"); 2037 for (String i : mEnabledProviders) { 2038 pw.println(" " + i); 2039 } 2040 2041 } 2042 if (mDisabledProviders.size() > 0) { 2043 pw.println(" Disabled Providers:"); 2044 for (String i : mDisabledProviders) { 2045 pw.println(" " + i); 2046 } 2047 } 2048 pw.append(" "); 2049 mBlacklist.dump(pw); 2050 if (mMockProviders.size() > 0) { 2051 pw.println(" Mock Providers:"); 2052 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2053 i.getValue().dump(pw, " "); 2054 } 2055 } 2056 2057 pw.append(" fudger: "); 2058 mLocationFudger.dump(fd, pw, args); 2059 2060 if (args.length > 0 && "short".equals(args[0])) { 2061 return; 2062 } 2063 for (LocationProviderInterface provider: mProviders) { 2064 pw.print(provider.getName() + " Internal State"); 2065 if (provider instanceof LocationProviderProxy) { 2066 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2067 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2068 } 2069 pw.println(":"); 2070 provider.dump(fd, pw, args); 2071 } 2072 } 2073 } 2074} 2075