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