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