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