Loading core/api/module-lib-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -430,6 +430,7 @@ package android.provider { } public static final class Settings.Config extends android.provider.Settings.NameValueTable { method @RequiresPermission(android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void clearMonitorCallback(@NonNull android.content.ContentResolver); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean deleteString(@NonNull String, @NonNull String); method @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static java.util.Map<java.lang.String,java.lang.String> getStrings(@NonNull String, @NonNull java.util.List<java.lang.String>); Loading @@ -437,6 +438,7 @@ package android.provider { method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean putString(@NonNull String, @NonNull String, @Nullable String, boolean); method public static void registerContentObserver(@Nullable String, boolean, @NonNull android.database.ContentObserver); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String); method @RequiresPermission(android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void setMonitorCallback(@NonNull android.content.ContentResolver, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.MonitorCallback); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setStrings(@NonNull String, @NonNull java.util.Map<java.lang.String,java.lang.String>) throws android.provider.DeviceConfig.BadConfigException; method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void setSyncDisabledMode(int); method public static void unregisterContentObserver(@NonNull android.database.ContentObserver); Loading core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,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"; core/java/android/provider/Settings.java +72 −9 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.provider; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; Loading Loading @@ -87,6 +88,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.MemoryIntArray; import android.util.Slog; import android.view.Display; import android.view.MotionEvent; import android.view.ViewConfiguration; Loading @@ -112,6 +114,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; /** * The Settings provider contains global system-level device preferences. */ Loading Loading @@ -2719,6 +2723,10 @@ public final class Settings { public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG = "REGISTER_MONITOR_CALLBACK_config"; /** @hide - Private call() method to unregister monitor callback for 'configuration' table */ public static final String CALL_METHOD_UNREGISTER_MONITOR_CALLBACK_CONFIG = "UNREGISTER_MONITOR_CALLBACK_config"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type"; Loading Loading @@ -18370,16 +18378,41 @@ public final class Settings { } /** * Register callback for monitoring Config table. * Setter callback for monitoring Config table. * * @param callback callback to register * @param executor the {@link Executor} on which to invoke the callback * @param callback callback to set * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void registerMonitorCallback(@NonNull ContentResolver resolver, @NonNull RemoteCallback callback) { registerMonitorCallbackAsUser(resolver, resolver.getUserId(), callback); public static void setMonitorCallback( @NonNull ContentResolver resolver, @NonNull @CallbackExecutor Executor executor, @NonNull DeviceConfig.MonitorCallback callback) { setMonitorCallbackAsUser(executor, resolver, resolver.getUserId(), callback); } /** * Clear callback for monitoring Config table. * this may only be used to clear callback function registered by * {@link Config#setMonitorCallback} * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void clearMonitorCallback(@NonNull ContentResolver resolver) { try { Bundle arg = new Bundle(); arg.putInt(CALL_METHOD_USER_KEY, resolver.getUserId()); IContentProvider cp = sProviderHolder.getProvider(resolver); cp.call(resolver.getAttributionSource(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_UNREGISTER_MONITOR_CALLBACK_CONFIG, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't clear config monitor callback", e); } } Loading Loading @@ -18446,19 +18479,23 @@ public final class Settings { } } private static void registerMonitorCallbackAsUser( private static void setMonitorCallbackAsUser( @NonNull @CallbackExecutor Executor executor, @NonNull ContentResolver resolver, @UserIdInt int userHandle, @NonNull RemoteCallback callback) { @NonNull DeviceConfig.MonitorCallback callback) { try { Bundle arg = new Bundle(); arg.putInt(CALL_METHOD_USER_KEY, userHandle); arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback); arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, new RemoteCallback(result -> { handleMonitorCallback(result, executor, callback); })); IContentProvider cp = sProviderHolder.getProvider(resolver); cp.call(resolver.getAttributionSource(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't register config monitor callback", e); Log.w(TAG, "Can't set config monitor callback", e); } } Loading @@ -18468,6 +18505,32 @@ public final class Settings { sNameValueCache.clearGenerationTrackerForTest(); } private static void handleMonitorCallback( Bundle result, @NonNull @CallbackExecutor Executor executor, DeviceConfig.MonitorCallback monitorCallback) { String callbackType = result.getString(EXTRA_MONITOR_CALLBACK_TYPE, ""); switch (callbackType) { case EXTRA_NAMESPACE_UPDATED_CALLBACK: String updatedNamespace = result.getString(EXTRA_NAMESPACE); if (updatedNamespace != null) { executor.execute(() -> monitorCallback.onNamespaceUpdate(updatedNamespace)); } break; case EXTRA_ACCESS_CALLBACK: String callingPackage = result.getString(EXTRA_CALLING_PACKAGE, null); String namespace = result.getString(EXTRA_NAMESPACE, null); if (namespace != null && callingPackage != null) { executor.execute(() -> monitorCallback.onDeviceConfigAccess(callingPackage, namespace)); } break; default: Slog.w(TAG, "Unrecognized DeviceConfig callback"); break; } } private static String createCompositeName(@NonNull String namespace, @NonNull String name) { Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(name); core/res/AndroidManifest.xml +1 −1 Original line number Diff line number Diff line Loading @@ -3632,7 +3632,7 @@ <permission android:name="android.permission.SET_APP_SPECIFIC_LOCALECONFIG" android:protectionLevel="signature" /> <!-- @hide Allows an application to monitor {@link android.provider.Settings.Config} access. <!-- @SystemApi @hide Allows an application to monitor {@link android.provider.Settings.Config} access. <p>Not for use by third-party applications. --> <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS" android:protectionLevel="signature"/> Loading packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +15 −0 Original line number Diff line number Diff line Loading @@ -564,6 +564,11 @@ public class SettingsProvider extends ContentProvider { break; } case Settings.CALL_METHOD_UNREGISTER_MONITOR_CALLBACK_CONFIG: { clearMonitorCallback(); break; } case Settings.CALL_METHOD_LIST_GLOBAL: { Bundle result = new Bundle(); result.putStringArrayList(RESULT_SETTINGS_LIST, Loading Loading @@ -2352,6 +2357,16 @@ public class SettingsProvider extends ContentProvider { } } private void clearMonitorCallback() { getContext().enforceCallingOrSelfPermission( Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS, "Permission denial: registering for config access requires: " + Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS); synchronized (mLock) { mConfigMonitorCallback = null; } } private void reportDeviceConfigAccess(@Nullable String prefix) { if (prefix == null) { return; Loading Loading
core/api/module-lib-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -430,6 +430,7 @@ package android.provider { } public static final class Settings.Config extends android.provider.Settings.NameValueTable { method @RequiresPermission(android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void clearMonitorCallback(@NonNull android.content.ContentResolver); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean deleteString(@NonNull String, @NonNull String); method @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static String getString(@NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public static java.util.Map<java.lang.String,java.lang.String> getStrings(@NonNull String, @NonNull java.util.List<java.lang.String>); Loading @@ -437,6 +438,7 @@ package android.provider { method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean putString(@NonNull String, @NonNull String, @Nullable String, boolean); method public static void registerContentObserver(@Nullable String, boolean, @NonNull android.database.ContentObserver); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void resetToDefaults(int, @Nullable String); method @RequiresPermission(android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void setMonitorCallback(@NonNull android.content.ContentResolver, @NonNull java.util.concurrent.Executor, @NonNull android.provider.DeviceConfig.MonitorCallback); method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static boolean setStrings(@NonNull String, @NonNull java.util.Map<java.lang.String,java.lang.String>) throws android.provider.DeviceConfig.BadConfigException; method @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void setSyncDisabledMode(int); method public static void unregisterContentObserver(@NonNull android.database.ContentObserver); Loading
core/api/system-current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,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";
core/java/android/provider/Settings.java +72 −9 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.provider; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; Loading Loading @@ -87,6 +88,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.MemoryIntArray; import android.util.Slog; import android.view.Display; import android.view.MotionEvent; import android.view.ViewConfiguration; Loading @@ -112,6 +114,8 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; /** * The Settings provider contains global system-level device preferences. */ Loading Loading @@ -2719,6 +2723,10 @@ public final class Settings { public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG = "REGISTER_MONITOR_CALLBACK_config"; /** @hide - Private call() method to unregister monitor callback for 'configuration' table */ public static final String CALL_METHOD_UNREGISTER_MONITOR_CALLBACK_CONFIG = "UNREGISTER_MONITOR_CALLBACK_config"; /** @hide - String argument extra to the config monitor callback */ public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type"; Loading Loading @@ -18370,16 +18378,41 @@ public final class Settings { } /** * Register callback for monitoring Config table. * Setter callback for monitoring Config table. * * @param callback callback to register * @param executor the {@link Executor} on which to invoke the callback * @param callback callback to set * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void registerMonitorCallback(@NonNull ContentResolver resolver, @NonNull RemoteCallback callback) { registerMonitorCallbackAsUser(resolver, resolver.getUserId(), callback); public static void setMonitorCallback( @NonNull ContentResolver resolver, @NonNull @CallbackExecutor Executor executor, @NonNull DeviceConfig.MonitorCallback callback) { setMonitorCallbackAsUser(executor, resolver, resolver.getUserId(), callback); } /** * Clear callback for monitoring Config table. * this may only be used to clear callback function registered by * {@link Config#setMonitorCallback} * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS) public static void clearMonitorCallback(@NonNull ContentResolver resolver) { try { Bundle arg = new Bundle(); arg.putInt(CALL_METHOD_USER_KEY, resolver.getUserId()); IContentProvider cp = sProviderHolder.getProvider(resolver); cp.call(resolver.getAttributionSource(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_UNREGISTER_MONITOR_CALLBACK_CONFIG, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't clear config monitor callback", e); } } Loading Loading @@ -18446,19 +18479,23 @@ public final class Settings { } } private static void registerMonitorCallbackAsUser( private static void setMonitorCallbackAsUser( @NonNull @CallbackExecutor Executor executor, @NonNull ContentResolver resolver, @UserIdInt int userHandle, @NonNull RemoteCallback callback) { @NonNull DeviceConfig.MonitorCallback callback) { try { Bundle arg = new Bundle(); arg.putInt(CALL_METHOD_USER_KEY, userHandle); arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, callback); arg.putParcelable(CALL_METHOD_MONITOR_CALLBACK_KEY, new RemoteCallback(result -> { handleMonitorCallback(result, executor, callback); })); IContentProvider cp = sProviderHolder.getProvider(resolver); cp.call(resolver.getAttributionSource(), sProviderHolder.mUri.getAuthority(), CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg); } catch (RemoteException e) { Log.w(TAG, "Can't register config monitor callback", e); Log.w(TAG, "Can't set config monitor callback", e); } } Loading @@ -18468,6 +18505,32 @@ public final class Settings { sNameValueCache.clearGenerationTrackerForTest(); } private static void handleMonitorCallback( Bundle result, @NonNull @CallbackExecutor Executor executor, DeviceConfig.MonitorCallback monitorCallback) { String callbackType = result.getString(EXTRA_MONITOR_CALLBACK_TYPE, ""); switch (callbackType) { case EXTRA_NAMESPACE_UPDATED_CALLBACK: String updatedNamespace = result.getString(EXTRA_NAMESPACE); if (updatedNamespace != null) { executor.execute(() -> monitorCallback.onNamespaceUpdate(updatedNamespace)); } break; case EXTRA_ACCESS_CALLBACK: String callingPackage = result.getString(EXTRA_CALLING_PACKAGE, null); String namespace = result.getString(EXTRA_NAMESPACE, null); if (namespace != null && callingPackage != null) { executor.execute(() -> monitorCallback.onDeviceConfigAccess(callingPackage, namespace)); } break; default: Slog.w(TAG, "Unrecognized DeviceConfig callback"); break; } } private static String createCompositeName(@NonNull String namespace, @NonNull String name) { Preconditions.checkNotNull(namespace); Preconditions.checkNotNull(name);
core/res/AndroidManifest.xml +1 −1 Original line number Diff line number Diff line Loading @@ -3632,7 +3632,7 @@ <permission android:name="android.permission.SET_APP_SPECIFIC_LOCALECONFIG" android:protectionLevel="signature" /> <!-- @hide Allows an application to monitor {@link android.provider.Settings.Config} access. <!-- @SystemApi @hide Allows an application to monitor {@link android.provider.Settings.Config} access. <p>Not for use by third-party applications. --> <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS" android:protectionLevel="signature"/> Loading
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +15 −0 Original line number Diff line number Diff line Loading @@ -564,6 +564,11 @@ public class SettingsProvider extends ContentProvider { break; } case Settings.CALL_METHOD_UNREGISTER_MONITOR_CALLBACK_CONFIG: { clearMonitorCallback(); break; } case Settings.CALL_METHOD_LIST_GLOBAL: { Bundle result = new Bundle(); result.putStringArrayList(RESULT_SETTINGS_LIST, Loading Loading @@ -2352,6 +2357,16 @@ public class SettingsProvider extends ContentProvider { } } private void clearMonitorCallback() { getContext().enforceCallingOrSelfPermission( Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS, "Permission denial: registering for config access requires: " + Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS); synchronized (mLock) { mConfigMonitorCallback = null; } } private void reportDeviceConfigAccess(@Nullable String prefix) { if (prefix == null) { return; Loading