From e5601ce9bfa4effbddb84186f0fe1bfe4ad50301 Mon Sep 17 00:00:00 2001 From: Victoria Lease Date: Fri, 26 Oct 2012 14:34:48 -0700 Subject: [PATCH] make FLP play nicely with multiuser Frameworks' FusedLocationProvider runs as a specific user so that it can join a specific process. The solution that works for NLP, run one copy per user as that user, does not work for FLP. To make FLP play nicely with multiuser, I've allowed SYSTEM_UID to operate in the background and included a hardcoded exception to prevent ServiceWatcher from trying to launch one FLP per user. Bug: 7279799 Change-Id: I573ea5226d8d00777421b39c5c3fb0899bf09b4d --- .../server/LocationManagerService.java | 69 +++++++++++++------ 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 37dee1980c549..eb833eb54de53 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -405,7 +405,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run mLastLocation.clear(); for (LocationProviderInterface p : mProviders) { updateProviderListenersLocked(p.getName(), false, mCurrentUserId); - p.switchUser(userId); + if (!LocationManager.FUSED_PROVIDER.equals(p.getName())) { + p.switchUser(userId); + } } mCurrentUserId = userId; updateProvidersLocked(); @@ -664,9 +666,27 @@ public class LocationManagerService extends ILocationManager.Stub implements Run mProvidersByName.remove(provider.getName()); } + /** + * Returns true if the specified UID is SYSTEM_UID or matches the current user. + * + * @param uid the uid + * @return true if uid is SYSTEM_UID or matches the current user + */ + private boolean isCurrentUserOrSystemLocked(int uid) { + return uid == Process.SYSTEM_UID || UserHandle.getUserId(uid) == mCurrentUserId; + } - private boolean isAllowedBySettingsLocked(String provider, int userId) { - if (userId != mCurrentUserId) { + /** + * Returns the first UID in the current user's range. + * + * @return the first UID in the current user's range + */ + private int getCurrentUidBaseLocked() { + return UserHandle.getUid(mCurrentUserId, 0); + } + + private boolean isAllowedBySettingsLocked(String provider, int uid) { + if (!isCurrentUserOrSystemLocked(uid)) { return false; } if (mEnabledProviders.contains(provider)) { @@ -675,6 +695,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (mDisabledProviders.contains(provider)) { return false; } + if (uid == Process.SYSTEM_UID) { + return true; + } + // Use system settings ContentResolver resolver = mContext.getContentResolver(); @@ -828,8 +852,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run public List getProviders(Criteria criteria, boolean enabledOnly) { int allowedResolutionLevel = getCallerAllowedResolutionLevel(); ArrayList out; - int callingUserId = UserHandle.getCallingUserId(); - long identity = Binder.clearCallingIdentity(); + final int callingUid = Binder.getCallingUid(); + final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { out = new ArrayList(mProviders.size()); @@ -839,7 +863,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run continue; } if (allowedResolutionLevel >= getMinimumResolutionLevelForProviderUse(name)) { - if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) { + if (enabledOnly && !isAllowedBySettingsLocked(name, callingUid)) { continue; } if (criteria != null && !LocationProvider.propertiesMeetCriteria( @@ -915,7 +939,7 @@ 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, mCurrentUserId); + boolean shouldBeEnabled = isAllowedBySettingsLocked(name, getCurrentUidBaseLocked()); if (isEnabled && !shouldBeEnabled) { updateProviderListenersLocked(name, false, mCurrentUserId); changesMade = true; @@ -943,7 +967,7 @@ 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); - if (UserHandle.getUserId(record.mReceiver.mUid) == userId) { + if (isCurrentUserOrSystemLocked(record.mReceiver.mUid)) { // Sends a notification message to the receiver if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { if (deadReceivers == null) { @@ -982,7 +1006,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (records != null) { for (UpdateRecord record : records) { - if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { + if (isCurrentUserOrSystemLocked(record.mReceiver.mUid)) { LocationRequest locationRequest = record.mRequest; providerRequest.locationRequests.add(locationRequest); if (locationRequest.getInterval() < providerRequest.interval) { @@ -1000,7 +1024,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // under that threshold. long thresholdInterval = (providerRequest.interval + 1000) * 3 / 2; for (UpdateRecord record : records) { - if (UserHandle.getUserId(record.mReceiver.mUid) == mCurrentUserId) { + if (isCurrentUserOrSystemLocked(record.mReceiver.mUid)) { LocationRequest locationRequest = record.mRequest; if (locationRequest.getInterval() <= thresholdInterval) { worksource.add(record.mReceiver.mUid); @@ -1223,7 +1247,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run oldRecord.disposeLocked(false); } - boolean isProviderEnabled = isAllowedBySettingsLocked(name, UserHandle.getUserId(uid)); + boolean isProviderEnabled = isAllowedBySettingsLocked(name, uid); if (isProviderEnabled) { applyRequirementsLocked(name); } else { @@ -1278,9 +1302,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } // update provider + int currentUidBase = getCurrentUidBaseLocked(); for (String provider : providers) { // If provider is already disabled, don't need to do anything - if (!isAllowedBySettingsLocked(provider, mCurrentUserId)) { + if (!isAllowedBySettingsLocked(provider, currentUidBase)) { continue; } @@ -1298,7 +1323,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run request.getProvider()); // no need to sanitize this request, as only the provider name is used - long identity = Binder.clearCallingIdentity(); + final int callingUid = Binder.getCallingUid(); + final long identity = Binder.clearCallingIdentity(); try { if (mBlacklist.isBlacklisted(packageName)) { if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + @@ -1314,7 +1340,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run LocationProviderInterface provider = mProvidersByName.get(name); if (provider == null) return null; - if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null; + if (!isAllowedBySettingsLocked(name, callingUid)) { + return null; + } Location location = mLastLocation.get(name); if (location == null) { @@ -1471,13 +1499,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Run provider); if (LocationManager.FUSED_PROVIDER.equals(provider)) return false; - long identity = Binder.clearCallingIdentity(); + final int callingUid = Binder.getCallingUid(); + final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { LocationProviderInterface p = mProvidersByName.get(provider); if (p == null) return false; - return isAllowedBySettingsLocked(provider, mCurrentUserId); + return isAllowedBySettingsLocked(provider, callingUid); } } finally { Binder.restoreCallingIdentity(identity); @@ -1616,10 +1645,10 @@ public class LocationManagerService extends ILocationManager.Stub implements Run Receiver receiver = r.mReceiver; boolean receiverDead = false; - int receiverUserId = UserHandle.getUserId(receiver.mUid); - if (receiverUserId != mCurrentUserId) { + final int receiverUid = receiver.mUid; + if (!isCurrentUserOrSystemLocked(receiverUid)) { if (D) { - Log.d(TAG, "skipping loc update for background user " + receiverUserId + + Log.d(TAG, "skipping loc update for background uid " + receiverUid + " (current user: " + mCurrentUserId + ", app: " + receiver.mPackageName + ")"); } @@ -1716,7 +1745,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } synchronized (mLock) { - if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { + if (isAllowedBySettingsLocked(provider, getCurrentUidBaseLocked())) { handleLocationChangedLocked(location, passive); } }