summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server/LocationManagerService.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/LocationManagerService.java')
-rw-r--r--services/java/com/android/server/LocationManagerService.java220
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);
}
}