Loading core/java/android/provider/Settings.java +29 −2 Original line number Diff line number Diff line Loading @@ -4052,7 +4052,20 @@ public final class Settings { * @return true if the provider is enabled */ public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) { String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED); return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId()); } /** * Helper method for determining if a location provider is enabled. * @param cr the content resolver to use * @param provider the location provider to query * @param userId the userId to query * @return true if the provider is enabled * @hide */ public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) { String allowedProviders = Settings.Secure.getStringForUser(cr, LOCATION_PROVIDERS_ALLOWED, userId); return TextUtils.delimitedStringContains(allowedProviders, ',', provider); } Loading @@ -4064,6 +4077,19 @@ public final class Settings { */ public static final void setLocationProviderEnabled(ContentResolver cr, String provider, boolean enabled) { setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId()); } /** * Thread-safe method for enabling or disabling a single location provider. * @param cr the content resolver to use * @param provider the location provider to enable or disable * @param enabled true if the provider should be enabled * @param userId the userId for which to enable/disable providers * @hide */ public static final void setLocationProviderEnabledForUser(ContentResolver cr, String provider, boolean enabled, int userId) { // to ensure thread safety, we write the provider name with a '+' or '-' // and let the SettingsProvider handle it rather than reading and modifying // the list of enabled providers. Loading @@ -4072,7 +4098,8 @@ public final class Settings { } else { provider = "-" + provider; } putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider); putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider, userId); } } Loading services/java/com/android/server/LocationManagerService.java +111 −73 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading @@ -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"); } Loading @@ -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(); } } Loading Loading @@ -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; } Loading @@ -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); } /** Loading Loading @@ -695,6 +702,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public List<String> getProviders(Criteria criteria, boolean enabledOnly) { ArrayList<String> out; int callingUserId = UserHandle.getCallingUserId(); long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { out = new ArrayList<String>(mProviders.size()); for (LocationProviderInterface provider : mProviders) { Loading @@ -703,7 +713,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run continue; } if (isAllowedProviderSafe(name)) { if (enabledOnly && !isAllowedBySettingsLocked(name)) { if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) { continue; } if (criteria != null && !LocationProvider.propertiesMeetCriteria( Loading @@ -714,6 +724,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } } } finally { Binder.restoreCallingIdentity(identity); } if (D) Log.d(TAG, "getProviders()=" + out); return out; Loading Loading @@ -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; } } Loading @@ -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); Loading @@ -806,6 +819,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) { // Sends a notification message to the receiver if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { if (deadReceivers == null) { Loading @@ -816,6 +830,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run listeners++; } } } if (deadReceivers != null) { for (int i = deadReceivers.size() - 1; i >= 0; i--) { Loading Loading @@ -843,14 +858,15 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (records != null) { for (UpdateRecord record : records) { 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(); } } } if (providerRequest.reportLocation) { // calculate who to blame for power Loading @@ -860,6 +876,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) { LocationRequest locationRequest = record.mRequest; if (locationRequest.getInterval() <= thresholdInterval) { worksource.add(record.mReceiver.mUid); Loading @@ -867,6 +884,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } } } if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); p.setRequest(providerRequest, worksource); Loading Loading @@ -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 { Loading Loading @@ -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; } Loading @@ -1156,6 +1174,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run String perm = checkPermissionAndRequest(request); checkPackageName(packageName); long identity = Binder.clearCallingIdentity(); try { if (mBlacklist.isBlacklisted(packageName)) { if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + packageName); Loading @@ -1170,7 +1190,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run LocationProviderInterface provider = mProvidersByName.get(name); if (provider == null) return null; if (!isAllowedBySettingsLocked(name)) return null; if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null; Location location = mLastLocation.get(name); if (location == null) { Loading @@ -1186,6 +1206,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } return null; } finally { Binder.restoreCallingIdentity(identity); } } @Override Loading Loading @@ -1321,11 +1344,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run "\" provider requires ACCESS_FINE_LOCATION permission"); } 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); } } Loading Loading @@ -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); Loading Loading @@ -1551,7 +1589,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } synchronized (mLock) { if (isAllowedBySettingsLocked(provider)) { if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { handleLocationChangedLocked(location, passive); } } Loading services/java/com/android/server/ServiceWatcher.java +50 −35 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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++) { Loading @@ -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; } Loading @@ -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) { Loading Loading @@ -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; } 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; } 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) { Loading @@ -197,31 +198,37 @@ public class ServiceWatcher implements ServiceConnection { */ @Override public void onPackageUpdateFinished(String packageName, int uid) { synchronized (mLock) { if (packageName.equals(mPackageName)) { // package updated, make sure to rebind unbind(); unbindLocked(); } // check the updated package in case it is better bindBestPackage(packageName); bindBestPackageLocked(packageName); } } @Override public void onPackageAdded(String packageName, int uid) { synchronized (mLock) { if (packageName.equals(mPackageName)) { // package updated, make sure to rebind unbind(); unbindLocked(); } // check the new package is case it is better bindBestPackage(packageName); bindBestPackageLocked(packageName); } } @Override public void onPackageRemoved(String packageName, int uid) { synchronized (mLock) { if (packageName.equals(mPackageName)) { unbind(); unbindLocked(); // the currently bound package was removed, // need to search for a new package bindBestPackage(null); bindBestPackageLocked(null); } } } }; Loading Loading @@ -271,4 +278,12 @@ public class ServiceWatcher implements ServiceConnection { return mBinder; } } public void switchUser(int userId) { synchronized (mLock) { unbindLocked(); mCurrentUserId = userId; bindBestPackageLocked(null); } } } services/java/com/android/server/location/GeocoderProxy.java +5 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -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 () { Loading services/java/com/android/server/location/GpsLocationProvider.java +5 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading
core/java/android/provider/Settings.java +29 −2 Original line number Diff line number Diff line Loading @@ -4052,7 +4052,20 @@ public final class Settings { * @return true if the provider is enabled */ public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) { String allowedProviders = Settings.Secure.getString(cr, LOCATION_PROVIDERS_ALLOWED); return isLocationProviderEnabledForUser(cr, provider, UserHandle.myUserId()); } /** * Helper method for determining if a location provider is enabled. * @param cr the content resolver to use * @param provider the location provider to query * @param userId the userId to query * @return true if the provider is enabled * @hide */ public static final boolean isLocationProviderEnabledForUser(ContentResolver cr, String provider, int userId) { String allowedProviders = Settings.Secure.getStringForUser(cr, LOCATION_PROVIDERS_ALLOWED, userId); return TextUtils.delimitedStringContains(allowedProviders, ',', provider); } Loading @@ -4064,6 +4077,19 @@ public final class Settings { */ public static final void setLocationProviderEnabled(ContentResolver cr, String provider, boolean enabled) { setLocationProviderEnabledForUser(cr, provider, enabled, UserHandle.myUserId()); } /** * Thread-safe method for enabling or disabling a single location provider. * @param cr the content resolver to use * @param provider the location provider to enable or disable * @param enabled true if the provider should be enabled * @param userId the userId for which to enable/disable providers * @hide */ public static final void setLocationProviderEnabledForUser(ContentResolver cr, String provider, boolean enabled, int userId) { // to ensure thread safety, we write the provider name with a '+' or '-' // and let the SettingsProvider handle it rather than reading and modifying // the list of enabled providers. Loading @@ -4072,7 +4098,8 @@ public final class Settings { } else { provider = "-" + provider; } putString(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider); putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider, userId); } } Loading
services/java/com/android/server/LocationManagerService.java +111 −73 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading @@ -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); Loading @@ -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"); } Loading @@ -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(); } } Loading Loading @@ -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; } Loading @@ -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); } /** Loading Loading @@ -695,6 +702,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run @Override public List<String> getProviders(Criteria criteria, boolean enabledOnly) { ArrayList<String> out; int callingUserId = UserHandle.getCallingUserId(); long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { out = new ArrayList<String>(mProviders.size()); for (LocationProviderInterface provider : mProviders) { Loading @@ -703,7 +713,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run continue; } if (isAllowedProviderSafe(name)) { if (enabledOnly && !isAllowedBySettingsLocked(name)) { if (enabledOnly && !isAllowedBySettingsLocked(name, callingUserId)) { continue; } if (criteria != null && !LocationProvider.propertiesMeetCriteria( Loading @@ -714,6 +724,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } } } finally { Binder.restoreCallingIdentity(identity); } if (D) Log.d(TAG, "getProviders()=" + out); return out; Loading Loading @@ -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; } } Loading @@ -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); Loading @@ -806,6 +819,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) { // Sends a notification message to the receiver if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { if (deadReceivers == null) { Loading @@ -816,6 +830,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run listeners++; } } } if (deadReceivers != null) { for (int i = deadReceivers.size() - 1; i >= 0; i--) { Loading Loading @@ -843,14 +858,15 @@ public class LocationManagerService extends ILocationManager.Stub implements Run if (records != null) { for (UpdateRecord record : records) { 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(); } } } if (providerRequest.reportLocation) { // calculate who to blame for power Loading @@ -860,6 +876,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) { LocationRequest locationRequest = record.mRequest; if (locationRequest.getInterval() <= thresholdInterval) { worksource.add(record.mReceiver.mUid); Loading @@ -867,6 +884,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } } } if (D) Log.d(TAG, "provider request: " + provider + " " + providerRequest); p.setRequest(providerRequest, worksource); Loading Loading @@ -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 { Loading Loading @@ -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; } Loading @@ -1156,6 +1174,8 @@ public class LocationManagerService extends ILocationManager.Stub implements Run String perm = checkPermissionAndRequest(request); checkPackageName(packageName); long identity = Binder.clearCallingIdentity(); try { if (mBlacklist.isBlacklisted(packageName)) { if (D) Log.d(TAG, "not returning last loc for blacklisted app: " + packageName); Loading @@ -1170,7 +1190,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run LocationProviderInterface provider = mProvidersByName.get(name); if (provider == null) return null; if (!isAllowedBySettingsLocked(name)) return null; if (!isAllowedBySettingsLocked(name, mCurrentUserId)) return null; Location location = mLastLocation.get(name); if (location == null) { Loading @@ -1186,6 +1206,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } return null; } finally { Binder.restoreCallingIdentity(identity); } } @Override Loading Loading @@ -1321,11 +1344,16 @@ public class LocationManagerService extends ILocationManager.Stub implements Run "\" provider requires ACCESS_FINE_LOCATION permission"); } 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); } } Loading Loading @@ -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); Loading Loading @@ -1551,7 +1589,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } synchronized (mLock) { if (isAllowedBySettingsLocked(provider)) { if (isAllowedBySettingsLocked(provider, mCurrentUserId)) { handleLocationChangedLocked(location, passive); } } Loading
services/java/com/android/server/ServiceWatcher.java +50 −35 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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++) { Loading @@ -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; } Loading @@ -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) { Loading Loading @@ -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; } 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; } 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) { Loading @@ -197,31 +198,37 @@ public class ServiceWatcher implements ServiceConnection { */ @Override public void onPackageUpdateFinished(String packageName, int uid) { synchronized (mLock) { if (packageName.equals(mPackageName)) { // package updated, make sure to rebind unbind(); unbindLocked(); } // check the updated package in case it is better bindBestPackage(packageName); bindBestPackageLocked(packageName); } } @Override public void onPackageAdded(String packageName, int uid) { synchronized (mLock) { if (packageName.equals(mPackageName)) { // package updated, make sure to rebind unbind(); unbindLocked(); } // check the new package is case it is better bindBestPackage(packageName); bindBestPackageLocked(packageName); } } @Override public void onPackageRemoved(String packageName, int uid) { synchronized (mLock) { if (packageName.equals(mPackageName)) { unbind(); unbindLocked(); // the currently bound package was removed, // need to search for a new package bindBestPackage(null); bindBestPackageLocked(null); } } } }; Loading Loading @@ -271,4 +278,12 @@ public class ServiceWatcher implements ServiceConnection { return mBinder; } } public void switchUser(int userId) { synchronized (mLock) { unbindLocked(); mCurrentUserId = userId; bindBestPackageLocked(null); } } }
services/java/com/android/server/location/GeocoderProxy.java +5 −4 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 { Loading @@ -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 () { Loading
services/java/com/android/server/location/GpsLocationProvider.java +5 −0 Original line number Diff line number Diff line Loading @@ -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); Loading