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