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