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