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