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