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