diff options
Diffstat (limited to 'services/java/com/android/server/LocationManagerService.java')
| -rw-r--r-- | services/java/com/android/server/LocationManagerService.java | 220 |
1 files changed, 144 insertions, 76 deletions
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index ae95c4c..c5016e6 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -226,7 +226,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run updateProvidersLocked(); } } - }); + }, UserHandle.USER_ALL); mPackageMonitor.register(mContext, Looper.myLooper(), true); // listen for user change @@ -289,7 +289,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run mContext, LocationManager.NETWORK_PROVIDER, NETWORK_LOCATION_SERVICE_ACTION, - providerPackageNames, mLocationHandler); + providerPackageNames, mLocationHandler, mCurrentUserId); if (networkProvider != null) { mRealProviders.put(LocationManager.NETWORK_PROVIDER, networkProvider); mProxyProviders.add(networkProvider); @@ -303,18 +303,20 @@ public class LocationManagerService extends ILocationManager.Stub implements Run mContext, LocationManager.FUSED_PROVIDER, FUSED_LOCATION_SERVICE_ACTION, - providerPackageNames, mLocationHandler); + providerPackageNames, mLocationHandler, mCurrentUserId); if (fusedLocationProvider != null) { addProviderLocked(fusedLocationProvider); mProxyProviders.add(fusedLocationProvider); mEnabledProviders.add(fusedLocationProvider.getName()); + mRealProviders.put(LocationManager.FUSED_PROVIDER, fusedLocationProvider); } else { Slog.e(TAG, "no fused location provider found", new IllegalStateException("Location service needs a fused location provider")); } // bind to geocoder provider - mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames); + mGeocodeProvider = GeocoderProxy.createAndBind(mContext, providerPackageNames, + mCurrentUserId); if (mGeocodeProvider == null) { Slog.e(TAG, "no geocoder provider found"); } @@ -325,11 +327,15 @@ public class LocationManagerService extends ILocationManager.Stub implements Run * @param userId the new active user's UserId */ private void switchUser(int userId) { - //Log.d("LocationManagerService", "switchUser(" + mCurrentUserId + " -> " + userId + ")"); // TODO: remove this + mBlacklist.switchUser(userId); synchronized (mLock) { - // TODO: inform previous user's Receivers that they will no longer receive updates + mLastLocation.clear(); + for (LocationProviderInterface p : mProviders) { + updateProviderListenersLocked(p.getName(), false, mCurrentUserId); + p.switchUser(userId); + } mCurrentUserId = userId; - // TODO: inform new user's Receivers that they are back on the update train + updateProvidersLocked(); } } @@ -586,7 +592,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } - private boolean isAllowedBySettingsLocked(String provider) { + private boolean isAllowedBySettingsLocked(String provider, int userId) { + if (userId != mCurrentUserId) { + return false; + } if (mEnabledProviders.contains(provider)) { return true; } @@ -596,7 +605,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Use system settings ContentResolver resolver = mContext.getContentResolver(); - return Settings.Secure.isLocationProviderEnabled(resolver, provider); + return Settings.Secure.isLocationProviderEnabledForUser(resolver, provider, mCurrentUserId); } /** @@ -639,7 +648,27 @@ public class LocationManagerService extends ILocationManager.Stub implements Run == PackageManager.PERMISSION_GRANTED) || (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED); + } else { + // mock providers + LocationProviderInterface lp = mMockProviders.get(provider); + if (lp != null) { + ProviderProperties properties = lp.getProperties(); + if (properties != null) { + if (properties.mRequiresSatellite) { + // provider requiring satellites require FINE permission + return mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED; + } else if (properties.mRequiresNetwork || properties.mRequiresCell) { + // provider requiring network and or cell require COARSE or FINE + return (mContext.checkCallingOrSelfPermission(ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) || + (mContext.checkCallingOrSelfPermission(ACCESS_COARSE_LOCATION) + == PackageManager.PERMISSION_GRANTED); + } + } + } } + return false; } @@ -674,24 +703,30 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public List<String> getProviders(Criteria criteria, boolean enabledOnly) { ArrayList<String> out; - synchronized (mLock) { - out = new ArrayList<String>(mProviders.size()); - for (LocationProviderInterface provider : mProviders) { - String name = provider.getName(); - if (LocationManager.FUSED_PROVIDER.equals(name)) { - continue; - } - if (isAllowedProviderSafe(name)) { - if (enabledOnly && !isAllowedBySettingsLocked(name)) { + int callingUserId = UserHandle.getCallingUserId(); + long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + out = new ArrayList<String>(mProviders.size()); + for (LocationProviderInterface provider : mProviders) { + String name = provider.getName(); + if (LocationManager.FUSED_PROVIDER.equals(name)) { continue; } - if (criteria != null && !LocationProvider.propertiesMeetCriteria( - name, provider.getProperties(), criteria)) { - continue; + if (isAllowedProviderSafe(name)) { + if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) { + continue; + } + if (criteria != null && !LocationProvider.propertiesMeetCriteria( + name, provider.getProperties(), criteria)) { + continue; + } + out.add(name); } - out.add(name); } } + } finally { + Binder.restoreCallingIdentity(identity); } if (D) Log.d(TAG, "getProviders()=" + out); @@ -757,12 +792,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run LocationProviderInterface p = mProviders.get(i); boolean isEnabled = p.isEnabled(); String name = p.getName(); - boolean shouldBeEnabled = isAllowedBySettingsLocked(name); + boolean shouldBeEnabled = isAllowedBySettingsLocked(name, mCurrentUserId); if (isEnabled && !shouldBeEnabled) { - updateProviderListenersLocked(name, false); + updateProviderListenersLocked(name, false, mCurrentUserId); changesMade = true; } else if (!isEnabled && shouldBeEnabled) { - updateProviderListenersLocked(name, true); + updateProviderListenersLocked(name, true, mCurrentUserId); changesMade = true; } } @@ -772,7 +807,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } - private void updateProviderListenersLocked(String provider, boolean enabled) { + private void updateProviderListenersLocked(String provider, boolean enabled, int userId) { int listeners = 0; LocationProviderInterface p = mProvidersByName.get(provider); @@ -785,14 +820,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run final int N = records.size(); for (int i = 0; i < N; i++) { UpdateRecord record = records.get(i); - // Sends a notification message to the receiver - if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { - if (deadReceivers == null) { - deadReceivers = new ArrayList<Receiver>(); + if (UserHandle.getUserId(record.mReceiver.mUid) == userId) { + // Sends a notification message to the receiver + if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { + if (deadReceivers == null) { + deadReceivers = new ArrayList<Receiver>(); + } + deadReceivers.add(record.mReceiver); } - deadReceivers.add(record.mReceiver); + listeners++; } - listeners++; } } @@ -822,12 +859,13 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (records != null) { for (UpdateRecord record : records) { - LocationRequest locationRequest = record.mRequest; - - providerRequest.locationRequests.add(locationRequest); - if (locationRequest.getInterval() < providerRequest.interval) { - providerRequest.reportLocation = true; - providerRequest.interval = locationRequest.getInterval(); + if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { + LocationRequest locationRequest = record.mRequest; + providerRequest.locationRequests.add(locationRequest); + if (locationRequest.getInterval() < providerRequest.interval) { + providerRequest.reportLocation = true; + providerRequest.interval = locationRequest.getInterval(); + } } } @@ -839,9 +877,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // under that threshold. long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; for (UpdateRecord record : records) { - LocationRequest locationRequest = record.mRequest; - if (locationRequest.getInterval() <= thresholdInterval) { - worksource.add(record.mReceiver.mUid); + if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { + LocationRequest locationRequest = record.mRequest; + if (locationRequest.getInterval() <= thresholdInterval) { + worksource.add(record.mReceiver.mUid); + } } } } @@ -1063,7 +1103,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run oldRecord.disposeLocked(false); } - boolean isProviderEnabled = isAllowedBySettingsLocked(name); + boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid)); if (isProviderEnabled) { applyRequirementsLocked(name); } else { @@ -1120,7 +1160,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // update provider for (String provider : providers) { // If provider is already disabled, don't need to do anything - if (!isAllowedBySettingsLocked(provider)) { + if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) { continue; } @@ -1135,36 +1175,41 @@ public class LocationManagerService extends ILocationManager.Stub implements Run String perm = checkPermissionAndRequest(request); checkPackageName(packageName); - if (mBlacklist.isBlacklisted(packageName)) { - if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + - packageName); - return null; - } - - synchronized (mLock) { - // Figure out the provider. Either its explicitly request (deprecated API's), - // or use the fused provider - String name = request.getProvider(); - if (name == null) name = LocationManager.FUSED_PROVIDER; - LocationProviderInterface provider = mProvidersByName.get(name); - if (provider == null) return null; - - if (!isAllowedBySettingsLocked(name)) return null; - - Location location = mLastLocation.get(name); - if (location == null) { + long identity = Binder.clearCallingIdentity(); + try { + if (mBlacklist.isBlacklisted(packageName)) { + if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + + packageName); return null; } - if (ACCESS_FINE_LOCATION.equals(perm)) { - return location; - } else { - Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); - if (noGPSLocation != null) { - return mLocationFudger.getOrCreate(noGPSLocation); + + synchronized (mLock) { + // Figure out the provider. Either its explicitly request (deprecated API's), + // or use the fused provider + String name = request.getProvider(); + if (name == null) name = LocationManager.FUSED_PROVIDER; + LocationProviderInterface provider = mProvidersByName.get(name); + if (provider == null) return null; + + if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null; + + Location location = mLastLocation.get(name); + if (location == null) { + return null; + } + if (ACCESS_FINE_LOCATION.equals(perm)) { + return location; + } else { + Location noGPSLocation = location.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION); + if (noGPSLocation != null) { + return mLocationFudger.getOrCreate(noGPSLocation); + } } } + return null; + } finally { + Binder.restoreCallingIdentity(identity); } - return null; } @Override @@ -1292,14 +1337,24 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public boolean isProviderEnabled(String provider) { - checkPermission(); + String perms = checkPermission(); if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; + if (ACCESS_COARSE_LOCATION.equals(perms) && + !isProviderAllowedByCoarsePermission(provider)) { + throw new SecurityException("The \"" + provider + + "\" provider requires ACCESS_FINE_LOCATION permission"); + } - synchronized (mLock) { - LocationProviderInterface p = mProvidersByName.get(provider); - if (p == null) return false; + long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + LocationProviderInterface p = mProvidersByName.get(provider); + if (p == null) return false; - return isAllowedBySettingsLocked(provider); + return isAllowedBySettingsLocked(provider, mCurrentUserId); + } + } finally { + Binder.restoreCallingIdentity(identity); } } @@ -1388,9 +1443,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run long now = SystemClock.elapsedRealtime(); String provider = (passive ? LocationManager.PASSIVE_PROVIDER : location.getProvider()); - ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); - if (records == null || records.size() == 0) return; + // Skip if the provider is unknown. LocationProviderInterface p = mProvidersByName.get(provider); if (p == null) return; @@ -1411,6 +1465,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } lastLocation.set(location); + // Skip if there are no UpdateRecords for this provider. + ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); + if (records == null || records.size() == 0) return; + // Fetch coarse location Location coarseLocation = null; if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) { @@ -1432,6 +1490,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run Receiver receiver = r.mReceiver; boolean receiverDead = false; + int receiverUserId = UserHandle.getUserId(receiver.mUid); + if (receiverUserId != mCurrentUserId) { + if (D) { + Log.d(TAG, "skipping loc update for background user " + receiverUserId + + " (current user: " + mCurrentUserId + ", app: " + + receiver.mPackageName + ")"); + } + continue; + } + if (mBlacklist.isBlacklisted(receiver.mPackageName)) { if (D) Log.d(TAG, "skipping loc update for blacklisted app: " + receiver.mPackageName); @@ -1522,7 +1590,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } synchronized (mLock) { - if (isAllowedBySettingsLocked(provider)) { + if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { handleLocationChangedLocked(location, passive); } } |
