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