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