1/* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server; 18 19import android.app.AppOpsManager; 20import android.app.PendingIntent; 21import android.content.BroadcastReceiver; 22import android.content.ContentResolver; 23import android.content.Context; 24import android.content.Intent; 25import android.content.IntentFilter; 26import android.content.pm.ApplicationInfo; 27import android.content.pm.PackageInfo; 28import android.content.pm.PackageManager; 29import android.content.pm.PackageManager.NameNotFoundException; 30import android.content.pm.ResolveInfo; 31import android.content.pm.Signature; 32import android.content.res.Resources; 33import android.database.ContentObserver; 34import android.location.Address; 35import android.location.Criteria; 36import android.location.GeocoderParams; 37import android.location.Geofence; 38import android.location.IGpsStatusListener; 39import android.location.IGpsStatusProvider; 40import android.location.ILocationListener; 41import android.location.ILocationManager; 42import android.location.INetInitiatedListener; 43import android.location.Location; 44import android.location.LocationManager; 45import android.location.LocationProvider; 46import android.location.LocationRequest; 47import android.os.Binder; 48import android.os.Bundle; 49import android.os.Handler; 50import android.os.IBinder; 51import android.os.Looper; 52import android.os.Message; 53import android.os.PowerManager; 54import android.os.Process; 55import android.os.RemoteException; 56import android.os.SystemClock; 57import android.os.UserHandle; 58import android.os.WorkSource; 59import android.provider.Settings; 60import android.util.Log; 61import android.util.Slog; 62import com.android.internal.content.PackageMonitor; 63import com.android.internal.location.ProviderProperties; 64import com.android.internal.location.ProviderRequest; 65import com.android.internal.os.BackgroundThread; 66import com.android.server.location.FlpHardwareProvider; 67import com.android.server.location.FusedProxy; 68import com.android.server.location.GeocoderProxy; 69import com.android.server.location.GeofenceProxy; 70import com.android.server.location.GeofenceManager; 71import com.android.server.location.GpsLocationProvider; 72import com.android.server.location.LocationBlacklist; 73import com.android.server.location.LocationFudger; 74import com.android.server.location.LocationProviderInterface; 75import com.android.server.location.LocationProviderProxy; 76import com.android.server.location.MockProvider; 77import com.android.server.location.PassiveProvider; 78 79import java.io.FileDescriptor; 80import java.io.PrintWriter; 81import java.util.ArrayList; 82import java.util.Arrays; 83import java.util.HashMap; 84import java.util.HashSet; 85import java.util.List; 86import java.util.Map; 87import java.util.Set; 88 89/** 90 * The service class that manages LocationProviders and issues location 91 * updates and alerts. 92 */ 93public class LocationManagerService extends ILocationManager.Stub { 94 private static final String TAG = "LocationManagerService"; 95 public static final boolean D = Log.isLoggable(TAG, Log.DEBUG); 96 97 private static final String WAKELOCK_KEY = TAG; 98 99 // Location resolution level: no location data whatsoever 100 private static final int RESOLUTION_LEVEL_NONE = 0; 101 // Location resolution level: coarse location data only 102 private static final int RESOLUTION_LEVEL_COARSE = 1; 103 // Location resolution level: fine location data 104 private static final int RESOLUTION_LEVEL_FINE = 2; 105 106 private static final String ACCESS_MOCK_LOCATION = 107 android.Manifest.permission.ACCESS_MOCK_LOCATION; 108 private static final String ACCESS_LOCATION_EXTRA_COMMANDS = 109 android.Manifest.permission.ACCESS_LOCATION_EXTRA_COMMANDS; 110 private static final String INSTALL_LOCATION_PROVIDER = 111 android.Manifest.permission.INSTALL_LOCATION_PROVIDER; 112 113 private static final String NETWORK_LOCATION_SERVICE_ACTION = 114 "com.android.location.service.v3.NetworkLocationProvider"; 115 private static final String FUSED_LOCATION_SERVICE_ACTION = 116 "com.android.location.service.FusedLocationProvider"; 117 118 private static final int MSG_LOCATION_CHANGED = 1; 119 120 private static final long NANOS_PER_MILLI = 1000000L; 121 122 // The maximum interval a location request can have and still be considered "high power". 123 private static final long HIGH_POWER_INTERVAL_MS = 5 * 60 * 1000; 124 125 // Location Providers may sometimes deliver location updates 126 // slightly faster that requested - provide grace period so 127 // we don't unnecessarily filter events that are otherwise on 128 // time 129 private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100; 130 131 private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest(); 132 133 private final Context mContext; 134 private final AppOpsManager mAppOps; 135 136 // used internally for synchronization 137 private final Object mLock = new Object(); 138 139 // --- fields below are final after systemReady() --- 140 private LocationFudger mLocationFudger; 141 private GeofenceManager mGeofenceManager; 142 private PackageManager mPackageManager; 143 private PowerManager mPowerManager; 144 private GeocoderProxy mGeocodeProvider; 145 private IGpsStatusProvider mGpsStatusProvider; 146 private INetInitiatedListener mNetInitiatedListener; 147 private LocationWorkerHandler mLocationHandler; 148 private PassiveProvider mPassiveProvider; // track passive provider for special cases 149 private LocationBlacklist mBlacklist; 150 151 // --- fields below are protected by mLock --- 152 // Set of providers that are explicitly enabled 153 private final Set<String> mEnabledProviders = new HashSet<String>(); 154 155 // Set of providers that are explicitly disabled 156 private final Set<String> mDisabledProviders = new HashSet<String>(); 157 158 // Mock (test) providers 159 private final HashMap<String, MockProvider> mMockProviders = 160 new HashMap<String, MockProvider>(); 161 162 // all receivers 163 private final HashMap<Object, Receiver> mReceivers = new HashMap<Object, Receiver>(); 164 165 // currently installed providers (with mocks replacing real providers) 166 private final ArrayList<LocationProviderInterface> mProviders = 167 new ArrayList<LocationProviderInterface>(); 168 169 // real providers, saved here when mocked out 170 private final HashMap<String, LocationProviderInterface> mRealProviders = 171 new HashMap<String, LocationProviderInterface>(); 172 173 // mapping from provider name to provider 174 private final HashMap<String, LocationProviderInterface> mProvidersByName = 175 new HashMap<String, LocationProviderInterface>(); 176 177 // mapping from provider name to all its UpdateRecords 178 private final HashMap<String, ArrayList<UpdateRecord>> mRecordsByProvider = 179 new HashMap<String, ArrayList<UpdateRecord>>(); 180 181 // mapping from provider name to last known location 182 private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>(); 183 184 // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS. 185 // locations stored here are not fudged for coarse permissions. 186 private final HashMap<String, Location> mLastLocationCoarseInterval = 187 new HashMap<String, Location>(); 188 189 // all providers that operate over proxy, for authorizing incoming location 190 private final ArrayList<LocationProviderProxy> mProxyProviders = 191 new ArrayList<LocationProviderProxy>(); 192 193 // current active user on the device - other users are denied location data 194 private int mCurrentUserId = UserHandle.USER_OWNER; 195 196 public LocationManagerService(Context context) { 197 super(); 198 mContext = context; 199 mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 200 201 if (D) Log.d(TAG, "Constructed"); 202 203 // most startup is deferred until systemReady() 204 } 205 206 public void systemRunning() { 207 synchronized (mLock) { 208 if (D) Log.d(TAG, "systemReady()"); 209 210 // fetch package manager 211 mPackageManager = mContext.getPackageManager(); 212 213 // fetch power manager 214 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 215 216 // prepare worker thread 217 mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper()); 218 219 // prepare mLocationHandler's dependents 220 mLocationFudger = new LocationFudger(mContext, mLocationHandler); 221 mBlacklist = new LocationBlacklist(mContext, mLocationHandler); 222 mBlacklist.init(); 223 mGeofenceManager = new GeofenceManager(mContext, mBlacklist); 224 225 // Monitor for app ops mode changes. 226 AppOpsManager.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 changesMade = true; 1152 } else if (!isEnabled && shouldBeEnabled) { 1153 updateProviderListenersLocked(name, true, mCurrentUserId); 1154 changesMade = true; 1155 } 1156 } 1157 if (changesMade) { 1158 mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION), 1159 UserHandle.ALL); 1160 mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION), 1161 UserHandle.ALL); 1162 } 1163 } 1164 1165 private void updateProviderListenersLocked(String provider, boolean enabled, int userId) { 1166 int listeners = 0; 1167 1168 LocationProviderInterface p = mProvidersByName.get(provider); 1169 if (p == null) return; 1170 1171 ArrayList<Receiver> deadReceivers = null; 1172 1173 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1174 if (records != null) { 1175 final int N = records.size(); 1176 for (int i = 0; i < N; i++) { 1177 UpdateRecord record = records.get(i); 1178 if (UserHandle.getUserId(record.mReceiver.mUid) == userId) { 1179 // Sends a notification message to the receiver 1180 if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { 1181 if (deadReceivers == null) { 1182 deadReceivers = new ArrayList<Receiver>(); 1183 } 1184 deadReceivers.add(record.mReceiver); 1185 } 1186 listeners++; 1187 } 1188 } 1189 } 1190 1191 if (deadReceivers != null) { 1192 for (int i = deadReceivers.size() - 1; i >= 0; i--) { 1193 removeUpdatesLocked(deadReceivers.get(i)); 1194 } 1195 } 1196 1197 if (enabled) { 1198 p.enable(); 1199 if (listeners > 0) { 1200 applyRequirementsLocked(provider); 1201 } 1202 } else { 1203 p.disable(); 1204 } 1205 } 1206 1207 private void applyRequirementsLocked(String provider) { 1208 LocationProviderInterface p = mProvidersByName.get(provider); 1209 if (p == null) return; 1210 1211 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1212 WorkSource worksource = new WorkSource(); 1213 ProviderRequest providerRequest = new ProviderRequest(); 1214 1215 if (records != null) { 1216 for (UpdateRecord record : records) { 1217 if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { 1218 if (checkLocationAccess(record.mReceiver.mUid, record.mReceiver.mPackageName, 1219 record.mReceiver.mAllowedResolutionLevel)) { 1220 LocationRequest locationRequest = record.mRequest; 1221 providerRequest.locationRequests.add(locationRequest); 1222 if (locationRequest.getInterval() < providerRequest.interval) { 1223 providerRequest.reportLocation = true; 1224 providerRequest.interval = locationRequest.getInterval(); 1225 } 1226 } 1227 } 1228 } 1229 1230 if (providerRequest.reportLocation) { 1231 // calculate who to blame for power 1232 // This is somewhat arbitrary. We pick a threshold interval 1233 // that is slightly higher that the minimum interval, and 1234 // spread the blame across all applications with a request 1235 // under that threshold. 1236 long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; 1237 for (UpdateRecord record : records) { 1238 if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { 1239 LocationRequest locationRequest = record.mRequest; 1240 if (locationRequest.getInterval() <= thresholdInterval) { 1241 if (record.mReceiver.mWorkSource != null 1242 && record.mReceiver.mWorkSource.size() > 0 1243 && record.mReceiver.mWorkSource.getName(0) != null) { 1244 // Assign blame to another work source. 1245 // Can only assign blame if the WorkSource contains names. 1246 worksource.add(record.mReceiver.mWorkSource); 1247 } else { 1248 // Assign blame to caller. 1249 worksource.add( 1250 record.mReceiver.mUid, 1251 record.mReceiver.mPackageName); 1252 } 1253 } 1254 } 1255 } 1256 } 1257 } 1258 1259 if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); 1260 p.setRequest(providerRequest, worksource); 1261 } 1262 1263 private class UpdateRecord { 1264 final String mProvider; 1265 final LocationRequest mRequest; 1266 final Receiver mReceiver; 1267 Location mLastFixBroadcast; 1268 long mLastStatusBroadcast; 1269 1270 /** 1271 * Note: must be constructed with lock held. 1272 */ 1273 UpdateRecord(String provider, LocationRequest request, Receiver receiver) { 1274 mProvider = provider; 1275 mRequest = request; 1276 mReceiver = receiver; 1277 1278 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1279 if (records == null) { 1280 records = new ArrayList<UpdateRecord>(); 1281 mRecordsByProvider.put(provider, records); 1282 } 1283 if (!records.contains(this)) { 1284 records.add(this); 1285 } 1286 } 1287 1288 /** 1289 * Method to be called when a record will no longer be used. Calling this multiple times 1290 * must have the same effect as calling it once. 1291 */ 1292 void disposeLocked(boolean removeReceiver) { 1293 // remove from mRecordsByProvider 1294 ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider); 1295 if (globalRecords != null) { 1296 globalRecords.remove(this); 1297 } 1298 1299 if (!removeReceiver) return; // the caller will handle the rest 1300 1301 // remove from Receiver#mUpdateRecords 1302 HashMap<String, UpdateRecord> receiverRecords = mReceiver.mUpdateRecords; 1303 if (receiverRecords != null) { 1304 receiverRecords.remove(this.mProvider); 1305 1306 // and also remove the Receiver if it has no more update records 1307 if (removeReceiver && receiverRecords.size() == 0) { 1308 removeUpdatesLocked(mReceiver); 1309 } 1310 } 1311 } 1312 1313 @Override 1314 public String toString() { 1315 StringBuilder s = new StringBuilder(); 1316 s.append("UpdateRecord["); 1317 s.append(mProvider); 1318 s.append(' ').append(mReceiver.mPackageName).append('('); 1319 s.append(mReceiver.mUid).append(')'); 1320 s.append(' ').append(mRequest); 1321 s.append(']'); 1322 return s.toString(); 1323 } 1324 } 1325 1326 private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid, 1327 String packageName, WorkSource workSource, boolean hideFromAppOps) { 1328 IBinder binder = listener.asBinder(); 1329 Receiver receiver = mReceivers.get(binder); 1330 if (receiver == null) { 1331 receiver = new Receiver(listener, null, pid, uid, packageName, workSource, 1332 hideFromAppOps); 1333 mReceivers.put(binder, receiver); 1334 1335 try { 1336 receiver.getListener().asBinder().linkToDeath(receiver, 0); 1337 } catch (RemoteException e) { 1338 Slog.e(TAG, "linkToDeath failed:", e); 1339 return null; 1340 } 1341 } 1342 return receiver; 1343 } 1344 1345 private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName, 1346 WorkSource workSource, boolean hideFromAppOps) { 1347 Receiver receiver = mReceivers.get(intent); 1348 if (receiver == null) { 1349 receiver = new Receiver(null, intent, pid, uid, packageName, workSource, 1350 hideFromAppOps); 1351 mReceivers.put(intent, receiver); 1352 } 1353 return receiver; 1354 } 1355 1356 /** 1357 * Creates a LocationRequest based upon the supplied LocationRequest that to meets resolution 1358 * and consistency requirements. 1359 * 1360 * @param request the LocationRequest from which to create a sanitized version 1361 * @return a version of request that meets the given resolution and consistency requirements 1362 * @hide 1363 */ 1364 private LocationRequest createSanitizedRequest(LocationRequest request, int resolutionLevel) { 1365 LocationRequest sanitizedRequest = new LocationRequest(request); 1366 if (resolutionLevel < RESOLUTION_LEVEL_FINE) { 1367 switch (sanitizedRequest.getQuality()) { 1368 case LocationRequest.ACCURACY_FINE: 1369 sanitizedRequest.setQuality(LocationRequest.ACCURACY_BLOCK); 1370 break; 1371 case LocationRequest.POWER_HIGH: 1372 sanitizedRequest.setQuality(LocationRequest.POWER_LOW); 1373 break; 1374 } 1375 // throttle 1376 if (sanitizedRequest.getInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1377 sanitizedRequest.setInterval(LocationFudger.FASTEST_INTERVAL_MS); 1378 } 1379 if (sanitizedRequest.getFastestInterval() < LocationFudger.FASTEST_INTERVAL_MS) { 1380 sanitizedRequest.setFastestInterval(LocationFudger.FASTEST_INTERVAL_MS); 1381 } 1382 } 1383 // make getFastestInterval() the minimum of interval and fastest interval 1384 if (sanitizedRequest.getFastestInterval() > sanitizedRequest.getInterval()) { 1385 request.setFastestInterval(request.getInterval()); 1386 } 1387 return sanitizedRequest; 1388 } 1389 1390 private void checkPackageName(String packageName) { 1391 if (packageName == null) { 1392 throw new SecurityException("invalid package name: " + packageName); 1393 } 1394 int uid = Binder.getCallingUid(); 1395 String[] packages = mPackageManager.getPackagesForUid(uid); 1396 if (packages == null) { 1397 throw new SecurityException("invalid UID " + uid); 1398 } 1399 for (String pkg : packages) { 1400 if (packageName.equals(pkg)) return; 1401 } 1402 throw new SecurityException("invalid package name: " + packageName); 1403 } 1404 1405 private void checkPendingIntent(PendingIntent intent) { 1406 if (intent == null) { 1407 throw new IllegalArgumentException("invalid pending intent: " + intent); 1408 } 1409 } 1410 1411 private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent, 1412 int pid, int uid, String packageName, WorkSource workSource, boolean hideFromAppOps) { 1413 if (intent == null && listener == null) { 1414 throw new IllegalArgumentException("need either listener or intent"); 1415 } else if (intent != null && listener != null) { 1416 throw new IllegalArgumentException("cannot register both listener and intent"); 1417 } else if (intent != null) { 1418 checkPendingIntent(intent); 1419 return getReceiverLocked(intent, pid, uid, packageName, workSource, hideFromAppOps); 1420 } else { 1421 return getReceiverLocked(listener, pid, uid, packageName, workSource, hideFromAppOps); 1422 } 1423 } 1424 1425 @Override 1426 public void requestLocationUpdates(LocationRequest request, ILocationListener listener, 1427 PendingIntent intent, String packageName) { 1428 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1429 checkPackageName(packageName); 1430 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1431 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1432 request.getProvider()); 1433 WorkSource workSource = request.getWorkSource(); 1434 if (workSource != null && workSource.size() > 0) { 1435 checkDeviceStatsAllowed(); 1436 } 1437 boolean hideFromAppOps = request.getHideFromAppOps(); 1438 if (hideFromAppOps) { 1439 checkUpdateAppOpsAllowed(); 1440 } 1441 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1442 1443 final int pid = Binder.getCallingPid(); 1444 final int uid = Binder.getCallingUid(); 1445 // providers may use public location API's, need to clear identity 1446 long identity = Binder.clearCallingIdentity(); 1447 try { 1448 // We don't check for MODE_IGNORED here; we will do that when we go to deliver 1449 // a location. 1450 checkLocationAccess(uid, packageName, allowedResolutionLevel); 1451 1452 synchronized (mLock) { 1453 Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid, 1454 packageName, workSource, hideFromAppOps); 1455 requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName); 1456 } 1457 } finally { 1458 Binder.restoreCallingIdentity(identity); 1459 } 1460 } 1461 1462 private void requestLocationUpdatesLocked(LocationRequest request, Receiver receiver, 1463 int pid, int uid, String packageName) { 1464 // Figure out the provider. Either its explicitly request (legacy use cases), or 1465 // use the fused provider 1466 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1467 String name = request.getProvider(); 1468 if (name == null) { 1469 throw new IllegalArgumentException("provider name must not be null"); 1470 } 1471 1472 if (D) Log.d(TAG, "request " + Integer.toHexString(System.identityHashCode(receiver)) 1473 + " " + name + " " + request + " from " + packageName + "(" + uid + ")"); 1474 LocationProviderInterface provider = mProvidersByName.get(name); 1475 if (provider == null) { 1476 throw new IllegalArgumentException("provider doesn't exist: " + name); 1477 } 1478 1479 UpdateRecord record = new UpdateRecord(name, request, receiver); 1480 UpdateRecord oldRecord = receiver.mUpdateRecords.put(name, record); 1481 if (oldRecord != null) { 1482 oldRecord.disposeLocked(false); 1483 } 1484 1485 boolean isProviderEnabled = isAllowedByUserSettingsLocked(name, uid); 1486 if (isProviderEnabled) { 1487 applyRequirementsLocked(name); 1488 } else { 1489 // Notify the listener that updates are currently disabled 1490 receiver.callProviderEnabledLocked(name, false); 1491 } 1492 // Update the monitoring here just in case multiple location requests were added to the 1493 // same receiver (this request may be high power and the initial might not have been). 1494 receiver.updateMonitoring(true); 1495 } 1496 1497 @Override 1498 public void removeUpdates(ILocationListener listener, PendingIntent intent, 1499 String packageName) { 1500 checkPackageName(packageName); 1501 1502 final int pid = Binder.getCallingPid(); 1503 final int uid = Binder.getCallingUid(); 1504 1505 synchronized (mLock) { 1506 WorkSource workSource = null; 1507 boolean hideFromAppOps = false; 1508 Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid, 1509 packageName, workSource, hideFromAppOps); 1510 1511 // providers may use public location API's, need to clear identity 1512 long identity = Binder.clearCallingIdentity(); 1513 try { 1514 removeUpdatesLocked(receiver); 1515 } finally { 1516 Binder.restoreCallingIdentity(identity); 1517 } 1518 } 1519 } 1520 1521 private void removeUpdatesLocked(Receiver receiver) { 1522 if (D) Log.i(TAG, "remove " + Integer.toHexString(System.identityHashCode(receiver))); 1523 1524 if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) { 1525 receiver.getListener().asBinder().unlinkToDeath(receiver, 0); 1526 synchronized (receiver) { 1527 receiver.clearPendingBroadcastsLocked(); 1528 } 1529 } 1530 1531 receiver.updateMonitoring(false); 1532 1533 // Record which providers were associated with this listener 1534 HashSet<String> providers = new HashSet<String>(); 1535 HashMap<String, UpdateRecord> oldRecords = receiver.mUpdateRecords; 1536 if (oldRecords != null) { 1537 // Call dispose() on the obsolete update records. 1538 for (UpdateRecord record : oldRecords.values()) { 1539 record.disposeLocked(false); 1540 } 1541 // Accumulate providers 1542 providers.addAll(oldRecords.keySet()); 1543 } 1544 1545 // update provider 1546 for (String provider : providers) { 1547 // If provider is already disabled, don't need to do anything 1548 if (!isAllowedByCurrentUserSettingsLocked(provider)) { 1549 continue; 1550 } 1551 1552 applyRequirementsLocked(provider); 1553 } 1554 } 1555 1556 private void applyAllProviderRequirementsLocked() { 1557 for (LocationProviderInterface p : mProviders) { 1558 // If provider is already disabled, don't need to do anything 1559 if (!isAllowedByCurrentUserSettingsLocked(p.getName())) { 1560 continue; 1561 } 1562 1563 applyRequirementsLocked(p.getName()); 1564 } 1565 } 1566 1567 @Override 1568 public Location getLastLocation(LocationRequest request, String packageName) { 1569 if (D) Log.d(TAG, "getLastLocation: " + request); 1570 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1571 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1572 checkPackageName(packageName); 1573 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1574 request.getProvider()); 1575 // no need to sanitize this request, as only the provider name is used 1576 1577 final int uid = Binder.getCallingUid(); 1578 final long identity = Binder.clearCallingIdentity(); 1579 try { 1580 if (mBlacklist.isBlacklisted(packageName)) { 1581 if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + 1582 packageName); 1583 return null; 1584 } 1585 1586 if (!reportLocationAccessNoThrow(uid, packageName, allowedResolutionLevel)) { 1587 if (D) Log.d(TAG, "not returning last loc for no op app: " + 1588 packageName); 1589 return null; 1590 } 1591 1592 synchronized (mLock) { 1593 // Figure out the provider. Either its explicitly request (deprecated API's), 1594 // or use the fused provider 1595 String name = request.getProvider(); 1596 if (name == null) name = LocationManager.FUSED_PROVIDER; 1597 LocationProviderInterface provider = mProvidersByName.get(name); 1598 if (provider == null) return null; 1599 1600 if (!isAllowedByUserSettingsLocked(name, uid)) return null; 1601 1602 Location location; 1603 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1604 // Make sure that an app with coarse permissions can't get frequent location 1605 // updates by calling LocationManager.getLastKnownLocation repeatedly. 1606 location = mLastLocationCoarseInterval.get(name); 1607 } else { 1608 location = mLastLocation.get(name); 1609 } 1610 if (location == null) { 1611 return null; 1612 } 1613 if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 1614 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1615 if (noGPSLocation != null) { 1616 return new Location(mLocationFudger.getOrCreate(noGPSLocation)); 1617 } 1618 } else { 1619 return new Location(location); 1620 } 1621 } 1622 return null; 1623 } finally { 1624 Binder.restoreCallingIdentity(identity); 1625 } 1626 } 1627 1628 @Override 1629 public void requestGeofence(LocationRequest request, Geofence geofence, PendingIntent intent, 1630 String packageName) { 1631 if (request == null) request = DEFAULT_LOCATION_REQUEST; 1632 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1633 checkResolutionLevelIsSufficientForGeofenceUse(allowedResolutionLevel); 1634 checkPendingIntent(intent); 1635 checkPackageName(packageName); 1636 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1637 request.getProvider()); 1638 LocationRequest sanitizedRequest = createSanitizedRequest(request, allowedResolutionLevel); 1639 1640 if (D) Log.d(TAG, "requestGeofence: " + sanitizedRequest + " " + geofence + " " + intent); 1641 1642 // geo-fence manager uses the public location API, need to clear identity 1643 int uid = Binder.getCallingUid(); 1644 if (UserHandle.getUserId(uid) != UserHandle.USER_OWNER) { 1645 // temporary measure until geofences work for secondary users 1646 Log.w(TAG, "proximity alerts are currently available only to the primary user"); 1647 return; 1648 } 1649 long identity = Binder.clearCallingIdentity(); 1650 try { 1651 mGeofenceManager.addFence(sanitizedRequest, geofence, intent, allowedResolutionLevel, 1652 uid, packageName); 1653 } finally { 1654 Binder.restoreCallingIdentity(identity); 1655 } 1656 } 1657 1658 @Override 1659 public void removeGeofence(Geofence geofence, PendingIntent intent, String packageName) { 1660 checkResolutionLevelIsSufficientForGeofenceUse(getCallerAllowedResolutionLevel()); 1661 checkPendingIntent(intent); 1662 checkPackageName(packageName); 1663 1664 if (D) Log.d(TAG, "removeGeofence: " + geofence + " " + intent); 1665 1666 // geo-fence manager uses the public location API, need to clear identity 1667 long identity = Binder.clearCallingIdentity(); 1668 try { 1669 mGeofenceManager.removeFence(geofence, intent); 1670 } finally { 1671 Binder.restoreCallingIdentity(identity); 1672 } 1673 } 1674 1675 1676 @Override 1677 public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) { 1678 if (mGpsStatusProvider == null) { 1679 return false; 1680 } 1681 int allowedResolutionLevel = getCallerAllowedResolutionLevel(); 1682 checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel, 1683 LocationManager.GPS_PROVIDER); 1684 1685 final int uid = Binder.getCallingUid(); 1686 final long ident = Binder.clearCallingIdentity(); 1687 try { 1688 if (!checkLocationAccess(uid, packageName, allowedResolutionLevel)) { 1689 return false; 1690 } 1691 } finally { 1692 Binder.restoreCallingIdentity(ident); 1693 } 1694 1695 try { 1696 mGpsStatusProvider.addGpsStatusListener(listener); 1697 } catch (RemoteException e) { 1698 Slog.e(TAG, "mGpsStatusProvider.addGpsStatusListener failed", e); 1699 return false; 1700 } 1701 return true; 1702 } 1703 1704 @Override 1705 public void removeGpsStatusListener(IGpsStatusListener listener) { 1706 synchronized (mLock) { 1707 try { 1708 mGpsStatusProvider.removeGpsStatusListener(listener); 1709 } catch (Exception e) { 1710 Slog.e(TAG, "mGpsStatusProvider.removeGpsStatusListener failed", e); 1711 } 1712 } 1713 } 1714 1715 @Override 1716 public boolean sendExtraCommand(String provider, String command, Bundle extras) { 1717 if (provider == null) { 1718 // throw NullPointerException to remain compatible with previous implementation 1719 throw new NullPointerException(); 1720 } 1721 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1722 provider); 1723 1724 // and check for ACCESS_LOCATION_EXTRA_COMMANDS 1725 if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS) 1726 != PackageManager.PERMISSION_GRANTED)) { 1727 throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); 1728 } 1729 1730 synchronized (mLock) { 1731 LocationProviderInterface p = mProvidersByName.get(provider); 1732 if (p == null) return false; 1733 1734 return p.sendExtraCommand(command, extras); 1735 } 1736 } 1737 1738 @Override 1739 public boolean sendNiResponse(int notifId, int userResponse) { 1740 if (Binder.getCallingUid() != Process.myUid()) { 1741 throw new SecurityException( 1742 "calling sendNiResponse from outside of the system is not allowed"); 1743 } 1744 try { 1745 return mNetInitiatedListener.sendNiResponse(notifId, userResponse); 1746 } catch (RemoteException e) { 1747 Slog.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); 1748 return false; 1749 } 1750 } 1751 1752 /** 1753 * @return null if the provider does not exist 1754 * @throws SecurityException if the provider is not allowed to be 1755 * accessed by the caller 1756 */ 1757 @Override 1758 public ProviderProperties getProviderProperties(String provider) { 1759 if (mProvidersByName.get(provider) == null) { 1760 return null; 1761 } 1762 1763 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1764 provider); 1765 1766 LocationProviderInterface p; 1767 synchronized (mLock) { 1768 p = mProvidersByName.get(provider); 1769 } 1770 1771 if (p == null) return null; 1772 return p.getProperties(); 1773 } 1774 1775 @Override 1776 public boolean isProviderEnabled(String provider) { 1777 // TODO: remove this check in next release, see b/10696351 1778 checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(), 1779 provider); 1780 1781 // Fused provider is accessed indirectly via criteria rather than the provider-based APIs, 1782 // so we discourage its use 1783 if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; 1784 1785 int uid = Binder.getCallingUid(); 1786 long identity = Binder.clearCallingIdentity(); 1787 try { 1788 synchronized (mLock) { 1789 LocationProviderInterface p = mProvidersByName.get(provider); 1790 if (p == null) return false; 1791 1792 return isAllowedByUserSettingsLocked(provider, uid); 1793 } 1794 } finally { 1795 Binder.restoreCallingIdentity(identity); 1796 } 1797 } 1798 1799 /** 1800 * Returns "true" if the UID belongs to a bound location provider. 1801 * 1802 * @param uid the uid 1803 * @return true if uid belongs to a bound location provider 1804 */ 1805 private boolean isUidALocationProvider(int uid) { 1806 if (uid == Process.SYSTEM_UID) { 1807 return true; 1808 } 1809 if (mGeocodeProvider != null) { 1810 if (doesPackageHaveUid(uid, mGeocodeProvider.getConnectedPackageName())) return true; 1811 } 1812 for (LocationProviderProxy proxy : mProxyProviders) { 1813 if (doesPackageHaveUid(uid, proxy.getConnectedPackageName())) return true; 1814 } 1815 return false; 1816 } 1817 1818 private void checkCallerIsProvider() { 1819 if (mContext.checkCallingOrSelfPermission(INSTALL_LOCATION_PROVIDER) 1820 == PackageManager.PERMISSION_GRANTED) { 1821 return; 1822 } 1823 1824 // Previously we only used the INSTALL_LOCATION_PROVIDER 1825 // check. But that is system or signature 1826 // protection level which is not flexible enough for 1827 // providers installed oustide the system image. So 1828 // also allow providers with a UID matching the 1829 // currently bound package name 1830 1831 if (isUidALocationProvider(Binder.getCallingUid())) { 1832 return; 1833 } 1834 1835 throw new SecurityException("need INSTALL_LOCATION_PROVIDER permission, " + 1836 "or UID of a currently bound location provider"); 1837 } 1838 1839 private boolean doesPackageHaveUid(int uid, String packageName) { 1840 if (packageName == null) { 1841 return false; 1842 } 1843 try { 1844 ApplicationInfo appInfo = mPackageManager.getApplicationInfo(packageName, 0); 1845 if (appInfo.uid != uid) { 1846 return false; 1847 } 1848 } catch (NameNotFoundException e) { 1849 return false; 1850 } 1851 return true; 1852 } 1853 1854 @Override 1855 public void reportLocation(Location location, boolean passive) { 1856 checkCallerIsProvider(); 1857 1858 if (!location.isComplete()) { 1859 Log.w(TAG, "Dropping incomplete location: " + location); 1860 return; 1861 } 1862 1863 mLocationHandler.removeMessages(MSG_LOCATION_CHANGED, location); 1864 Message m = Message.obtain(mLocationHandler, MSG_LOCATION_CHANGED, location); 1865 m.arg1 = (passive ? 1 : 0); 1866 mLocationHandler.sendMessageAtFrontOfQueue(m); 1867 } 1868 1869 1870 private static boolean shouldBroadcastSafe( 1871 Location loc, Location lastLoc, UpdateRecord record, long now) { 1872 // Always broadcast the first update 1873 if (lastLoc == null) { 1874 return true; 1875 } 1876 1877 // Check whether sufficient time has passed 1878 long minTime = record.mRequest.getFastestInterval(); 1879 long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) 1880 / NANOS_PER_MILLI; 1881 if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) { 1882 return false; 1883 } 1884 1885 // Check whether sufficient distance has been traveled 1886 double minDistance = record.mRequest.getSmallestDisplacement(); 1887 if (minDistance > 0.0) { 1888 if (loc.distanceTo(lastLoc) <= minDistance) { 1889 return false; 1890 } 1891 } 1892 1893 // Check whether sufficient number of udpates is left 1894 if (record.mRequest.getNumUpdates() <= 0) { 1895 return false; 1896 } 1897 1898 // Check whether the expiry date has passed 1899 if (record.mRequest.getExpireAt() < now) { 1900 return false; 1901 } 1902 1903 return true; 1904 } 1905 1906 private void handleLocationChangedLocked(Location location, boolean passive) { 1907 if (D) Log.d(TAG, "incoming location: " + location); 1908 1909 long now = SystemClock.elapsedRealtime(); 1910 String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); 1911 1912 // Skip if the provider is unknown. 1913 LocationProviderInterface p = mProvidersByName.get(provider); 1914 if (p == null) return; 1915 1916 // Update last known locations 1917 Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1918 Location lastNoGPSLocation = null; 1919 Location lastLocation = mLastLocation.get(provider); 1920 if (lastLocation == null) { 1921 lastLocation = new Location(provider); 1922 mLastLocation.put(provider, lastLocation); 1923 } else { 1924 lastNoGPSLocation = lastLocation.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1925 if (noGPSLocation == null && lastNoGPSLocation != null) { 1926 // New location has no no-GPS location: adopt last no-GPS location. This is set 1927 // directly into location because we do not want to notify COARSE clients. 1928 location.setExtraLocation(Location.EXTRA_NO_GPS_LOCATION, lastNoGPSLocation); 1929 } 1930 } 1931 lastLocation.set(location); 1932 1933 // Update last known coarse interval location if enough time has passed. 1934 Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider); 1935 if (lastLocationCoarseInterval == null) { 1936 lastLocationCoarseInterval = new Location(location); 1937 mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval); 1938 } 1939 long timeDiffNanos = location.getElapsedRealtimeNanos() 1940 - lastLocationCoarseInterval.getElapsedRealtimeNanos(); 1941 if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) { 1942 lastLocationCoarseInterval.set(location); 1943 } 1944 // Don't ever return a coarse location that is more recent than the allowed update 1945 // interval (i.e. don't allow an app to keep registering and unregistering for 1946 // location updates to overcome the minimum interval). 1947 noGPSLocation = 1948 lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); 1949 1950 // Skip if there are no UpdateRecords for this provider. 1951 ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); 1952 if (records == null || records.size() == 0) return; 1953 1954 // Fetch coarse location 1955 Location coarseLocation = null; 1956 if (noGPSLocation != null) { 1957 coarseLocation = mLocationFudger.getOrCreate(noGPSLocation); 1958 } 1959 1960 // Fetch latest status update time 1961 long newStatusUpdateTime = p.getStatusUpdateTime(); 1962 1963 // Get latest status 1964 Bundle extras = new Bundle(); 1965 int status = p.getStatus(extras); 1966 1967 ArrayList<Receiver> deadReceivers = null; 1968 ArrayList<UpdateRecord> deadUpdateRecords = null; 1969 1970 // Broadcast location or status to all listeners 1971 for (UpdateRecord r : records) { 1972 Receiver receiver = r.mReceiver; 1973 boolean receiverDead = false; 1974 1975 int receiverUserId = UserHandle.getUserId(receiver.mUid); 1976 if (receiverUserId != mCurrentUserId && !isUidALocationProvider(receiver.mUid)) { 1977 if (D) { 1978 Log.d(TAG, "skipping loc update for background user " + receiverUserId + 1979 " (current user: " + mCurrentUserId + ", app: " + 1980 receiver.mPackageName + ")"); 1981 } 1982 continue; 1983 } 1984 1985 if (mBlacklist.isBlacklisted(receiver.mPackageName)) { 1986 if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + 1987 receiver.mPackageName); 1988 continue; 1989 } 1990 1991 if (!reportLocationAccessNoThrow(receiver.mUid, receiver.mPackageName, 1992 receiver.mAllowedResolutionLevel)) { 1993 if (D) Log.d(TAG, "skipping loc update for no op app: " + 1994 receiver.mPackageName); 1995 continue; 1996 } 1997 1998 Location notifyLocation = null; 1999 if (receiver.mAllowedResolutionLevel < RESOLUTION_LEVEL_FINE) { 2000 notifyLocation = coarseLocation; // use coarse location 2001 } else { 2002 notifyLocation = lastLocation; // use fine location 2003 } 2004 if (notifyLocation != null) { 2005 Location lastLoc = r.mLastFixBroadcast; 2006 if ((lastLoc == null) || shouldBroadcastSafe(notifyLocation, lastLoc, r, now)) { 2007 if (lastLoc == null) { 2008 lastLoc = new Location(notifyLocation); 2009 r.mLastFixBroadcast = lastLoc; 2010 } else { 2011 lastLoc.set(notifyLocation); 2012 } 2013 if (!receiver.callLocationChangedLocked(notifyLocation)) { 2014 Slog.w(TAG, "RemoteException calling onLocationChanged on " + receiver); 2015 receiverDead = true; 2016 } 2017 r.mRequest.decrementNumUpdates(); 2018 } 2019 } 2020 2021 long prevStatusUpdateTime = r.mLastStatusBroadcast; 2022 if ((newStatusUpdateTime > prevStatusUpdateTime) && 2023 (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { 2024 2025 r.mLastStatusBroadcast = newStatusUpdateTime; 2026 if (!receiver.callStatusChangedLocked(provider, status, extras)) { 2027 receiverDead = true; 2028 Slog.w(TAG, "RemoteException calling onStatusChanged on " + receiver); 2029 } 2030 } 2031 2032 // track expired records 2033 if (r.mRequest.getNumUpdates() <= 0 || r.mRequest.getExpireAt() < now) { 2034 if (deadUpdateRecords == null) { 2035 deadUpdateRecords = new ArrayList<UpdateRecord>(); 2036 } 2037 deadUpdateRecords.add(r); 2038 } 2039 // track dead receivers 2040 if (receiverDead) { 2041 if (deadReceivers == null) { 2042 deadReceivers = new ArrayList<Receiver>(); 2043 } 2044 if (!deadReceivers.contains(receiver)) { 2045 deadReceivers.add(receiver); 2046 } 2047 } 2048 } 2049 2050 // remove dead records and receivers outside the loop 2051 if (deadReceivers != null) { 2052 for (Receiver receiver : deadReceivers) { 2053 removeUpdatesLocked(receiver); 2054 } 2055 } 2056 if (deadUpdateRecords != null) { 2057 for (UpdateRecord r : deadUpdateRecords) { 2058 r.disposeLocked(true); 2059 } 2060 applyRequirementsLocked(provider); 2061 } 2062 } 2063 2064 private class LocationWorkerHandler extends Handler { 2065 public LocationWorkerHandler(Looper looper) { 2066 super(looper, null, true); 2067 } 2068 2069 @Override 2070 public void handleMessage(Message msg) { 2071 switch (msg.what) { 2072 case MSG_LOCATION_CHANGED: 2073 handleLocationChanged((Location) msg.obj, msg.arg1 == 1); 2074 break; 2075 } 2076 } 2077 } 2078 2079 private boolean isMockProvider(String provider) { 2080 synchronized (mLock) { 2081 return mMockProviders.containsKey(provider); 2082 } 2083 } 2084 2085 private void handleLocationChanged(Location location, boolean passive) { 2086 // create a working copy of the incoming Location so that the service can modify it without 2087 // disturbing the caller's copy 2088 Location myLocation = new Location(location); 2089 String provider = myLocation.getProvider(); 2090 2091 // set "isFromMockProvider" bit if location came from a mock provider. we do not clear this 2092 // bit if location did not come from a mock provider because passive/fused providers can 2093 // forward locations from mock providers, and should not grant them legitimacy in doing so. 2094 if (!myLocation.isFromMockProvider() && isMockProvider(provider)) { 2095 myLocation.setIsFromMockProvider(true); 2096 } 2097 2098 synchronized (mLock) { 2099 if (isAllowedByCurrentUserSettingsLocked(provider)) { 2100 if (!passive) { 2101 // notify passive provider of the new location 2102 mPassiveProvider.updateLocation(myLocation); 2103 } 2104 handleLocationChangedLocked(myLocation, passive); 2105 } 2106 } 2107 } 2108 2109 private final PackageMonitor mPackageMonitor = new PackageMonitor() { 2110 @Override 2111 public void onPackageDisappeared(String packageName, int reason) { 2112 // remove all receivers associated with this package name 2113 synchronized (mLock) { 2114 ArrayList<Receiver> deadReceivers = null; 2115 2116 for (Receiver receiver : mReceivers.values()) { 2117 if (receiver.mPackageName.equals(packageName)) { 2118 if (deadReceivers == null) { 2119 deadReceivers = new ArrayList<Receiver>(); 2120 } 2121 deadReceivers.add(receiver); 2122 } 2123 } 2124 2125 // perform removal outside of mReceivers loop 2126 if (deadReceivers != null) { 2127 for (Receiver receiver : deadReceivers) { 2128 removeUpdatesLocked(receiver); 2129 } 2130 } 2131 } 2132 } 2133 }; 2134 2135 // Geocoder 2136 2137 @Override 2138 public boolean geocoderIsPresent() { 2139 return mGeocodeProvider != null; 2140 } 2141 2142 @Override 2143 public String getFromLocation(double latitude, double longitude, int maxResults, 2144 GeocoderParams params, List<Address> addrs) { 2145 if (mGeocodeProvider != null) { 2146 return mGeocodeProvider.getFromLocation(latitude, longitude, maxResults, 2147 params, addrs); 2148 } 2149 return null; 2150 } 2151 2152 2153 @Override 2154 public String getFromLocationName(String locationName, 2155 double lowerLeftLatitude, double lowerLeftLongitude, 2156 double upperRightLatitude, double upperRightLongitude, int maxResults, 2157 GeocoderParams params, List<Address> addrs) { 2158 2159 if (mGeocodeProvider != null) { 2160 return mGeocodeProvider.getFromLocationName(locationName, lowerLeftLatitude, 2161 lowerLeftLongitude, upperRightLatitude, upperRightLongitude, 2162 maxResults, params, addrs); 2163 } 2164 return null; 2165 } 2166 2167 // Mock Providers 2168 2169 private void checkMockPermissionsSafe() { 2170 boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), 2171 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; 2172 if (!allowMocks) { 2173 throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); 2174 } 2175 2176 if (mContext.checkCallingPermission(ACCESS_MOCK_LOCATION) != 2177 PackageManager.PERMISSION_GRANTED) { 2178 throw new SecurityException("Requires ACCESS_MOCK_LOCATION permission"); 2179 } 2180 } 2181 2182 @Override 2183 public void addTestProvider(String name, ProviderProperties properties) { 2184 checkMockPermissionsSafe(); 2185 2186 if (LocationManager.PASSIVE_PROVIDER.equals(name)) { 2187 throw new IllegalArgumentException("Cannot mock the passive location provider"); 2188 } 2189 2190 long identity = Binder.clearCallingIdentity(); 2191 synchronized (mLock) { 2192 MockProvider provider = new MockProvider(name, this, properties); 2193 // remove the real provider if we are replacing GPS or network provider 2194 if (LocationManager.GPS_PROVIDER.equals(name) 2195 || LocationManager.NETWORK_PROVIDER.equals(name) 2196 || LocationManager.FUSED_PROVIDER.equals(name)) { 2197 LocationProviderInterface p = mProvidersByName.get(name); 2198 if (p != null) { 2199 removeProviderLocked(p); 2200 } 2201 } 2202 if (mProvidersByName.get(name) != null) { 2203 throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); 2204 } 2205 addProviderLocked(provider); 2206 mMockProviders.put(name, provider); 2207 mLastLocation.put(name, null); 2208 mLastLocationCoarseInterval.put(name, null); 2209 updateProvidersLocked(); 2210 } 2211 Binder.restoreCallingIdentity(identity); 2212 } 2213 2214 @Override 2215 public void removeTestProvider(String provider) { 2216 checkMockPermissionsSafe(); 2217 synchronized (mLock) { 2218 MockProvider mockProvider = mMockProviders.remove(provider); 2219 if (mockProvider == null) { 2220 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2221 } 2222 long identity = Binder.clearCallingIdentity(); 2223 removeProviderLocked(mProvidersByName.get(provider)); 2224 2225 // reinstate real provider if available 2226 LocationProviderInterface realProvider = mRealProviders.get(provider); 2227 if (realProvider != null) { 2228 addProviderLocked(realProvider); 2229 } 2230 mLastLocation.put(provider, null); 2231 mLastLocationCoarseInterval.put(provider, null); 2232 updateProvidersLocked(); 2233 Binder.restoreCallingIdentity(identity); 2234 } 2235 } 2236 2237 @Override 2238 public void setTestProviderLocation(String provider, Location loc) { 2239 checkMockPermissionsSafe(); 2240 synchronized (mLock) { 2241 MockProvider mockProvider = mMockProviders.get(provider); 2242 if (mockProvider == null) { 2243 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2244 } 2245 // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required 2246 long identity = Binder.clearCallingIdentity(); 2247 mockProvider.setLocation(loc); 2248 Binder.restoreCallingIdentity(identity); 2249 } 2250 } 2251 2252 @Override 2253 public void clearTestProviderLocation(String provider) { 2254 checkMockPermissionsSafe(); 2255 synchronized (mLock) { 2256 MockProvider mockProvider = mMockProviders.get(provider); 2257 if (mockProvider == null) { 2258 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2259 } 2260 mockProvider.clearLocation(); 2261 } 2262 } 2263 2264 @Override 2265 public void setTestProviderEnabled(String provider, boolean enabled) { 2266 checkMockPermissionsSafe(); 2267 synchronized (mLock) { 2268 MockProvider mockProvider = mMockProviders.get(provider); 2269 if (mockProvider == null) { 2270 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2271 } 2272 long identity = Binder.clearCallingIdentity(); 2273 if (enabled) { 2274 mockProvider.enable(); 2275 mEnabledProviders.add(provider); 2276 mDisabledProviders.remove(provider); 2277 } else { 2278 mockProvider.disable(); 2279 mEnabledProviders.remove(provider); 2280 mDisabledProviders.add(provider); 2281 } 2282 updateProvidersLocked(); 2283 Binder.restoreCallingIdentity(identity); 2284 } 2285 } 2286 2287 @Override 2288 public void clearTestProviderEnabled(String provider) { 2289 checkMockPermissionsSafe(); 2290 synchronized (mLock) { 2291 MockProvider mockProvider = mMockProviders.get(provider); 2292 if (mockProvider == null) { 2293 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2294 } 2295 long identity = Binder.clearCallingIdentity(); 2296 mEnabledProviders.remove(provider); 2297 mDisabledProviders.remove(provider); 2298 updateProvidersLocked(); 2299 Binder.restoreCallingIdentity(identity); 2300 } 2301 } 2302 2303 @Override 2304 public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { 2305 checkMockPermissionsSafe(); 2306 synchronized (mLock) { 2307 MockProvider mockProvider = mMockProviders.get(provider); 2308 if (mockProvider == null) { 2309 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2310 } 2311 mockProvider.setStatus(status, extras, updateTime); 2312 } 2313 } 2314 2315 @Override 2316 public void clearTestProviderStatus(String provider) { 2317 checkMockPermissionsSafe(); 2318 synchronized (mLock) { 2319 MockProvider mockProvider = mMockProviders.get(provider); 2320 if (mockProvider == null) { 2321 throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); 2322 } 2323 mockProvider.clearStatus(); 2324 } 2325 } 2326 2327 private void log(String log) { 2328 if (Log.isLoggable(TAG, Log.VERBOSE)) { 2329 Slog.d(TAG, log); 2330 } 2331 } 2332 2333 @Override 2334 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2335 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 2336 != PackageManager.PERMISSION_GRANTED) { 2337 pw.println("Permission Denial: can't dump LocationManagerService from from pid=" 2338 + Binder.getCallingPid() 2339 + ", uid=" + Binder.getCallingUid()); 2340 return; 2341 } 2342 2343 synchronized (mLock) { 2344 pw.println("Current Location Manager state:"); 2345 pw.println(" Location Listeners:"); 2346 for (Receiver receiver : mReceivers.values()) { 2347 pw.println(" " + receiver); 2348 } 2349 pw.println(" Records by Provider:"); 2350 for (Map.Entry<String, ArrayList<UpdateRecord>> entry : mRecordsByProvider.entrySet()) { 2351 pw.println(" " + entry.getKey() + ":"); 2352 for (UpdateRecord record : entry.getValue()) { 2353 pw.println(" " + record); 2354 } 2355 } 2356 pw.println(" Last Known Locations:"); 2357 for (Map.Entry<String, Location> entry : mLastLocation.entrySet()) { 2358 String provider = entry.getKey(); 2359 Location location = entry.getValue(); 2360 pw.println(" " + provider + ": " + location); 2361 } 2362 2363 pw.println(" Last Known Locations Coarse Intervals:"); 2364 for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) { 2365 String provider = entry.getKey(); 2366 Location location = entry.getValue(); 2367 pw.println(" " + provider + ": " + location); 2368 } 2369 2370 mGeofenceManager.dump(pw); 2371 2372 if (mEnabledProviders.size() > 0) { 2373 pw.println(" Enabled Providers:"); 2374 for (String i : mEnabledProviders) { 2375 pw.println(" " + i); 2376 } 2377 2378 } 2379 if (mDisabledProviders.size() > 0) { 2380 pw.println(" Disabled Providers:"); 2381 for (String i : mDisabledProviders) { 2382 pw.println(" " + i); 2383 } 2384 } 2385 pw.append(" "); 2386 mBlacklist.dump(pw); 2387 if (mMockProviders.size() > 0) { 2388 pw.println(" Mock Providers:"); 2389 for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { 2390 i.getValue().dump(pw, " "); 2391 } 2392 } 2393 2394 pw.append(" fudger: "); 2395 mLocationFudger.dump(fd, pw, args); 2396 2397 if (args.length > 0 && "short".equals(args[0])) { 2398 return; 2399 } 2400 for (LocationProviderInterface provider: mProviders) { 2401 pw.print(provider.getName() + " Internal State"); 2402 if (provider instanceof LocationProviderProxy) { 2403 LocationProviderProxy proxy = (LocationProviderProxy) provider; 2404 pw.print(" (" + proxy.getConnectedPackageName() + ")"); 2405 } 2406 pw.println(":"); 2407 provider.dump(fd, pw, args); 2408 } 2409 } 2410 } 2411} 2412