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