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