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