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

Commit 9f47ce09 authored by Neil Fuller's avatar Neil Fuller Committed by Android (Google) Code Review
Browse files

Merge "Add device_config cmds for disabling syncs" into sc-dev

parents 629d1f3e ad3d45a6
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.net.Uri;
import android.provider.Settings.Config.SyncDisabledMode;
import android.provider.Settings.ResetMode;
import android.util.ArrayMap;
import android.util.Log;
@@ -845,6 +846,37 @@ public final class DeviceConfig {
        Settings.Config.resetToDefaults(contentResolver, resetMode, namespace);
    }

    /**
     * Disables or re-enables bulk modifications ({@link #setProperties(Properties)}) to device
     * config values. This is intended for use during tests to prevent a sync operation clearing
     * config values, which could influence the outcome of the tests, i.e. by changing behavior.
     *
     * @param syncDisabledMode the mode to use, see {@link Settings.Config#SYNC_DISABLED_MODE_NONE},
     *     {@link Settings.Config#SYNC_DISABLED_MODE_PERSISTENT} and {@link
     *     Settings.Config#SYNC_DISABLED_MODE_UNTIL_REBOOT}
     *
     * @see #isSyncDisabled()
     * @hide
     */
    @RequiresPermission(WRITE_DEVICE_CONFIG)
    public static void setSyncDisabled(@SyncDisabledMode int syncDisabledMode) {
        ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
        Settings.Config.setSyncDisabled(contentResolver, syncDisabledMode);
    }

    /**
     * Returns the current state of sync disabling, {@code true} when disabled, {@code false}
     * otherwise.
     *
     * @see #setSyncDisabled(int)
     * @hide
     */
    @RequiresPermission(WRITE_DEVICE_CONFIG)
    public static boolean isSyncDisabled() {
        ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
        return Settings.Config.isSyncDisabled(contentResolver);
    }

    /**
     * Add a listener for property changes.
     * <p>
+146 −11
Original line number Diff line number Diff line
@@ -267,8 +267,40 @@ public final class Settings {
    /** @hide */
    public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
    /**
     * The return values for {@link Settings.Config#set}
     * @hide
     */
    @IntDef(prefix = "SET_ALL_RESULT_",
            value = { SET_ALL_RESULT_FAILURE, SET_ALL_RESULT_SUCCESS, SET_ALL_RESULT_DISABLED })
    @Retention(RetentionPolicy.SOURCE)
    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
    public @interface SetAllResult {}
    /**
     * A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates failure.
     * @hide
     */
    public static final int SET_ALL_RESULT_FAILURE = 0;
    /**
     * A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates success.
     * @hide
     */
    public static final int SET_ALL_RESULT_SUCCESS = 1;
    /**
     * A return value for {@link #KEY_CONFIG_SET_ALL_RETURN}, indicates a set all is disabled.
     * @hide
     */
    public static final int SET_ALL_RESULT_DISABLED = 2;
    /** @hide */
    public static final String KEY_CONFIG_SET_ALL_RETURN = "config_set_all_return";
    /** @hide */
    public static final String KEY_CONFIG_SET_RETURN = "config_set_return";
    public static final String KEY_CONFIG_IS_SYNC_DISABLED_RETURN =
            "config_is_sync_disabled_return";
    /**
     * An int extra specifying a subscription ID.
@@ -2323,6 +2355,11 @@ public final class Settings {
     */
    public static final String CALL_METHOD_PREFIX_KEY = "_prefix";
    /**
     * @hide - String argument extra to the fast-path call()-based requests
     */
    public static final String CALL_METHOD_SYNC_DISABLED_MODE_KEY = "_disabled_mode";
    /**
     * @hide - RemoteCallback monitor callback argument extra to the fast-path call()-based requests
     */
@@ -2386,6 +2423,15 @@ 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 disable / re-enable syncs to the 'configuration' table */
    public static final String CALL_METHOD_SET_SYNC_DISABLED_CONFIG = "SET_SYNC_DISABLED_config";
    /**
     * @hide - Private call() method to return whether syncs are disabled for the 'configuration'
     * table
     */
    public static final String CALL_METHOD_IS_SYNC_DISABLED_CONFIG = "IS_SYNC_DISABLED_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";
