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