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