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