@@ -2762,11 +2808,11 @@ public final class Settings {
            return true;
        }
        public boolean setStringsForPrefix(ContentResolver cr, String prefix,
        public @SetAllResult int setStringsForPrefix(ContentResolver cr, String prefix,
                HashMap<String, String> keyValues) {
            if (mCallSetAllCommand == null) {
                // This NameValueCache does not support atomically setting multiple flags
                return false;
                return SET_ALL_RESULT_FAILURE;
            }
            try {
                Bundle args = new Bundle();
@@ -2776,10 +2822,10 @@ public final class Settings {
                Bundle bundle = cp.call(cr.getAttributionSource(),
                        mProviderHolder.mUri.getAuthority(),
                        mCallSetAllCommand, null, args);
                return bundle.getBoolean(KEY_CONFIG_SET_RETURN);
                return bundle.getInt(KEY_CONFIG_SET_ALL_RETURN);
            } catch (RemoteException e) {
                // Not supported by the remote side
                return false;
                return SET_ALL_RESULT_FAILURE;
            }
        }
@@ -14199,6 +14245,15 @@ public final class Settings {
        public static final String ARE_USER_DISABLED_HDR_FORMATS_ALLOWED =
                "are_user_disabled_hdr_formats_allowed";
        /**
         * Whether or not syncs (bulk set operations) for {@link DeviceConfig} are disabled
         * currently. The value is boolean (1 or 0). The value '1' means that {@link
         * DeviceConfig#setProperties(DeviceConfig.Properties)} will return {@code false}.
         *
         * @hide
         */
        public static final String DEVICE_CONFIG_SYNC_DISABLED = "device_config_sync_disabled";
        /** @hide */ public static String zenModeToString(int mode) {
            if (mode == ZEN_MODE_IMPORTANT_INTERRUPTIONS) return "ZEN_MODE_IMPORTANT_INTERRUPTIONS";
            if (mode == ZEN_MODE_ALARMS) return "ZEN_MODE_ALARMS";
@@ -16033,6 +16088,39 @@ public final class Settings {
     * @hide
     */
    public static final class Config extends NameValueTable {
        /**
         * The modes that can be used when disabling syncs to the 'config' settings.
         * @hide
         */
        @IntDef(prefix = "DISABLE_SYNC_MODE_",
                value = { SYNC_DISABLED_MODE_NONE, SYNC_DISABLED_MODE_PERSISTENT,
                        SYNC_DISABLED_MODE_UNTIL_REBOOT })
        @Retention(RetentionPolicy.SOURCE)
        @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
        public @interface SyncDisabledMode {}
        /**
         * Sync is not not disabled.
         *
         * @hide
         */
        public static final int SYNC_DISABLED_MODE_NONE = 0;
        /**
         * Disabling of Config bulk update / syncing is persistent, i.e. it survives a device
         * reboot.
         * @hide
         */
        public static final int SYNC_DISABLED_MODE_PERSISTENT = 1;
        /**
         * Disabling of Config bulk update / syncing is not persistent, i.e. it will not survive a
         * device reboot.
         * @hide
         */
        public static final int SYNC_DISABLED_MODE_UNTIL_REBOOT = 2;
        private static final ContentProviderHolder sProviderHolder =
                new ContentProviderHolder(DeviceConfig.CONTENT_URI);
@@ -16125,7 +16213,7 @@ public final class Settings {
         * @param resolver to access the database with.
         * @param namespace to which the names should be set.
         * @param keyValues map of key names (without the prefix) to values.
         * @return
         * @return true if the name/value pairs were set, false if setting was blocked
         *
         * @hide
         */
@@ -16138,13 +16226,16 @@ public final class Settings {
                compositeKeyValueMap.put(
                        createCompositeName(namespace, entry.getKey()), entry.getValue());
            }
            int result = sNameValueCache.setStringsForPrefix(
                    resolver, createPrefix(namespace), compositeKeyValueMap);
            if (result == SET_ALL_RESULT_SUCCESS) {
                return true;
            } else if (result == SET_ALL_RESULT_DISABLED) {
                return false;
            }
            // If can't set given configuration that means it's bad
            if (!sNameValueCache.setStringsForPrefix(resolver, createPrefix(namespace),
                    compositeKeyValueMap)) {
            throw new DeviceConfig.BadConfigException();
        }
            return true;
        }
        /**
         * Reset the values to their defaults.
@@ -16178,6 +16269,50 @@ public final class Settings {
            }
        }
        /**
         * Bridge method between {@link DeviceConfig#setSyncDisabled(int)} and the
         * {@link com.android.providers.settings.SettingsProvider} implementation.
         *
         * @hide
         */
        @SuppressLint("AndroidFrameworkRequiresPermission")
        @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
        static void setSyncDisabled(
                @NonNull ContentResolver resolver, @SyncDisabledMode int disableSyncMode) {
            try {
                Bundle args = new Bundle();
                args.putInt(CALL_METHOD_SYNC_DISABLED_MODE_KEY, disableSyncMode);
                IContentProvider cp = sProviderHolder.getProvider(resolver);
                cp.call(resolver.getAttributionSource(),
                        sProviderHolder.mUri.getAuthority(), CALL_METHOD_SET_SYNC_DISABLED_CONFIG,
                        null, args);
            } catch (RemoteException e) {
                Log.w(TAG, "Can't set sync disabled " + DeviceConfig.CONTENT_URI, e);
            }
        }
        /**
         * Bridge method between {@link DeviceConfig#isSyncDisabled()} and the
         * {@link com.android.providers.settings.SettingsProvider} implementation.
         *
         * @hide
         */
        @SuppressLint("AndroidFrameworkRequiresPermission")
        @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
        static boolean isSyncDisabled(@NonNull ContentResolver resolver) {
            try {
                Bundle args = Bundle.EMPTY;
                IContentProvider cp = sProviderHolder.getProvider(resolver);
                Bundle bundle = cp.call(resolver.getAttributionSource(),
                        sProviderHolder.mUri.getAuthority(), CALL_METHOD_IS_SYNC_DISABLED_CONFIG,
                        null, args);
                return bundle.getBoolean(KEY_CONFIG_IS_SYNC_DISABLED_RETURN);
            } catch (RemoteException e) {
                Log.w(TAG, "Can't query sync disabled " + DeviceConfig.CONTENT_URI, e);
            }
            return false;
        }
        /**
         * Register callback for monitoring Config table.
         *
+56 −0
Original line number Diff line number Diff line
@@ -762,6 +762,62 @@ public class DeviceConfigTest {
//        }
//    }

    @Test
    public void syncDisabling() throws Exception {
        Properties properties1 = new Properties.Builder(NAMESPACE)
                .setString(KEY, VALUE)
                .build();
        Properties properties2 = new Properties.Builder(NAMESPACE)
                .setString(KEY, VALUE2)
                .build();

        try {
            // Ensure the device starts in a known state.
            DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);

            // Assert starting state.
            assertThat(DeviceConfig.isSyncDisabled()).isFalse();
            assertThat(DeviceConfig.setProperties(properties1)).isTrue();
            assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
                    .isEqualTo(VALUE);

            // Test disabled (persistent). Persistence is not actually tested, that would require
            // a host test.
            DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_PERSISTENT);
            assertThat(DeviceConfig.isSyncDisabled()).isTrue();
            assertThat(DeviceConfig.setProperties(properties2)).isFalse();
            assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
                    .isEqualTo(VALUE);

            // Return to not disabled.
            DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
            assertThat(DeviceConfig.isSyncDisabled()).isFalse();
            assertThat(DeviceConfig.setProperties(properties2)).isTrue();
            assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
                    .isEqualTo(VALUE2);

            // Test disabled (persistent). Absence of persistence is not actually tested, that would
            // require a host test.
            DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_UNTIL_REBOOT);
            assertThat(DeviceConfig.isSyncDisabled()).isTrue();
            assertThat(DeviceConfig.setProperties(properties1)).isFalse();
            assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
                    .isEqualTo(VALUE2);

            // Return to not disabled.
            DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);
            assertThat(DeviceConfig.isSyncDisabled()).isFalse();
            assertThat(DeviceConfig.setProperties(properties1)).isTrue();
            assertThat(DeviceConfig.getProperties(NAMESPACE, KEY).getString(KEY, DEFAULT_VALUE))
                    .isEqualTo(VALUE);
        } finally {
            // Try to return to the default sync disabled state in case of failure.
            DeviceConfig.setSyncDisabled(Settings.Config.SYNC_DISABLED_MODE_NONE);

            // NAMESPACE will be cleared by cleanUp()
        }
    }

    private static boolean deleteViaContentProvider(String namespace, String key) {
        ContentResolver resolver = InstrumentationRegistry.getContext().getContentResolver();
        String compositeName = namespace + "/" + key;
+2 −1
Original line number Diff line number Diff line
@@ -96,7 +96,8 @@ public class NameValueCacheTest {
                    mCacheGenerationStore.set(0, ++mCurrentGeneration);

                    Bundle result = new Bundle();
                    result.putBoolean(Settings.KEY_CONFIG_SET_RETURN, true);
                    result.putInt(Settings.KEY_CONFIG_SET_ALL_RETURN,
                            Settings.SET_ALL_RESULT_SUCCESS);
                    return result;
                });

+2 −1
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ public class GlobalSettings {
        Settings.Global.CUSTOM_BUGREPORT_HANDLER_USER,
        Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
        Settings.Global.USER_DISABLED_HDR_FORMATS,
        Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED
        Settings.Global.ARE_USER_DISABLED_HDR_FORMATS_ALLOWED,
        Settings.Global.DEVICE_CONFIG_SYNC_DISABLED,
    };
}
Loading