Loading api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ package android { field public static final String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS"; field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE"; field public static final String MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE = "android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE"; field public static final String MONITOR_DEVICE_CONFIG_ACCESS = "android.permission.MONITOR_DEVICE_CONFIG_ACCESS"; field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE"; field public static final String NETWORK_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE"; field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING"; Loading core/java/android/provider/DeviceConfig.java +8 −0 Original line number Diff line number Diff line Loading @@ -795,6 +795,14 @@ public final class DeviceConfig { } } /** * Returns list of namespaces that can be read without READ_DEVICE_CONFIG_PERMISSION; * @hide */ public static @NonNull List<String> getPublicNamespaces() { return PUBLIC_NAMESPACES; } /** * Interface for monitoring changes to properties. Implementations will receive callbacks when * properties change, including a {@link Properties} object which contains a single namespace Loading core/java/android/provider/Settings.java +57 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import android.os.IBinder; import android.os.LocaleList; import android.os.PowerManager.AutoPowerSaveModeTriggers; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; Loading Loading @@ -2160,6 +2161,11 @@ public final class Settings { */ public static final String CALL_METHOD_PREFIX_KEY = "_prefix"; /** * @hide - RemoteCallback monitor callback argument extra to the fast-path call()-based requests */ public static final String CALL_METHOD_MONITOR_CALLBACK_KEY = "_monitor_callback_key"; /** * @hide - String argument extra to the fast-path call()-based requests */ Loading Loading @@ -2218,6 +2224,26 @@ public final class Settings { /** @hide - Private call() method to reset to defaults the 'configuration' table */ public static final String CALL_METHOD_LIST_CONFIG = "LIST_config"; /** @hide - Private call() method to register monitor callback for 'configuration' table */ public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG = "REGISTER_MONITOR_CALLBACK_config"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_ACCESS_CALLBACK = "access_callback"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_NAMESPACE_UPDATED_CALLBACK = "namespace_updated_callback"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_NAMESPACE = "namespace"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_CALLING_PACKAGE = "calling_package"; /** * Activity Extra: Limit available options in launched activity based on the given authority. * <p> Loading Loading @@ -14155,6 +14181,37 @@ public final class Settings { } } /** * Register callback for monitoring Config table. * * @param resolver Handle to the content resolver. * @param callback callback to register * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void registerMonitorCallback(@NonNull ContentResolver resolver, @NonNull RemoteCallback callback) { registerMonitorCallbackAsUser(resolver, resolver.getUserId(), callback); } private static void registerMonitorCallbackAsUser( @NonNull ContentResolver resolver, @UserIdInt int userHandle, @NonNull RemoteCallback callback) { try { Bundle arg = new Bundle(); arg.putInt(CALL_METHOD_USER_KEY, userHandle); arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback); IContentProvider cp = sProviderHolder.getProvider(resolver); cp.call(resolver.getPackageName(), resolver.getFeatureId(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't register config monitor callback", e); } } private static String createCompositeName(@NonNull String namespace, @NonNull String name) { Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(name); core/res/AndroidManifest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -2709,6 +2709,11 @@ <permission android:name="android.permission.READ_DEVICE_CONFIG" android:protectionLevel="signature|preinstalled" /> <!-- @SystemApi @hide Allows an application to monitor config settings access. <p>Not for use by third-party applications. --> <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS" android:protectionLevel="signature"/> <!-- @SystemApi @TestApi Allows an application to call {@link android.app.ActivityManager#forceStopPackage}. @hide --> Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +75 −10 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.SELinux; import android.os.ServiceManager; Loading Loading @@ -274,6 +275,9 @@ public class SettingsProvider extends ContentProvider { private final Object mLock = new Object(); @GuardedBy("mLock") private RemoteCallback mConfigMonitorCallback; @GuardedBy("mLock") private SettingsRegistry mSettingsRegistry; Loading Loading @@ -450,8 +454,17 @@ public class SettingsProvider extends ContentProvider { case Settings.CALL_METHOD_LIST_CONFIG: { String prefix = getSettingPrefix(args); return packageValuesForCallResult(getAllConfigFlags(prefix), Bundle result = packageValuesForCallResult(getAllConfigFlags(prefix), isTrackingGeneration(args)); reportDeviceConfigAccess(prefix); return result; } case Settings.CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG: { RemoteCallback callback = args.getParcelable( Settings.CALL_METHOD_MONITOR_CALLBACK_KEY); setMonitorCallback(callback); break; } case Settings.CALL_METHOD_LIST_GLOBAL: { Loading Loading @@ -1052,8 +1065,9 @@ public class SettingsProvider extends ContentProvider { enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG); synchronized (mLock) { return mSettingsRegistry.setSettingsLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM, prefix, keyValues, resolveCallingPackage()); final int key = makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM); return mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues, resolveCallingPackage()); } } Loading Loading @@ -2155,6 +2169,59 @@ public class SettingsProvider extends ContentProvider { return result; } private void setMonitorCallback(RemoteCallback callback) { if (callback == null) { return; } getContext().enforceCallingOrSelfPermission( Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS, "Permission denial: registering for config access requires: " + Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS); synchronized (mLock) { mConfigMonitorCallback = callback; } } private void reportDeviceConfigAccess(@Nullable String prefix) { if (prefix == null) { return; } String callingPackage = getCallingPackage(); String namespace = prefix.replace("/", ""); if (DeviceConfig.getPublicNamespaces().contains(namespace)) { return; } synchronized (mLock) { if (mConfigMonitorCallback != null) { Bundle callbackResult = new Bundle(); callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE, Settings.EXTRA_ACCESS_CALLBACK); callbackResult.putString(Settings.EXTRA_CALLING_PACKAGE, callingPackage); callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace); mConfigMonitorCallback.sendResult(callbackResult); } } } private void reportDeviceConfigUpdate(@Nullable String prefix) { if (prefix == null) { return; } String namespace = prefix.replace("/", ""); if (DeviceConfig.getPublicNamespaces().contains(namespace)) { return; } synchronized (mLock) { if (mConfigMonitorCallback != null) { Bundle callbackResult = new Bundle(); callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE, Settings.EXTRA_NAMESPACE_UPDATED_CALLBACK); callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace); mConfigMonitorCallback.sendResult(callbackResult); } } } private static int getRequestingUserId(Bundle args) { final int callingUserId = UserHandle.getCallingUserId(); return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId) Loading Loading @@ -2715,22 +2782,20 @@ public class SettingsProvider extends ContentProvider { } /** * Set Settings using consumed keyValues, returns true if the keyValues can be set, false * otherwise. * Set Config Settings using consumed keyValues, returns true if the keyValues can be set, * false otherwise. */ public boolean setSettingsLocked(int type, int userId, String prefix, public boolean setConfigSettingsLocked(int key, String prefix, Map<String, String> keyValues, String packageName) { final int key = makeKey(type, userId); SettingsState settingsState = peekSettingsStateLocked(key); if (settingsState != null) { if (SETTINGS_TYPE_CONFIG == type && settingsState.isNewConfigBannedLocked(prefix, keyValues)) { if (settingsState.isNewConfigBannedLocked(prefix, keyValues)) { return false; } List<String> changedSettings = settingsState.setSettingsLocked(prefix, keyValues, packageName); if (!changedSettings.isEmpty()) { reportDeviceConfigUpdate(prefix); notifyForConfigSettingsChangeLocked(key, prefix, changedSettings); } } Loading Loading
api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,7 @@ package android { field public static final String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS"; field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE"; field public static final String MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE = "android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE"; field public static final String MONITOR_DEVICE_CONFIG_ACCESS = "android.permission.MONITOR_DEVICE_CONFIG_ACCESS"; field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE"; field public static final String NETWORK_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE"; field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING"; Loading
core/java/android/provider/DeviceConfig.java +8 −0 Original line number Diff line number Diff line Loading @@ -795,6 +795,14 @@ public final class DeviceConfig { } } /** * Returns list of namespaces that can be read without READ_DEVICE_CONFIG_PERMISSION; * @hide */ public static @NonNull List<String> getPublicNamespaces() { return PUBLIC_NAMESPACES; } /** * Interface for monitoring changes to properties. Implementations will receive callbacks when * properties change, including a {@link Properties} object which contains a single namespace Loading
core/java/android/provider/Settings.java +57 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import android.os.IBinder; import android.os.LocaleList; import android.os.PowerManager.AutoPowerSaveModeTriggers; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; Loading Loading @@ -2160,6 +2161,11 @@ public final class Settings { */ public static final String CALL_METHOD_PREFIX_KEY = "_prefix"; /** * @hide - RemoteCallback monitor callback argument extra to the fast-path call()-based requests */ public static final String CALL_METHOD_MONITOR_CALLBACK_KEY = "_monitor_callback_key"; /** * @hide - String argument extra to the fast-path call()-based requests */ Loading Loading @@ -2218,6 +2224,26 @@ public final class Settings { /** @hide - Private call() method to reset to defaults the 'configuration' table */ public static final String CALL_METHOD_LIST_CONFIG = "LIST_config"; /** @hide - Private call() method to register monitor callback for 'configuration' table */ public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG = "REGISTER_MONITOR_CALLBACK_config"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_ACCESS_CALLBACK = "access_callback"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_NAMESPACE_UPDATED_CALLBACK = "namespace_updated_callback"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_NAMESPACE = "namespace"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_CALLING_PACKAGE = "calling_package"; /** * Activity Extra: Limit available options in launched activity based on the given authority. * <p> Loading Loading @@ -14155,6 +14181,37 @@ public final class Settings { } } /** * Register callback for monitoring Config table. * * @param resolver Handle to the content resolver. * @param callback callback to register * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void registerMonitorCallback(@NonNull ContentResolver resolver, @NonNull RemoteCallback callback) { registerMonitorCallbackAsUser(resolver, resolver.getUserId(), callback); } private static void registerMonitorCallbackAsUser( @NonNull ContentResolver resolver, @UserIdInt int userHandle, @NonNull RemoteCallback callback) { try { Bundle arg = new Bundle(); arg.putInt(CALL_METHOD_USER_KEY, userHandle); arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback); IContentProvider cp = sProviderHolder.getProvider(resolver); cp.call(resolver.getPackageName(), resolver.getFeatureId(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't register config monitor callback", e); } } private static String createCompositeName(@NonNull String namespace, @NonNull String name) { Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(name);
core/res/AndroidManifest.xml +5 −0 Original line number Diff line number Diff line Loading @@ -2709,6 +2709,11 @@ <permission android:name="android.permission.READ_DEVICE_CONFIG" android:protectionLevel="signature|preinstalled" /> <!-- @SystemApi @hide Allows an application to monitor config settings access. <p>Not for use by third-party applications. --> <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS" android:protectionLevel="signature"/> <!-- @SystemApi @TestApi Allows an application to call {@link android.app.ActivityManager#forceStopPackage}. @hide --> Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +75 −10 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.SELinux; import android.os.ServiceManager; Loading Loading @@ -274,6 +275,9 @@ public class SettingsProvider extends ContentProvider { private final Object mLock = new Object(); @GuardedBy("mLock") private RemoteCallback mConfigMonitorCallback; @GuardedBy("mLock") private SettingsRegistry mSettingsRegistry; Loading Loading @@ -450,8 +454,17 @@ public class SettingsProvider extends ContentProvider { case Settings.CALL_METHOD_LIST_CONFIG: { String prefix = getSettingPrefix(args); return packageValuesForCallResult(getAllConfigFlags(prefix), Bundle result = packageValuesForCallResult(getAllConfigFlags(prefix), isTrackingGeneration(args)); reportDeviceConfigAccess(prefix); return result; } case Settings.CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG: { RemoteCallback callback = args.getParcelable( Settings.CALL_METHOD_MONITOR_CALLBACK_KEY); setMonitorCallback(callback); break; } case Settings.CALL_METHOD_LIST_GLOBAL: { Loading Loading @@ -1052,8 +1065,9 @@ public class SettingsProvider extends ContentProvider { enforceWritePermission(Manifest.permission.WRITE_DEVICE_CONFIG); synchronized (mLock) { return mSettingsRegistry.setSettingsLocked(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM, prefix, keyValues, resolveCallingPackage()); final int key = makeKey(SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM); return mSettingsRegistry.setConfigSettingsLocked(key, prefix, keyValues, resolveCallingPackage()); } } Loading Loading @@ -2155,6 +2169,59 @@ public class SettingsProvider extends ContentProvider { return result; } private void setMonitorCallback(RemoteCallback callback) { if (callback == null) { return; } getContext().enforceCallingOrSelfPermission( Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS, "Permission denial: registering for config access requires: " + Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS); synchronized (mLock) { mConfigMonitorCallback = callback; } } private void reportDeviceConfigAccess(@Nullable String prefix) { if (prefix == null) { return; } String callingPackage = getCallingPackage(); String namespace = prefix.replace("/", ""); if (DeviceConfig.getPublicNamespaces().contains(namespace)) { return; } synchronized (mLock) { if (mConfigMonitorCallback != null) { Bundle callbackResult = new Bundle(); callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE, Settings.EXTRA_ACCESS_CALLBACK); callbackResult.putString(Settings.EXTRA_CALLING_PACKAGE, callingPackage); callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace); mConfigMonitorCallback.sendResult(callbackResult); } } } private void reportDeviceConfigUpdate(@Nullable String prefix) { if (prefix == null) { return; } String namespace = prefix.replace("/", ""); if (DeviceConfig.getPublicNamespaces().contains(namespace)) { return; } synchronized (mLock) { if (mConfigMonitorCallback != null) { Bundle callbackResult = new Bundle(); callbackResult.putString(Settings.EXTRA_MONITOR_CALLBACK_TYPE, Settings.EXTRA_NAMESPACE_UPDATED_CALLBACK); callbackResult.putString(Settings.EXTRA_NAMESPACE, namespace); mConfigMonitorCallback.sendResult(callbackResult); } } } private static int getRequestingUserId(Bundle args) { final int callingUserId = UserHandle.getCallingUserId(); return (args != null) ? args.getInt(Settings.CALL_METHOD_USER_KEY, callingUserId) Loading Loading @@ -2715,22 +2782,20 @@ public class SettingsProvider extends ContentProvider { } /** * Set Settings using consumed keyValues, returns true if the keyValues can be set, false * otherwise. * Set Config Settings using consumed keyValues, returns true if the keyValues can be set, * false otherwise. */ public boolean setSettingsLocked(int type, int userId, String prefix, public boolean setConfigSettingsLocked(int key, String prefix, Map<String, String> keyValues, String packageName) { final int key = makeKey(type, userId); SettingsState settingsState = peekSettingsStateLocked(key); if (settingsState != null) { if (SETTINGS_TYPE_CONFIG == type && settingsState.isNewConfigBannedLocked(prefix, keyValues)) { if (settingsState.isNewConfigBannedLocked(prefix, keyValues)) { return false; } List<String> changedSettings = settingsState.setSettingsLocked(prefix, keyValues, packageName); if (!changedSettings.isEmpty()) { reportDeviceConfigUpdate(prefix); notifyForConfigSettingsChangeLocked(key, prefix, changedSettings); } } Loading