LocationManagerService.java revision da479c5f8c9675dc11b3d6c4024749064d54bb67
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 checkPermissionForProvider(getBestCallingPermission(), provider); 1344 1345 LocationProviderInterface p; 1346 synchronized (mLock) { 1347 p = mProvidersByName.get(provider); 1348 } 1349 1350 if (p == null) return null; 1351 return p.getProperties(); 1352 } 1353 1354 @Override 1355 public boolean isProviderEnabled(String provider) { 1356 checkPermissionForProvider(getBestCallingPermission(), provider); 1357 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1358 1359 long identity = Binder.clearCallingIdentity(); 1360 try { 1361 synchronized (mLock) { 1362 LocationProviderInterface p = mProvidersByName.get(provider); 1363 if (p == null) return false; 1364 1365 return isAllowedBySettingsLocked(provider, mCurrentUserId); 1366 } 1367 } finally { 1368 Binder.restoreCallingIdentity(identity); 1369 } 1370 } 1371 1372 private void checkCallerIsProvider() { 1373 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 1374 == PackageManager.PERMISSION_GRANTED) { 1375 return; 1376 } 1377 1378 // Previously we only used the INSTALL_LOCATION_PROVIDER 1379 // check. But that is system or signature 1380 // protection level which is not flexible enough for 1381 // providers installed oustide the system image. So 1382 // also allow providers with a UID matching the 1383 // currently bound package name 1384 1385 int uid = Binder.getCallingUid(); 1386 1387 if (mGeocodeProvider != null) { 1388 if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return; 1389 } 1390 for (LocationProviderProxy proxy : mProxyProviders) { 1391 if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return; 1392 } 1393 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 1394 "or UID of a currently bound location provider"); 1395 } 1396 1397 private boolean doesPackageHaveUid(int uid, String packageName) { 1398 if (packageName == null) { 1399 return false; 1400 } 1401 try { 1402 ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0); 1403 if (appInfo.uid != uid) { 1404 return false; 1405 } 1406 } catch (NameNotFoundException e) { 1407 return false; 1408 } 1409 return true; 1410 } 1411 1412 @Override 1413 public void reportLocation(Location location, boolean passive) { 1414 checkCallerIsProvider(); 1415 1416 if (!location.isComplete()) { 1417 Log.w(TAG, "Dropping incomplete location: " + location); 1418 return; 1419 } 1420 1421 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 1422 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 1423 m.arg1 = (passive ? 1 : 0); 1424 mLocationHandler.sendMessageAtFrontOfQueue(m); 1425 } 1426 1427 1428 private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) { 1429 // Always broadcast the first update 1430 if (lastLoc == null) { 1431 return true; 1432 } 1433 1434 // Check whether sufficient time has passed 1435 long minTime = record.mRequest.getFastestInterval(); 1436 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L; 1437 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 1438 return false; 1439 } 1440 1441 // Check whether sufficient distance has been traveled 1442 double minDistance = record.mRequest.getSmallestDisplacement(); 1443 if (minDistance > 0.0) { 1444 if (loc.distanceTo(lastLoc) <= minDistance) { 1445 return false; 1446 } 1447 } 1448 1449 return true; 1450 } 1451 1452 private void handleLocationChangedLocked(Location location, boolean passive) { 1453 if (D) Log.d(TAG, "incoming location: " + location); 1454 1455 long now = SystemClock.elapsedRealtime(); 1456 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 1457 1458 // Skip if the provider is unknown. 1459 LocationProviderInterface p = mProvidersByName.get(provider); 1460 if (p == null) return; 1461 1462 // Update last known locations 1463 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1464 Location lastNoGPSLocation = null; 1465 Location lastLocation = mLastLocation.get(provider); 1466 if (lastLocation == null) { 1467 lastLocation = new Location(provider); 1468 mLastLocation.put(provider, lastLocation); 1469 } else { 1470 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1471 if (noGPSLocation == null && lastNoGPSLocation != null) { 1472 // New location has no no-GPS location: adopt last no-GPS location. This is set 1473 // directly into location because we do not want to notify COARSE clients. 1474 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 1475 } 1476 } 1477 lastLocation.set(location); 1478 1479 // Skip if there are no UpdateRecords for this provider. 1480 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1481 if (records == null || records.size() == 0) return; 1482 1483 // Fetch coarse location 1484 Location coarseLocation = null; 1485 if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) { 1486 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 1487 } 1488 1489 // Fetch latest status update time 1490 long newStatusUpdateTime = p.getStatusUpdateTime(); 1491 1492 // Get latest status 1493 Bundle extras = new Bundle(); 1494 int status = p.getStatus(extras); 1495 1496 ArrayList<Receiver> deadReceivers = null; 1497 ArrayList<UpdateRecord> deadUpdateRecords = null; 1498 1499 // Broadcast location or status to all listeners 1500 for (UpdateRecord r : records) { 1501 Receiver receiver = r.mReceiver; 1502 boolean receiverDead = false; 1503 1504 int receiverUserId = UserHandle.getUserId(receiver.mUid); 1505 if (receiverUserId != mCurrentUserId) { 1506 if (D) { 1507 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 1508 " (current user: " + mCurrentUserId + ", app: " + 1509 receiver.mPackageName + ")"); 1510 } 1511 continue; 1512 } 1513 1514 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 1515 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 1516 receiver.mPackageName); 1517 continue; 1518 } 1519 1520 Location notifyLocation = null; 1521 if (ACCESS_FINE_LOCATION.equals(receiver.mPermission)) { 1522 notifyLocation = lastLocation; // use fine location 1523 } else { 1524 notifyLocation = coarseLocation; // use coarse location if available 1525 } 1526 if (notifyLocation != null) { 1527 Location lastLoc = r.mLastFixBroadcast; 1528 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r)) { 1529 if (lastLoc == null) { 1530 lastLoc = new Location(notifyLocation); 1531 r.mLastFixBroadcast = lastLoc; 1532 } else { 1533 lastLoc.set(notifyLocation); 1534 } 1535 if (!receiver.callLocationChangedLocked(notifyLocation)) { 1536 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 1537 receiverDead = true; 1538 } 1539 } 1540 } 1541 1542 long prevStatusUpdateTime = r.mLastStatusBroadcast; 1543 if ((newStatusUpdateTime > prevStatusUpdateTime) && 1544 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 1545 1546 r.mLastStatusBroadcast = newStatusUpdateTime; 1547 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 1548 receiverDead = true; 1549 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 1550 } 1551 } 1552 1553 // track expired records 1554 if (r.mRequest.getNumUpdates() == 0 || r.mRequest.getExpireAt() < now) { 1555 if (deadUpdateRecords == null) { 1556 deadUpdateRecords = new ArrayList<UpdateRecord>(); 1557 } 1558 deadUpdateRecords.add(r); 1559 } 1560 // track dead receivers 1561 if (receiverDead) { 1562 if (deadReceivers == null) { 1563 deadReceivers = new ArrayList<Receiver>(); 1564 } 1565 if (!deadReceivers.contains(receiver)) { 1566 deadReceivers.add(receiver); 1567 } 1568 } 1569 } 1570 1571 // remove dead records and receivers outside the loop 1572 if (deadReceivers != null) { 1573 for (Receiver receiver : deadReceivers) { 1574 removeUpdatesLocked(receiver); 1575 } 1576 } 1577 if (deadUpdateRecords != null) { 1578 for (UpdateRecord r : deadUpdateRecords) { 1579 r.disposeLocked(true); 1580 } 1581 } 1582 } 1583 1584 private class LocationWorkerHandler extends Handler { 1585 @Override 1586 public void handleMessage(Message msg) { 1587 switch (msg.what) { 1588 case MSG_LOCATION_CHANGED: 1589 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 1590 break; 1591 } 1592 } 1593 } 1594 1595 private void handleLocationChanged(Location location, boolean passive) { 1596 String provider = location.getProvider(); 1597 1598 if (!passive) { 1599 // notify passive provider of the new location 1600 mPassiveProvider.updateLocation(location); 1601 } 1602 1603 synchronized (mLock) { 1604 if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { 1605 handleLocationChangedLocked(location, passive); 1606 } 1607 } 1608 } 1609 1610 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 1611 @Override 1612 public void onPackageDisappeared(String packageName, int reason) { 1613 // remove all receivers associated with this package name 1614 synchronized (mLock) { 1615 ArrayList<Receiver> deadReceivers = null; 1616 1617 for (Receiver receiver : mReceivers.values()) { 1618 if (receiver.mPackageName.equals(packageName)) { 1619 if (deadReceivers == null) { 1620 deadReceivers = new ArrayList<Receiver>(); 1621 } 1622 deadReceivers.add(receiver); 1623 } 1624 } 1625 1626 // perform removal outside of mReceivers loop 1627 if (deadReceivers != null) { 1628 for (Receiver receiver : deadReceivers) { 1629 removeUpdatesLocked(receiver); 1630 } 1631 } 1632 } 1633 } 1634 }; 1635 1636 // Wake locks 1637 1638 private void incrementPendingBroadcasts() { 1639 synchronized (mWakeLock) { 1640 if (mPendingBroadcasts++ == 0) { 1641 try { 1642 mWakeLock.acquire(); 1643 log("Acquired wakelock"); 1644 } catch (Exception e) { 1645 // This is to catch a runtime exception thrown when we try to release an 1646 // already released lock. 1647 Slog.e(TAG, "exception in acquireWakeLock()", e); 1648 } 1649 } 1650 } 1651 } 1652 1653 private void decrementPendingBroadcasts() { 1654 synchronized (mWakeLock) { 1655 if (--mPendingBroadcasts == 0) { 1656 try { 1657 // Release wake lock 1658 if (mWakeLock.isHeld()) { 1659 mWakeLock.release(); 1660 log("Released wakelock"); 1661 } else { 1662 log("Can't release wakelock again!"); 1663 } 1664 } catch (Exception e) { 1665 // This is to catch a runtime exception thrown when we try to release an 1666 // already released lock. 1667 Slog.e(TAG, "exception in releaseWakeLock()", e); 1668 } 1669 } 1670 } 1671 } 1672 1673 // Geocoder 1674 1675 @Override 1676 public boolean geocoderIsPresent() { 1677 return mGeocodeProvider != null; 1678 } 1679 1680 @Override 1681 public String getFromLocation(double latitude, double longitude, int maxResults, 1682 GeocoderParams params, List<Address> addrs) { 1683 if (mGeocodeProvider != null) { 1684 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 1685 params, addrs); 1686 } 1687 return null; 1688 } 1689 1690 1691 @Override 1692 public String getFromLocationName(String locationName, 1693 double lowerLeftLatitude, double lowerLeftLongitude, 1694 double upperRightLatitude, double upperRightLongitude, int maxResults, 1695 GeocoderParams params, List<Address> addrs) { 1696 1697 if (mGeocodeProvider != null) { 1698 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 1699 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 1700 maxResults, params, addrs); 1701 } 1702 return null; 1703 } 1704 1705 // Mock Providers 1706 1707 private void checkMockPermissionsSafe() { 1708 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 1709 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 1710 if (!allowMocks) { 1711 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 1712 } 1713 1714 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 1715 PackageManager.PERMISSION_GRANTED) { 1716 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 1717 } 1718 } 1719 1720 @Override 1721 public void addTestProvider(String name, ProviderProperties properties) { 1722 checkMockPermissionsSafe(); 1723 1724 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 1725 throw new IllegalArgumentException("Cannot mock the passive location provider"); 1726 } 1727 1728 long identity = Binder.clearCallingIdentity(); 1729 synchronized (mLock) { 1730 MockProvider provider = new MockProvider(name, this, properties); 1731 // remove the real provider if we are replacing GPS or network provider 1732 if (LocationManager.GPS_PROVIDER.equals(name) 1733 || LocationManager.NETWORK_PROVIDER.equals(name) 1734 || LocationManager.FUSED_PROVIDER.equals(name)) { 1735 LocationProviderInterface p = mProvidersByName.get(name); 1736 if (p != null) { 1737 removeProviderLocked(p); 1738 } 1739 } 1740 if (mProvidersByName.get(name) != null) { 1741 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 1742 } 1743 addProviderLocked(provider); 1744 mMockProviders.put(name, provider); 1745 mLastLocation.put(name, null); 1746 updateProvidersLocked(); 1747 } 1748 Binder.restoreCallingIdentity(identity); 1749 } 1750 1751 @Override 1752 public void removeTestProvider(String provider) { 1753 checkMockPermissionsSafe(); 1754 synchronized (mLock) { 1755 MockProvider mockProvider = mMockProviders.get(provider); 1756 if (mockProvider == null) { 1757 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1758 } 1759 long identity = Binder.clearCallingIdentity(); 1760 removeProviderLocked(mProvidersByName.get(provider)); 1761 mMockProviders.remove(mockProvider); 1762 1763 // reinstate real provider if available 1764 LocationProviderInterface realProvider = mRealProviders.get(provider); 1765 if (realProvider != null) { 1766 addProviderLocked(realProvider); 1767 } 1768 mLastLocation.put(provider, null); 1769 updateProvidersLocked(); 1770 Binder.restoreCallingIdentity(identity); 1771 } 1772 } 1773 1774 @Override 1775 public void setTestProviderLocation(String provider, Location loc) { 1776 checkMockPermissionsSafe(); 1777 synchronized (mLock) { 1778 MockProvider mockProvider = mMockProviders.get(provider); 1779 if (mockProvider == null) { 1780 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1781 } 1782 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 1783 long identity = Binder.clearCallingIdentity(); 1784 mockProvider.setLocation(loc); 1785 Binder.restoreCallingIdentity(identity); 1786 } 1787 } 1788 1789 @Override 1790 public void clearTestProviderLocation(String provider) { 1791 checkMockPermissionsSafe(); 1792 synchronized (mLock) { 1793 MockProvider mockProvider = mMockProviders.get(provider); 1794 if (mockProvider == null) { 1795 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1796 } 1797 mockProvider.clearLocation(); 1798 } 1799 } 1800 1801 @Override 1802 public void setTestProviderEnabled(String provider, boolean enabled) { 1803 checkMockPermissionsSafe(); 1804 synchronized (mLock) { 1805 MockProvider mockProvider = mMockProviders.get(provider); 1806 if (mockProvider == null) { 1807 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1808 } 1809 long identity = Binder.clearCallingIdentity(); 1810 if (enabled) { 1811 mockProvider.enable(); 1812 mEnabledProviders.add(provider); 1813 mDisabledProviders.remove(provider); 1814 } else { 1815 mockProvider.disable(); 1816 mEnabledProviders.remove(provider); 1817 mDisabledProviders.add(provider); 1818 } 1819 updateProvidersLocked(); 1820 Binder.restoreCallingIdentity(identity); 1821 } 1822 } 1823 1824 @Override 1825 public void clearTestProviderEnabled(String provider) { 1826 checkMockPermissionsSafe(); 1827 synchronized (mLock) { 1828 MockProvider mockProvider = mMockProviders.get(provider); 1829 if (mockProvider == null) { 1830 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1831 } 1832 long identity = Binder.clearCallingIdentity(); 1833 mEnabledProviders.remove(provider); 1834 mDisabledProviders.remove(provider); 1835 updateProvidersLocked(); 1836 Binder.restoreCallingIdentity(identity); 1837 } 1838 } 1839 1840 @Override 1841 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 1842 checkMockPermissionsSafe(); 1843 synchronized (mLock) { 1844 MockProvider mockProvider = mMockProviders.get(provider); 1845 if (mockProvider == null) { 1846 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1847 } 1848 mockProvider.setStatus(status, extras, updateTime); 1849 } 1850 } 1851 1852 @Override 1853 public void clearTestProviderStatus(String provider) { 1854 checkMockPermissionsSafe(); 1855 synchronized (mLock) { 1856 MockProvider mockProvider = mMockProviders.get(provider); 1857 if (mockProvider == null) { 1858 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 1859 } 1860 mockProvider.clearStatus(); 1861 } 1862 } 1863 1864 private void log(String log) { 1865 if (Log.isLoggable(TAG, Log.VERBOSE)) { 1866 Slog.d(TAG, log); 1867 } 1868 } 1869 1870 @Override 1871 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1872 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1873 != PackageManager.PERMISSION_GRANTED) { 1874 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 1875 + Binder.getCallingPid() 1876 + ", uid=" + Binder.getCallingUid()); 1877 return; 1878 } 1879 1880 synchronized (mLock) { 1881 pw.println("Current Location Manager state:"); 1882 pw.println(" Location Listeners:"); 1883 for (Receiver receiver : mReceivers.values()) { 1884 pw.println(" " + receiver); 1885 } 1886 pw.println(" Records by Provider:"); 1887 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 1888 pw.println(" " + entry.getKey() + ":"); 1889 for (UpdateRecord record : entry.getValue()) { 1890 pw.println(" " + record); 1891 } 1892 } 1893 pw.println(" Last Known Locations:"); 1894 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 1895 String provider = entry.getKey(); 1896 Location location = entry.getValue(); 1897 pw.println(" " + provider + ": " + location); 1898 } 1899 1900 mGeofenceManager.dump(pw); 1901 1902 if (mEnabledProviders.size() > 0) { 1903 pw.println(" Enabled Providers:"); 1904 for (String i : mEnabledProviders) { 1905 pw.println(" " + i); 1906 } 1907 1908 } 1909 if (mDisabledProviders.size() > 0) { 1910 pw.println(" Disabled Providers:"); 1911 for (String i : mDisabledProviders) { 1912 pw.println(" " + i); 1913 } 1914 } 1915 pw.append(" "); 1916 mBlacklist.dump(pw); 1917 if (mMockProviders.size() > 0) { 1918 pw.println(" Mock Providers:"); 1919 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 1920 i.getValue().dump(pw, " "); 1921 } 1922 } 1923 1924 pw.append(" fudger: "); 1925 mLocationFudger.dump(fd, pw, args); 1926 1927 if (args.length > 0 && "short".equals(args[0])) { 1928 return; 1929 } 1930 for (LocationProviderInterface provider: mProviders) { 1931 pw.print(provider.getName() + " Internal State"); 1932 if (provider instanceof LocationProviderProxy) { 1933 LocationProviderProxy proxy = (LocationProviderProxy) provider; 1934 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 1935 } 1936 pw.println(":"); 1937 provider.dump(fd, pw, args); 1938 } 1939 } 1940 } 1941} 1942