diff options
author | Victoria Lease <violets@google.com> | 2012-10-09 12:22:02 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-10-09 12:22:03 -0700 |
commit | c0c0c0e612e1ccf1e55eb2a9338ddfff40d8d7f2 (patch) | |
tree | c5666d6939ad58705078ba46192533739abc8a53 /services/java/com/android/server | |
parent | e45c4e42d26f13d2e405d1d87a665f5796cd1b6d (diff) | |
parent | b711d57ca4e2c6a1befbfa1a41f4b8094755a93f (diff) | |
download | frameworks_base-c0c0c0e612e1ccf1e55eb2a9338ddfff40d8d7f2.zip frameworks_base-c0c0c0e612e1ccf1e55eb2a9338ddfff40d8d7f2.tar.gz frameworks_base-c0c0c0e612e1ccf1e55eb2a9338ddfff40d8d7f2.tar.bz2 |
Merge "Multiuser love for LocationManager" into jb-mr1-dev
Diffstat (limited to 'services/java/com/android/server')
8 files changed, 193 insertions, 116 deletions
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index e73d599..ca28e4c 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,7 +303,7 @@ 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); @@ -314,7 +314,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } // 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"); } @@ -326,11 +327,14 @@ public class LocationManagerService extends ILocationManager.Stub implements Run */ private void switchUser(int userId) { mBlacklist.switchUser(userId); - //Log.d("LocationManagerService", "switchUser(" + mCurrentUserId + " -> " + userId + ")"); // TODO: remove this 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(); } } @@ -587,7 +591,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; } @@ -597,7 +604,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); } /** @@ -695,24 +702,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); @@ -778,12 +791,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; } } @@ -793,7 +806,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); @@ -806,14 +819,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++; } } @@ -843,12 +858,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(); + } } } @@ -860,9 +876,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); + } } } } @@ -1084,7 +1102,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 { @@ -1141,7 +1159,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; } @@ -1156,36 +1174,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 @@ -1321,11 +1344,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run "\" 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); } } @@ -1461,6 +1489,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); @@ -1551,7 +1589,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } synchronized (mLock) { - if (isAllowedBySettingsLocked(provider)) { + if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { handleLocationChangedLocked(location, passive); } } diff --git a/services/java/com/android/server/ServiceWatcher.java b/services/java/com/android/server/ServiceWatcher.java index e99949b..5598b0a 100644 --- a/services/java/com/android/server/ServiceWatcher.java +++ b/services/java/com/android/server/ServiceWatcher.java @@ -27,6 +27,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.os.Handler; import android.os.IBinder; +import android.os.UserHandle; import android.util.Log; import com.android.internal.content.PackageMonitor; @@ -58,15 +59,17 @@ public class ServiceWatcher implements ServiceConnection { private IBinder mBinder; // connected service private String mPackageName; // current best package private int mVersion; // current best version + private int mCurrentUserId; public ServiceWatcher(Context context, String logTag, String action, - List<String> initialPackageNames, Runnable newServiceWork, Handler handler) { + List<String> initialPackageNames, Runnable newServiceWork, Handler handler, int userId) { mContext = context; mTag = logTag; mAction = action; mPm = mContext.getPackageManager(); mNewServiceWork = newServiceWork; mHandler = handler; + mCurrentUserId = userId; mSignatureSets = new ArrayList<HashSet<Signature>>(); for (int i=0; i < initialPackageNames.size(); i++) { @@ -85,9 +88,11 @@ public class ServiceWatcher implements ServiceConnection { } public boolean start() { - if (!bindBestPackage(null)) return false; + synchronized (mLock) { + if (!bindBestPackageLocked(null)) return false; + } - mPackageMonitor.register(mContext, null, true); + mPackageMonitor.register(mContext, null, UserHandle.ALL, true); return true; } @@ -98,13 +103,13 @@ public class ServiceWatcher implements ServiceConnection { * is null. * Return true if a new package was found to bind to. */ - private boolean bindBestPackage(String justCheckThisPackage) { + private boolean bindBestPackageLocked(String justCheckThisPackage) { Intent intent = new Intent(mAction); if (justCheckThisPackage != null) { intent.setPackage(justCheckThisPackage); } - List<ResolveInfo> rInfos = mPm.queryIntentServices(new Intent(mAction), - PackageManager.GET_META_DATA); + List<ResolveInfo> rInfos = mPm.queryIntentServicesAsUser(new Intent(mAction), + PackageManager.GET_META_DATA, mCurrentUserId); int bestVersion = Integer.MIN_VALUE; String bestPackage = null; for (ResolveInfo rInfo : rInfos) { @@ -141,36 +146,32 @@ public class ServiceWatcher implements ServiceConnection { (bestPackage == null ? "no new best package" : "new best packge: " + bestPackage))); if (bestPackage != null) { - bindToPackage(bestPackage, bestVersion); + bindToPackageLocked(bestPackage, bestVersion); return true; } return false; } - private void unbind() { + private void unbindLocked() { String pkg; - synchronized (mLock) { - pkg = mPackageName; - mPackageName = null; - mVersion = Integer.MIN_VALUE; - } + pkg = mPackageName; + mPackageName = null; + mVersion = Integer.MIN_VALUE; if (pkg != null) { if (D) Log.d(mTag, "unbinding " + pkg); mContext.unbindService(this); } } - private void bindToPackage(String packageName, int version) { - unbind(); + private void bindToPackageLocked(String packageName, int version) { + unbindLocked(); Intent intent = new Intent(mAction); intent.setPackage(packageName); - synchronized (mLock) { - mPackageName = packageName; - mVersion = version; - } + mPackageName = packageName; + mVersion = version; if (D) Log.d(mTag, "binding " + packageName + " (version " + version + ")"); mContext.bindService(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND - | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE); + | Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_NOT_VISIBLE, mCurrentUserId); } private boolean isSignatureMatch(Signature[] signatures) { @@ -197,31 +198,37 @@ public class ServiceWatcher implements ServiceConnection { */ @Override public void onPackageUpdateFinished(String packageName, int uid) { - if (packageName.equals(mPackageName)) { - // package updated, make sure to rebind - unbind(); + synchronized (mLock) { + if (packageName.equals(mPackageName)) { + // package updated, make sure to rebind + unbindLocked(); + } + // check the updated package in case it is better + bindBestPackageLocked(packageName); } - // check the updated package in case it is better - bindBestPackage(packageName); } @Override public void onPackageAdded(String packageName, int uid) { - if (packageName.equals(mPackageName)) { - // package updated, make sure to rebind - unbind(); + synchronized (mLock) { + if (packageName.equals(mPackageName)) { + // package updated, make sure to rebind + unbindLocked(); + } + // check the new package is case it is better + bindBestPackageLocked(packageName); } - // check the new package is case it is better - bindBestPackage(packageName); } @Override public void onPackageRemoved(String packageName, int uid) { - if (packageName.equals(mPackageName)) { - unbind(); - // the currently bound package was removed, - // need to search for a new package - bindBestPackage(null); + synchronized (mLock) { + if (packageName.equals(mPackageName)) { + unbindLocked(); + // the currently bound package was removed, + // need to search for a new package + bindBestPackageLocked(null); + } } } }; @@ -271,4 +278,12 @@ public class ServiceWatcher implements ServiceConnection { return mBinder; } } + + public void switchUser(int userId) { + synchronized (mLock) { + unbindLocked(); + mCurrentUserId = userId; + bindBestPackageLocked(null); + } + } } diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java index 7d030e9..f5cc59f 100644 --- a/services/java/com/android/server/location/GeocoderProxy.java +++ b/services/java/com/android/server/location/GeocoderProxy.java @@ -21,6 +21,7 @@ import android.location.Address; import android.location.GeocoderParams; import android.location.IGeocodeProvider; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import com.android.server.ServiceWatcher; @@ -38,8 +39,8 @@ public class GeocoderProxy { private final ServiceWatcher mServiceWatcher; public static GeocoderProxy createAndBind(Context context, - List<String> initialPackageNames) { - GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames); + List<String> initialPackageNames, int userId) { + GeocoderProxy proxy = new GeocoderProxy(context, initialPackageNames, userId); if (proxy.bind()) { return proxy; } else { @@ -47,11 +48,11 @@ public class GeocoderProxy { } } - public GeocoderProxy(Context context, List<String> initialPackageNames) { + public GeocoderProxy(Context context, List<String> initialPackageNames, int userId) { mContext = context; mServiceWatcher = new ServiceWatcher(mContext, TAG, SERVICE_ACTION, initialPackageNames, - null, null); + null, null, userId); } private boolean bind () { diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java index a254d74..c272da4 100755 --- a/services/java/com/android/server/location/GpsLocationProvider.java +++ b/services/java/com/android/server/location/GpsLocationProvider.java @@ -783,6 +783,11 @@ public class GpsLocationProvider implements LocationProviderInterface { sendMessage(SET_REQUEST, 0, new GpsRequest(request, source)); } + @Override + public void switchUser(int userId) { + // nothing to do here + } + private void handleSetRequest(ProviderRequest request, WorkSource source) { if (DEBUG) Log.d(TAG, "setRequest " + request); diff --git a/services/java/com/android/server/location/LocationProviderInterface.java b/services/java/com/android/server/location/LocationProviderInterface.java index 6f09232..80e71f1 100644 --- a/services/java/com/android/server/location/LocationProviderInterface.java +++ b/services/java/com/android/server/location/LocationProviderInterface.java @@ -38,6 +38,8 @@ public interface LocationProviderInterface { public boolean isEnabled(); public void setRequest(ProviderRequest request, WorkSource source); + public void switchUser(int userId); + public void dump(FileDescriptor fd, PrintWriter pw, String[] args); // --- deprecated (but still supported) --- diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java index 7faf72c..dd2e71c 100644 --- a/services/java/com/android/server/location/LocationProviderProxy.java +++ b/services/java/com/android/server/location/LocationProviderProxy.java @@ -25,6 +25,7 @@ import android.location.LocationProvider; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; +import android.os.UserHandle; import android.os.WorkSource; import android.util.Log; @@ -54,9 +55,9 @@ public class LocationProviderProxy implements LocationProviderInterface { private WorkSource mWorksource = new WorkSource(); public static LocationProviderProxy createAndBind(Context context, String name, String action, - List<String> initialPackageNames, Handler handler) { + List<String> initialPackageNames, Handler handler, int userId) { LocationProviderProxy proxy = new LocationProviderProxy(context, name, action, - initialPackageNames, handler); + initialPackageNames, handler, userId); if (proxy.bind()) { return proxy; } else { @@ -65,11 +66,11 @@ public class LocationProviderProxy implements LocationProviderInterface { } private LocationProviderProxy(Context context, String name, String action, - List<String> initialPackageNames, Handler handler) { + List<String> initialPackageNames, Handler handler, int userId) { mContext = context; mName = name; mServiceWatcher = new ServiceWatcher(mContext, TAG, action, initialPackageNames, - mNewServiceWork, handler); + mNewServiceWork, handler, userId); } private boolean bind () { @@ -211,6 +212,11 @@ public class LocationProviderProxy implements LocationProviderInterface { } @Override + public void switchUser(int userId) { + mServiceWatcher.switchUser(userId); + } + + @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.append("REMOTE SERVICE"); pw.append(" name=").append(mName); diff --git a/services/java/com/android/server/location/MockProvider.java b/services/java/com/android/server/location/MockProvider.java index 36c43ff..1194cbc 100644 --- a/services/java/com/android/server/location/MockProvider.java +++ b/services/java/com/android/server/location/MockProvider.java @@ -156,6 +156,11 @@ public class MockProvider implements LocationProviderInterface { public void setRequest(ProviderRequest request, WorkSource source) { } @Override + public void switchUser(int userId) { + // nothing to do here + } + + @Override public boolean sendExtraCommand(String command, Bundle extras) { return false; } diff --git a/services/java/com/android/server/location/PassiveProvider.java b/services/java/com/android/server/location/PassiveProvider.java index 71bae07..734c572 100644 --- a/services/java/com/android/server/location/PassiveProvider.java +++ b/services/java/com/android/server/location/PassiveProvider.java @@ -96,6 +96,11 @@ public class PassiveProvider implements LocationProviderInterface { mReportLocation = request.reportLocation; } + @Override + public void switchUser(int userId) { + // nothing to do here + } + public void updateLocation(Location location) { if (mReportLocation) { try { |