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