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