Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit af9b4e45 authored by Hassan Ali's avatar Hassan Ali
Browse files

Expose set/clear monitor callback

Exposing set/clear monitor callback as part of moving rescue party calls to use device config apis instead
of depending on settings.config.

To follow API guildlines: add executor parameter, clear monitor
callback, pass monitorCallback interface instead of passing generic
remote callback function

Test: atest CtsProviderTestCases:android.provider.cts.settings.Settings_ConfigTest#testRegisterMonitorCallback, atest CtsDeviceConfigTestCases:android.deviceconfig.cts.DeviceConfigApiTests#testRegisterMonitorCallback
Bug: 261723248
Change-Id: I40e567a9eb6a4fe3e1d167b1ece909a859f6c2df
parent dc01f138
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -430,6 +430,7 @@ package android.provider {
  }
  }


  public static final class Settings.Config extends android.provider.Settings.NameValueTable {
  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 @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 @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>);
    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>);
@@ -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 @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 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.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 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 @RequiresPermission(android.Manifest.permission.WRITE_DEVICE_CONFIG) public static void setSyncDisabledMode(int);
    method public static void unregisterContentObserver(@NonNull android.database.ContentObserver);
    method public static void unregisterContentObserver(@NonNull android.database.ContentObserver);
+1 −0
Original line number Original line Diff line number Diff line
@@ -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_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_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 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 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_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE";
    field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING";
    field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING";
+72 −9
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package android.provider;
package android.provider;
import android.Manifest;
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.NonNull;
@@ -87,6 +88,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.Log;
import android.util.Log;
import android.util.MemoryIntArray;
import android.util.MemoryIntArray;
import android.util.Slog;
import android.view.Display;
import android.view.Display;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewConfiguration;
@@ -112,6 +114,8 @@ import java.util.List;
import java.util.Map;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.Executor;
/**
/**
 * The Settings provider contains global system-level device preferences.
 * The Settings provider contains global system-level device preferences.
 */
 */
@@ -2719,6 +2723,10 @@ public final class Settings {
    public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG =
    public static final String CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG =
            "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 */
    /** @hide - String argument extra to the config monitor callback */
    public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type";
    public static final String EXTRA_MONITOR_CALLBACK_TYPE = "monitor_callback_type";
@@ -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
         * @hide
         */
         */
        @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
        @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS)
        @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS)
        public static void registerMonitorCallback(@NonNull ContentResolver resolver,
        public static void setMonitorCallback(
                @NonNull RemoteCallback callback) {
                @NonNull ContentResolver resolver,
            registerMonitorCallbackAsUser(resolver, resolver.getUserId(), callback);
                @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);
            }
        }
        }
@@ -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 ContentResolver resolver, @UserIdInt int userHandle,
                @NonNull RemoteCallback callback) {
                @NonNull DeviceConfig.MonitorCallback callback) {
            try {
            try {
                Bundle arg = new Bundle();
                Bundle arg = new Bundle();
                arg.putInt(CALL_METHOD_USER_KEY, userHandle);
                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);
                IContentProvider cp = sProviderHolder.getProvider(resolver);
                cp.call(resolver.getAttributionSource(),
                cp.call(resolver.getAttributionSource(),
                        sProviderHolder.mUri.getAuthority(),
                        sProviderHolder.mUri.getAuthority(),
                        CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg);
                        CALL_METHOD_REGISTER_MONITOR_CALLBACK_CONFIG, null, arg);
            } catch (RemoteException e) {
            } catch (RemoteException e) {
                Log.w(TAG, "Can't register config monitor callback", e);
                Log.w(TAG, "Can't set config monitor callback", e);
            }
            }
        }
        }
@@ -18468,6 +18505,32 @@ public final class Settings {
            sNameValueCache.clearGenerationTrackerForTest();
            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) {
        private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
            Preconditions.checkNotNull(namespace);
            Preconditions.checkNotNull(namespace);
            Preconditions.checkNotNull(name);
            Preconditions.checkNotNull(name);
+1 −1
Original line number Original line Diff line number Diff line
@@ -3632,7 +3632,7 @@
    <permission android:name="android.permission.SET_APP_SPECIFIC_LOCALECONFIG"
    <permission android:name="android.permission.SET_APP_SPECIFIC_LOCALECONFIG"
        android:protectionLevel="signature" />
        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. -->
    <p>Not for use by third-party applications. -->
    <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
    <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
        android:protectionLevel="signature"/>
        android:protectionLevel="signature"/>
+15 −0
Original line number Original line Diff line number Diff line
@@ -564,6 +564,11 @@ public class SettingsProvider extends ContentProvider {
                break;
                break;
            }
            }


            case Settings.CALL_METHOD_UNREGISTER_MONITOR_CALLBACK_CONFIG: {
                clearMonitorCallback();
                break;
            }

            case Settings.CALL_METHOD_LIST_GLOBAL: {
            case Settings.CALL_METHOD_LIST_GLOBAL: {
                Bundle result = new Bundle();
                Bundle result = new Bundle();
                result.putStringArrayList(RESULT_SETTINGS_LIST,
                result.putStringArrayList(RESULT_SETTINGS_LIST,
@@ -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) {
    private void reportDeviceConfigAccess(@Nullable String prefix) {
        if (prefix == null) {
        if (prefix == null) {
            return;
            return;
Loading