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