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