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