LocationManagerService.java revision 07ee5d1f1db4d6df4bdb52af2eb4ab7b167df0b4
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 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, 1794 // so we discourage its use 1795 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1796 1797 int uid = Binder.getCallingUid(); 1798 long identity = Binder.clearCallingIdentity(); 1799 try { 1800 synchronized (mLock) { 1801 LocationProviderInterface p = mProvidersByName.get(provider); 1802 if (p == null) return false; 1803 1804 return isAllowedByUserSettingsLocked(provider, uid); 1805 } 1806 } finally { 1807 Binder.restoreCallingIdentity(identity); 1808 } 1809 } 1810 1811 /** 1812 * Returns "true" if the UID belongs to a bound location provider. 1813 * 1814 * @param uid the uid 1815 * @return true if uid belongs to a bound location provider 1816 */ 1817 private boolean isUidALocationProvider(int uid) { 1818 if (uid == Process.SYSTEM_UID) { 1819 return true; 1820 } 1821 if (mGeocodeProvider != null) { 1822 if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return true; 1823 } 1824 for (LocationProviderProxy proxy : mProxyProviders) { 1825 if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return true; 1826 } 1827 return false; 1828 } 1829 1830 private void checkCallerIsProvider() { 1831 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 1832 == PackageManager.PERMISSION_GRANTED) { 1833 return; 1834 } 1835 1836 // Previously we only used the INSTALL_LOCATION_PROVIDER 1837 // check. But that is system or signature 1838 // protection level which is not flexible enough for 1839 // providers installed oustide the system image. So 1840 // also allow providers with a UID matching the 1841 // currently bound package name 1842 1843 if (isUidALocationProvider(Binder.getCallingUid())) { 1844 return; 1845 } 1846 1847 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 1848 "or UID of a currently bound location provider"); 1849 } 1850 1851 private boolean doesPackageHaveUid(int uid, String packageName) { 1852 if (packageName == null) { 1853 return false; 1854 } 1855 try { 1856 ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0); 1857 if (appInfo.uid != uid) { 1858 return false; 1859 } 1860 } catch (NameNotFoundException e) { 1861 return false; 1862 } 1863 return true; 1864 } 1865 1866 @Override 1867 public void reportLocation(Location location, boolean passive) { 1868 checkCallerIsProvider(); 1869 1870 if (!location.isComplete()) { 1871 Log.w(TAG, "Dropping incomplete location: " + location); 1872 return; 1873 } 1874 1875 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 1876 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 1877 m.arg1 = (passive ? 1 : 0); 1878 mLocationHandler.sendMessageAtFrontOfQueue(m); 1879 } 1880 1881 1882 private static boolean shouldBroadcastSafe( 1883 Location loc, Location lastLoc, UpdateRecord record, long now) { 1884 // Always broadcast the first update 1885 if (lastLoc == null) { 1886 return true; 1887 } 1888 1889 // Check whether sufficient time has passed 1890 long minTime = record.mRequest.getFastestInterval(); 1891 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) 1892 / NANOS_PER_MILLI; 1893 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 1894 return false; 1895 } 1896 1897 // Check whether sufficient distance has been traveled 1898 double minDistance = record.mRequest.getSmallestDisplacement(); 1899 if (minDistance > 0.0) { 1900 if (loc.distanceTo(lastLoc) <= minDistance) { 1901 return false; 1902 } 1903 } 1904 1905 // Check whether sufficient number of udpates is left 1906 if (record.mRequest.getNumUpdates() <= 0) { 1907 return false; 1908 } 1909 1910 // Check whether the expiry date has passed 1911 if (record.mRequest.getExpireAt() < now) { 1912 return false; 1913 } 1914 1915 return true; 1916 } 1917 1918 private void handleLocationChangedLocked(Location location, boolean passive) { 1919 if (D) Log.d(TAG, "incoming location: " + location); 1920 1921 long now = SystemClock.elapsedRealtime(); 1922 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 1923 1924 // Skip if the provider is unknown. 1925 LocationProviderInterface p = mProvidersByName.get(provider); 1926 if (p == null) return; 1927 1928 // Update last known locations 1929 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1930 Location lastNoGPSLocation = null; 1931 Location lastLocation = mLastLocation.get(provider); 1932 if (lastLocation == null) { 1933 lastLocation = new Location(provider); 1934 mLastLocation.put(provider, lastLocation); 1935 } else { 1936 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1937 if (noGPSLocation == null && lastNoGPSLocation != null) { 1938 // New location has no no-GPS location: adopt last no-GPS location. This is set 1939 // directly into location because we do not want to notify COARSE clients. 1940 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 1941 } 1942 } 1943 lastLocation.set(location); 1944 1945 // Update last known coarse interval location if enough time has passed. 1946 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider); 1947 if (lastLocationCoarseInterval == null) { 1948 lastLocationCoarseInterval = new Location(location); 1949 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval); 1950 } 1951 long timeDiffNanos = location.getElapsedRealtimeNanos() 1952 - lastLocationCoarseInterval.getElapsedRealtimeNanos(); 1953 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) { 1954 lastLocationCoarseInterval.set(location); 1955 } 1956 // Don't ever return a coarse location that is more recent than the allowed update 1957 // interval (i.e. don't allow an app to keep registering and unregistering for 1958 // location updates to overcome the minimum interval). 1959 noGPSLocation = 1960 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1961 1962 // Skip if there are no UpdateRecords for this provider. 1963 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1964 if (records == null || records.size() == 0) return; 1965 1966 // Fetch coarse location 1967 Location coarseLocation = null; 1968 if (noGPSLocation != null) { 1969 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 1970 } 1971 1972 // Fetch latest status update time 1973 long newStatusUpdateTime = p.getStatusUpdateTime(); 1974 1975 // Get latest status 1976 Bundle extras = new Bundle(); 1977 int status = p.getStatus(extras); 1978 1979 ArrayList<Receiver> deadReceivers = null; 1980 ArrayList<UpdateRecord> deadUpdateRecords = null; 1981 1982 // Broadcast location or status to all listeners 1983 for (UpdateRecord r : records) { 1984 Receiver receiver = r.mReceiver; 1985 boolean receiverDead = false; 1986 1987 int receiverUserId = UserHandle.getUserId(receiver.mUid); 1988 if (receiverUserId != mCurrentUserId && !isUidALocationProvider(receiver.mUid)) { 1989 if (D) { 1990 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 1991 " (current user: " + mCurrentUserId + ", app: " + 1992 receiver.mPackageName + ")"); 1993 } 1994 continue; 1995 } 1996 1997 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 1998 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 1999 receiver.mPackageName); 2000 continue; 2001 } 2002 2003 if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName, 2004 receiver.mAllowedResolutionLevel)) { 2005 if (D) Log.d(TAG, "skipping loc update for no op app: " + 2006 receiver.mPackageName); 2007 continue; 2008 } 2009 2010 Location notifyLocation = null; 2011 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2012 notifyLocation = coarseLocation; // use coarse location 2013 } else { 2014 notifyLocation = lastLocation; // use fine location 2015 } 2016 if (notifyLocation != null) { 2017 Location lastLoc = r.mLastFixBroadcast; 2018 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) { 2019 if (lastLoc == null) { 2020 lastLoc = new Location(notifyLocation); 2021 r.mLastFixBroadcast = lastLoc; 2022 } else { 2023 lastLoc.set(notifyLocation); 2024 } 2025 if (!receiver.callLocationChangedLocked(notifyLocation)) { 2026 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 2027 receiverDead = true; 2028 } 2029 r.mRequest.decrementNumUpdates(); 2030 } 2031 } 2032 2033 long prevStatusUpdateTime = r.mLastStatusBroadcast; 2034 if ((newStatusUpdateTime > prevStatusUpdateTime) && 2035 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 2036 2037 r.mLastStatusBroadcast = newStatusUpdateTime; 2038 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 2039 receiverDead = true; 2040 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 2041 } 2042 } 2043 2044 // track expired records 2045 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) { 2046 if (deadUpdateRecords == null) { 2047 deadUpdateRecords = new ArrayList<UpdateRecord>(); 2048 } 2049 deadUpdateRecords.add(r); 2050 } 2051 // track dead receivers 2052 if (receiverDead) { 2053 if (deadReceivers == null) { 2054 deadReceivers = new ArrayList<Receiver>(); 2055 } 2056 if (!deadReceivers.contains(receiver)) { 2057 deadReceivers.add(receiver); 2058 } 2059 } 2060 } 2061 2062 // remove dead records and receivers outside the loop 2063 if (deadReceivers != null) { 2064 for (Receiver receiver : deadReceivers) { 2065 removeUpdatesLocked(receiver); 2066 } 2067 } 2068 if (deadUpdateRecords != null) { 2069 for (UpdateRecord r : deadUpdateRecords) { 2070 r.disposeLocked(true); 2071 } 2072 applyRequirementsLocked(provider); 2073 } 2074 } 2075 2076 private class LocationWorkerHandler extends Handler { 2077 public LocationWorkerHandler(Looper looper) { 2078 super(looper, null, true); 2079 } 2080 2081 @Override 2082 public void handleMessage(Message msg) { 2083 switch (msg.what) { 2084 case MSG_LOCATION_CHANGED: 2085 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 2086 break; 2087 } 2088 } 2089 } 2090 2091 private boolean isMockProvider(String provider) { 2092 synchronized (mLock) { 2093 return mMockProviders.containsKey(provider); 2094 } 2095 } 2096 2097 private void handleLocationChanged(Location location, boolean passive) { 2098 // create a working copy of the incoming Location so that the service can modify it without 2099 // disturbing the caller's copy 2100 Location myLocation = new Location(location); 2101 String provider = myLocation.getProvider(); 2102 2103 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this 2104 // bit if location did not come from a mock provider because passive/fused providers can 2105 // forward locations from mock providers, and should not grant them legitimacy in doing so. 2106 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) { 2107 myLocation.setIsFromMockProvider(true); 2108 } 2109 2110 synchronized (mLock) { 2111 if (isAllowedByCurrentUserSettingsLocked(provider)) { 2112 if (!passive) { 2113 // notify passive provider of the new location 2114 mPassiveProvider.updateLocation(myLocation); 2115 } 2116 handleLocationChangedLocked(myLocation, passive); 2117 } 2118 } 2119 } 2120 2121 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 2122 @Override 2123 public void onPackageDisappeared(String packageName, int reason) { 2124 // remove all receivers associated with this package name 2125 synchronized (mLock) { 2126 ArrayList<Receiver> deadReceivers = null; 2127 2128 for (Receiver receiver : mReceivers.values()) { 2129 if (receiver.mPackageName.equals(packageName)) { 2130 if (deadReceivers == null) { 2131 deadReceivers = new ArrayList<Receiver>(); 2132 } 2133 deadReceivers.add(receiver); 2134 } 2135 } 2136 2137 // perform removal outside of mReceivers loop 2138 if (deadReceivers != null) { 2139 for (Receiver receiver : deadReceivers) { 2140 removeUpdatesLocked(receiver); 2141 } 2142 } 2143 } 2144 } 2145 }; 2146 2147 // Geocoder 2148 2149 @Override 2150 public boolean geocoderIsPresent() { 2151 return mGeocodeProvider != null; 2152 } 2153 2154 @Override 2155 public String getFromLocation(double latitude, double longitude, int maxResults, 2156 GeocoderParams params, List<Address> addrs) { 2157 if (mGeocodeProvider != null) { 2158 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 2159 params, addrs); 2160 } 2161 return null; 2162 } 2163 2164 2165 @Override 2166 public String getFromLocationName(String locationName, 2167 double lowerLeftLatitude, double lowerLeftLongitude, 2168 double upperRightLatitude, double upperRightLongitude, int maxResults, 2169 GeocoderParams params, List<Address> addrs) { 2170 2171 if (mGeocodeProvider != null) { 2172 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 2173 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 2174 maxResults, params, addrs); 2175 } 2176 return null; 2177 } 2178 2179 // Mock Providers 2180 2181 private void checkMockPermissionsSafe() { 2182 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 2183 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 2184 if (!allowMocks) { 2185 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 2186 } 2187 2188 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 2189 PackageManager.PERMISSION_GRANTED) { 2190 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 2191 } 2192 } 2193 2194 @Override 2195 public void addTestProvider(String name, ProviderProperties properties) { 2196 checkMockPermissionsSafe(); 2197 2198 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 2199 throw new IllegalArgumentException("Cannot mock the passive location provider"); 2200 } 2201 2202 long identity = Binder.clearCallingIdentity(); 2203 synchronized (mLock) { 2204 MockProvider provider = new MockProvider(name, this, properties); 2205 // remove the real provider if we are replacing GPS or network provider 2206 if (LocationManager.GPS_PROVIDER.equals(name) 2207 || LocationManager.NETWORK_PROVIDER.equals(name) 2208 || LocationManager.FUSED_PROVIDER.equals(name)) { 2209 LocationProviderInterface p = mProvidersByName.get(name); 2210 if (p != null) { 2211 removeProviderLocked(p); 2212 } 2213 } 2214 if (mProvidersByName.get(name) != null) { 2215 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 2216 } 2217 addProviderLocked(provider); 2218 mMockProviders.put(name, provider); 2219 mLastLocation.put(name, null); 2220 mLastLocationCoarseInterval.put(name, null); 2221 updateProvidersLocked(); 2222 } 2223 Binder.restoreCallingIdentity(identity); 2224 } 2225 2226 @Override 2227 public void removeTestProvider(String provider) { 2228 checkMockPermissionsSafe(); 2229 synchronized (mLock) { 2230 2231 // These methods can't be called after removing the test provider, so first make sure 2232 // we don't leave anything dangling (cf b/11446702). 2233 clearTestProviderEnabled(provider); 2234 clearTestProviderLocation(provider); 2235 clearTestProviderStatus(provider); 2236 2237 MockProvider mockProvider = mMockProviders.remove(provider); 2238 if (mockProvider == null) { 2239 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2240 } 2241 long identity = Binder.clearCallingIdentity(); 2242 removeProviderLocked(mProvidersByName.get(provider)); 2243 2244 // reinstate real provider if available 2245 LocationProviderInterface realProvider = mRealProviders.get(provider); 2246 if (realProvider != null) { 2247 addProviderLocked(realProvider); 2248 } 2249 mLastLocation.put(provider, null); 2250 mLastLocationCoarseInterval.put(provider, null); 2251 updateProvidersLocked(); 2252 Binder.restoreCallingIdentity(identity); 2253 } 2254 } 2255 2256 @Override 2257 public void setTestProviderLocation(String provider, Location loc) { 2258 checkMockPermissionsSafe(); 2259 synchronized (mLock) { 2260 MockProvider mockProvider = mMockProviders.get(provider); 2261 if (mockProvider == null) { 2262 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2263 } 2264 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 2265 long identity = Binder.clearCallingIdentity(); 2266 mockProvider.setLocation(loc); 2267 Binder.restoreCallingIdentity(identity); 2268 } 2269 } 2270 2271 @Override 2272 public void clearTestProviderLocation(String provider) { 2273 checkMockPermissionsSafe(); 2274 synchronized (mLock) { 2275 MockProvider mockProvider = mMockProviders.get(provider); 2276 if (mockProvider == null) { 2277 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2278 } 2279 mockProvider.clearLocation(); 2280 } 2281 } 2282 2283 @Override 2284 public void setTestProviderEnabled(String provider, boolean enabled) { 2285 checkMockPermissionsSafe(); 2286 synchronized (mLock) { 2287 MockProvider mockProvider = mMockProviders.get(provider); 2288 if (mockProvider == null) { 2289 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2290 } 2291 long identity = Binder.clearCallingIdentity(); 2292 if (enabled) { 2293 mockProvider.enable(); 2294 mEnabledProviders.add(provider); 2295 mDisabledProviders.remove(provider); 2296 } else { 2297 mockProvider.disable(); 2298 mEnabledProviders.remove(provider); 2299 mDisabledProviders.add(provider); 2300 } 2301 updateProvidersLocked(); 2302 Binder.restoreCallingIdentity(identity); 2303 } 2304 } 2305 2306 @Override 2307 public void clearTestProviderEnabled(String provider) { 2308 checkMockPermissionsSafe(); 2309 synchronized (mLock) { 2310 MockProvider mockProvider = mMockProviders.get(provider); 2311 if (mockProvider == null) { 2312 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2313 } 2314 long identity = Binder.clearCallingIdentity(); 2315 mEnabledProviders.remove(provider); 2316 mDisabledProviders.remove(provider); 2317 updateProvidersLocked(); 2318 Binder.restoreCallingIdentity(identity); 2319 } 2320 } 2321 2322 @Override 2323 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 2324 checkMockPermissionsSafe(); 2325 synchronized (mLock) { 2326 MockProvider mockProvider = mMockProviders.get(provider); 2327 if (mockProvider == null) { 2328 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2329 } 2330 mockProvider.setStatus(status, extras, updateTime); 2331 } 2332 } 2333 2334 @Override 2335 public void clearTestProviderStatus(String provider) { 2336 checkMockPermissionsSafe(); 2337 synchronized (mLock) { 2338 MockProvider mockProvider = mMockProviders.get(provider); 2339 if (mockProvider == null) { 2340 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2341 } 2342 mockProvider.clearStatus(); 2343 } 2344 } 2345 2346 private void log(String log) { 2347 if (Log.isLoggable(TAG, Log.VERBOSE)) { 2348 Slog.d(TAG, log); 2349 } 2350 } 2351 2352 @Override 2353 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2354 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2355 != PackageManager.PERMISSION_GRANTED) { 2356 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2357 + Binder.getCallingPid() 2358 + ", uid=" + Binder.getCallingUid()); 2359 return; 2360 } 2361 2362 synchronized (mLock) { 2363 pw.println("Current Location Manager state:"); 2364 pw.println(" Location Listeners:"); 2365 for (Receiver receiver : mReceivers.values()) { 2366 pw.println(" " + receiver); 2367 } 2368 pw.println(" Active Records by Provider:"); 2369 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2370 pw.println(" " + entry.getKey() + ":"); 2371 for (UpdateRecord record : entry.getValue()) { 2372 pw.println(" " + record); 2373 } 2374 } 2375 pw.println(" Historical Records by Provider:"); 2376 for (Map.Entry<PackageProviderKey, PackageStatistics> entry 2377 : mRequestStatistics.statistics.entrySet()) { 2378 PackageProviderKey key = entry.getKey(); 2379 PackageStatistics stats = entry.getValue(); 2380 pw.println(" " + key.packageName + ": " + key.providerName + ": " + stats); 2381 } 2382 pw.println(" Last Known Locations:"); 2383 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2384 String provider = entry.getKey(); 2385 Location location = entry.getValue(); 2386 pw.println(" " + provider + ": " + location); 2387 } 2388 2389 pw.println(" Last Known Locations Coarse Intervals:"); 2390 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) { 2391 String provider = entry.getKey(); 2392 Location location = entry.getValue(); 2393 pw.println(" " + provider + ": " + location); 2394 } 2395 2396 mGeofenceManager.dump(pw); 2397 2398 if (mEnabledProviders.size() > 0) { 2399 pw.println(" Enabled Providers:"); 2400 for (String i : mEnabledProviders) { 2401 pw.println(" " + i); 2402 } 2403 2404 } 2405 if (mDisabledProviders.size() > 0) { 2406 pw.println(" Disabled Providers:"); 2407 for (String i : mDisabledProviders) { 2408 pw.println(" " + i); 2409 } 2410 } 2411 pw.append(" "); 2412 mBlacklist.dump(pw); 2413 if (mMockProviders.size() > 0) { 2414 pw.println(" Mock Providers:"); 2415 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2416 i.getValue().dump(pw, " "); 2417 } 2418 } 2419 2420 pw.append(" fudger: "); 2421 mLocationFudger.dump(fd, pw, args); 2422 2423 if (args.length > 0 && "short".equals(args[0])) { 2424 return; 2425 } 2426 for (LocationProviderInterface provider: mProviders) { 2427 pw.print(provider.getName() + " Internal State"); 2428 if (provider instanceof LocationProviderProxy) { 2429 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2430 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2431 } 2432 pw.println(":"); 2433 provider.dump(fd, pw, args); 2434 } 2435 } 2436 } 2437} 2438