diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 5f562cf86d0f7..f3089c1092e64 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -294,9 +294,8 @@ public class LocationManagerService extends ILocationManager.Stub { AppOpsManager.WATCH_FOREGROUND_CHANGES, new AppOpsManager.OnOpChangedInternalListener() { public void onOpChanged(int op, String packageName) { - // onOpChanged invoked on ui thread, move to our thread to reduce - // risk of - // blocking ui thread + // onOpChanged invoked on ui thread, move to our thread to reduce risk + // of blocking ui thread mHandler.post(() -> { synchronized (mLock) { onAppOpChangedLocked(); @@ -307,8 +306,7 @@ public class LocationManagerService extends ILocationManager.Stub { mPackageManager.addOnPermissionsChangeListener( uid -> { // listener invoked on ui thread, move to our thread to reduce risk of - // blocking - // ui thread + // blocking ui thread mHandler.post(() -> { synchronized (mLock) { onPermissionsChangedLocked(); @@ -318,8 +316,7 @@ public class LocationManagerService extends ILocationManager.Stub { mActivityManager.addOnUidImportanceListener( (uid, importance) -> { // listener invoked on ui thread, move to our thread to reduce risk of - // blocking - // ui thread + // blocking ui thread mHandler.post(() -> { synchronized (mLock) { onUidImportanceChangedLocked(uid, importance); @@ -331,8 +328,7 @@ public class LocationManagerService extends ILocationManager.Stub { localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION, state -> { // listener invoked on ui thread, move to our thread to reduce risk of - // blocking - // ui thread + // blocking ui thread mHandler.post(() -> { synchronized (mLock) { onBatterySaverModeChangedLocked(state.locationMode); @@ -341,14 +337,14 @@ public class LocationManagerService extends ILocationManager.Stub { }); mBatterySaverMode = mPowerManager.getLocationPowerSaveMode(); - mSettingsStore.addOnLocationEnabledChangedListener(() -> { + mSettingsStore.addOnLocationEnabledChangedListener((userId) -> { synchronized (mLock) { - onLocationModeChangedLocked(true); + onLocationModeChangedLocked(userId, true); } }); - mSettingsStore.addOnLocationProvidersAllowedChangedListener(() -> { + mSettingsStore.addOnLocationProvidersAllowedChangedListener((userId) -> { synchronized (mLock) { - onProviderAllowedChangedLocked(); + onProviderAllowedChangedLocked(userId); } }); mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> { @@ -471,7 +467,11 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private void onLocationModeChangedLocked(boolean broadcast) { + private void onLocationModeChangedLocked(int userId, boolean broadcast) { + if (!isCurrentProfileLocked(userId)) { + return; + } + if (D) { Log.d(TAG, "location enabled is now " + isLocationEnabled()); } @@ -490,7 +490,11 @@ public class LocationManagerService extends ILocationManager.Stub { } @GuardedBy("mLock") - private void onProviderAllowedChangedLocked() { + private void onProviderAllowedChangedLocked(int userId) { + if (!isCurrentProfileLocked(userId)) { + return; + } + for (LocationProvider p : mProviders) { p.onAllowedChangedLocked(); } @@ -803,8 +807,8 @@ public class LocationManagerService extends ILocationManager.Stub { onUserProfilesChangedLocked(); // if the user changes, per-user settings may also have changed - onLocationModeChangedLocked(false); - onProviderAllowedChangedLocked(); + onLocationModeChangedLocked(userId, false); + onProviderAllowedChangedLocked(userId); // always force useability to be rechecked, even if no per-user settings have changed for (LocationProvider p : mProviders) { diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java index dc5628e0a4eb1..eb2a37b38f1cb 100644 --- a/services/core/java/com/android/server/location/LocationSettingsStore.java +++ b/services/core/java/com/android/server/location/LocationSettingsStore.java @@ -33,21 +33,51 @@ import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArraySet; import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; +import com.android.server.SystemConfig; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Supplier; /** * Provides accessors and listeners for all location related settings. */ public class LocationSettingsStore { + /** + * Listener for user-specific settings changes. + */ + public interface UserSettingChangedListener { + /** + * Called when setting changes. + */ + void onSettingChanged(int userId); + } + + /** + * Listener for global settings changes. + */ + public interface GlobalSettingChangedListener extends UserSettingChangedListener { + /** + * Called when setting changes. + */ + void onSettingChanged(); + + @Override + default void onSettingChanged(int userId) { + onSettingChanged(); + } + } + private static final String LOCATION_PACKAGE_BLACKLIST = "locationPackagePrefixBlacklist"; private static final String LOCATION_PACKAGE_WHITELIST = "locationPackagePrefixWhitelist"; @@ -63,9 +93,10 @@ public class LocationSettingsStore { private final LongGlobalSetting mBackgroundThrottleIntervalMs; private final StringListCachedSecureSetting mLocationPackageBlacklist; private final StringListCachedSecureSetting mLocationPackageWhitelist; - private final StringListCachedGlobalSetting mBackgroundThrottlePackageWhitelist; - private final StringListCachedGlobalSetting mIgnoreSettingsPackageWhitelist; + private final StringSetCachedGlobalSetting mBackgroundThrottlePackageWhitelist; + private final StringSetCachedGlobalSetting mIgnoreSettingsPackageWhitelist; + // TODO: get rid of handler public LocationSettingsStore(Context context, Handler handler) { mContext = context; @@ -78,10 +109,12 @@ public class LocationSettingsStore { LOCATION_PACKAGE_BLACKLIST, handler); mLocationPackageWhitelist = new StringListCachedSecureSetting(context, LOCATION_PACKAGE_WHITELIST, handler); - mBackgroundThrottlePackageWhitelist = new StringListCachedGlobalSetting(context, - LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, handler); - mIgnoreSettingsPackageWhitelist = new StringListCachedGlobalSetting(context, - LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST, handler); + mBackgroundThrottlePackageWhitelist = new StringSetCachedGlobalSetting(context, + LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, + () -> SystemConfig.getInstance().getAllowUnthrottledLocation(), handler); + mIgnoreSettingsPackageWhitelist = new StringSetCachedGlobalSetting(context, + LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST, + () -> SystemConfig.getInstance().getAllowIgnoreLocationSettings(), handler); } /** @@ -94,14 +127,14 @@ public class LocationSettingsStore { /** * Add a listener for changes to the location enabled setting. */ - public void addOnLocationEnabledChangedListener(Runnable listener) { + public void addOnLocationEnabledChangedListener(UserSettingChangedListener listener) { mLocationMode.addListener(listener); } /** * Remove a listener for changes to the location enabled setting. */ - public void removeOnLocationEnabledChangedListener(Runnable listener) { + public void removeOnLocationEnabledChangedListener(UserSettingChangedListener listener) { mLocationMode.addListener(listener); } @@ -115,15 +148,16 @@ public class LocationSettingsStore { /** * Add a listener for changes to the currently allowed location providers. */ - public void addOnLocationProvidersAllowedChangedListener(Runnable runnable) { - mLocationProvidersAllowed.addListener(runnable); + public void addOnLocationProvidersAllowedChangedListener(UserSettingChangedListener listener) { + mLocationProvidersAllowed.addListener(listener); } /** * Remove a listener for changes to the currently allowed location providers. */ - public void removeOnLocationProvidersAllowedChangedListener(Runnable runnable) { - mLocationProvidersAllowed.removeListener(runnable); + public void removeOnLocationProvidersAllowedChangedListener( + UserSettingChangedListener listener) { + mLocationProvidersAllowed.removeListener(listener); } /** @@ -136,14 +170,16 @@ public class LocationSettingsStore { /** * Add a listener for changes to the background throttle interval. */ - public void addOnBackgroundThrottleIntervalChangedListener(Runnable listener) { + public void addOnBackgroundThrottleIntervalChangedListener( + GlobalSettingChangedListener listener) { mBackgroundThrottleIntervalMs.addListener(listener); } /** * Remove a listener for changes to the background throttle interval. */ - public void removeOnBackgroundThrottleIntervalChangedListener(Runnable listener) { + public void removeOnBackgroundThrottleIntervalChangedListener( + GlobalSettingChangedListener listener) { mBackgroundThrottleIntervalMs.removeListener(listener); } @@ -175,42 +211,46 @@ public class LocationSettingsStore { /** * Retrieve the background throttle package whitelist. */ - public List getBackgroundThrottlePackageWhitelist() { + public Set getBackgroundThrottlePackageWhitelist() { return mBackgroundThrottlePackageWhitelist.getValue(); } /** * Add a listener for changes to the background throttle package whitelist. */ - public void addOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) { + public void addOnBackgroundThrottlePackageWhitelistChangedListener( + GlobalSettingChangedListener listener) { mBackgroundThrottlePackageWhitelist.addListener(listener); } /** * Remove a listener for changes to the background throttle package whitelist. */ - public void removeOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) { + public void removeOnBackgroundThrottlePackageWhitelistChangedListener( + GlobalSettingChangedListener listener) { mBackgroundThrottlePackageWhitelist.removeListener(listener); } /** * Retrieve the ignore settings package whitelist. */ - public List getIgnoreSettingsPackageWhitelist() { + public Set getIgnoreSettingsPackageWhitelist() { return mIgnoreSettingsPackageWhitelist.getValue(); } /** * Add a listener for changes to the ignore settings package whitelist. */ - public void addOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) { + public void addOnIgnoreSettingsPackageWhitelistChangedListener( + GlobalSettingChangedListener listener) { mIgnoreSettingsPackageWhitelist.addListener(listener); } /** * Remove a listener for changes to the ignore settings package whitelist. */ - public void removeOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) { + public void removeOnIgnoreSettingsPackageWhitelistChangedListener( + GlobalSettingChangedListener listener) { mIgnoreSettingsPackageWhitelist.removeListener(listener); } @@ -264,7 +304,7 @@ public class LocationSettingsStore { } } - List backgroundThrottlePackageWhitelist = + Set backgroundThrottlePackageWhitelist = mBackgroundThrottlePackageWhitelist.getValue(); if (!backgroundThrottlePackageWhitelist.isEmpty()) { ipw.println("Throttling Whitelisted Packages:"); @@ -275,7 +315,7 @@ public class LocationSettingsStore { ipw.decreaseIndent(); } - List ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue(); + Set ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue(); if (!ignoreSettingsPackageWhitelist.isEmpty()) { ipw.println("Bypass Whitelisted Packages:"); ipw.increaseIndent(); @@ -288,7 +328,7 @@ public class LocationSettingsStore { private abstract static class ObservingSetting extends ContentObserver { - private final CopyOnWriteArrayList mListeners; + private final CopyOnWriteArrayList mListeners; private ObservingSetting(Context context, String settingName, Handler handler) { super(handler); @@ -298,11 +338,11 @@ public class LocationSettingsStore { getUriFor(settingName), false, this, UserHandle.USER_ALL); } - public void addListener(Runnable listener) { + public void addListener(UserSettingChangedListener listener) { mListeners.add(listener); } - public void removeListener(Runnable listener) { + public void removeListener(UserSettingChangedListener listener) { mListeners.remove(listener); } @@ -310,8 +350,8 @@ public class LocationSettingsStore { @Override public void onChange(boolean selfChange, Uri uri, int userId) { - for (Runnable listener : mListeners) { - listener.run(); + for (UserSettingChangedListener listener : mListeners) { + listener.onSettingChanged(userId); } } } @@ -354,6 +394,8 @@ public class LocationSettingsStore { } public synchronized List getValueForUser(int userId) { + Preconditions.checkArgument(userId != UserHandle.USER_NULL); + if (userId != mCachedUserId) { String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), mSettingName, userId); @@ -409,29 +451,30 @@ public class LocationSettingsStore { } } - private static class StringListCachedGlobalSetting extends ObservingSetting { + private static class StringSetCachedGlobalSetting extends ObservingSetting { private final Context mContext; private final String mSettingName; + private final Supplier> mBaseValuesSupplier; private boolean mValid; - private List mCachedValue; + private ArraySet mCachedValue; - private StringListCachedGlobalSetting(Context context, String settingName, - Handler handler) { + private StringSetCachedGlobalSetting(Context context, String settingName, + Supplier> baseValuesSupplier, Handler handler) { super(context, settingName, handler); mContext = context; mSettingName = settingName; + mBaseValuesSupplier = baseValuesSupplier; } - public synchronized List getValue() { + public synchronized Set getValue() { if (!mValid) { + mCachedValue = new ArraySet<>(mBaseValuesSupplier.get()); String setting = Settings.Global.getString(mContext.getContentResolver(), mSettingName); - if (TextUtils.isEmpty(setting)) { - mCachedValue = Collections.emptyList(); - } else { - mCachedValue = Arrays.asList(setting.split(",")); + if (!TextUtils.isEmpty(setting)) { + mCachedValue.addAll(Arrays.asList(setting.split(","))); } mValid = true; }