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

Commit 02e7db9b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Updates to Settings.Config and SettingsProvider for the DeviceConfig API surface."

parents 04db03d0 c1323dc7
Loading
Loading
Loading
Loading
+17 −23
Original line number Diff line number Diff line
@@ -13933,13 +13933,6 @@ public final class Settings {
        /**
         * Store a name/value pair into the database.
         * <p>
         * The method takes an optional tag to associate with the setting which can be used to clear
         * only settings made by your package and associated with this tag by passing the tag to
         * {@link #resetToDefaults(ContentResolver, String)}. The value of this setting can be
         * overridden by future calls to this or other put methods, and the tag provided in those
         * calls, which may be null, will override the tag provided in this call. Any call to a put
         * method which does not accept a tag will effectively set the tag to null.
         * </p><p>
         * Also the method takes an argument whether to make the value the default for this setting.
         * If the system already specified a default value, then the one passed in here will
         * <strong>not</strong> be set as the default.
@@ -13948,46 +13941,47 @@ public final class Settings {
         * @param resolver to access the database with.
         * @param name to store.
         * @param value to associate with the name.
         * @param tag to associated with the setting.
         * @param makeDefault whether to make the value the default one.
         * @return true if the value was set, false on database errors.
         *
         * @see #resetToDefaults(ContentResolver, String)
         * @see #resetToDefaults(ContentResolver, int, String)
         *
         * @hide
         */
        // TODO(b/117663715): require a new write permission restricted to a single source
        @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
        static boolean putString(@NonNull ContentResolver resolver,
                @NonNull String name, @Nullable String value, @Nullable String tag,
                boolean makeDefault) {
            return sNameValueCache.putStringForUser(resolver, name, value, tag, makeDefault,
        static boolean putString(@NonNull ContentResolver resolver, @NonNull String name,
                @Nullable String value, boolean makeDefault) {
            return sNameValueCache.putStringForUser(resolver, name, value, null, makeDefault,
                    resolver.getUserId());
        }
        /**
         * Reset the settings to their defaults. This would reset <strong>only</strong> settings set
         * by the caller's package. Passing in the optional tag will reset only settings changed by
         * your package and associated with this tag.
         * Reset the values to their defaults.
         * <p>
         * The method accepts an optional prefix parameter. If provided, only pairs with a name that
         * starts with the exact prefix will be reset. Otherwise all will be reset.
         *
         * @param resolver Handle to the content resolver.
         * @param tag Optional tag which should be associated with the settings to reset.
         * @param resetMode The reset mode to use.
         * @param prefix Optionally, to limit which which pairs are reset.
         *
         * @see #putString(ContentResolver, String, String, String, boolean)
         * @see #putString(ContentResolver, String, String, boolean)
         *
         * @hide
         */
        // TODO(b/117663715): require a new write permission restricted to a single source
        @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
        static void resetToDefaults(@NonNull ContentResolver resolver,
                @Nullable String tag) {
        static void resetToDefaults(@NonNull ContentResolver resolver, @ResetMode int resetMode,
                @Nullable String prefix) {
            try {
                Bundle arg = new Bundle();
                arg.putInt(CALL_METHOD_USER_KEY, resolver.getUserId());
                if (tag != null) {
                    arg.putString(CALL_METHOD_TAG_KEY, tag);
                arg.putInt(Settings.CALL_METHOD_RESET_MODE_KEY, resetMode);
                if (prefix != null) {
                    arg.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
                }
                arg.putInt(CALL_METHOD_RESET_MODE_KEY, RESET_MODE_PACKAGE_DEFAULTS);
                arg.putInt(CALL_METHOD_RESET_MODE_KEY, resetMode);
                IContentProvider cp = sProviderHolder.getProvider(resolver);
                cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
                        CALL_METHOD_RESET_CONFIG, null, arg);
+27 −25
Original line number Diff line number Diff line
@@ -418,7 +418,7 @@ public class SettingsProvider extends ContentProvider {
            case Settings.CALL_METHOD_PUT_CONFIG: {
                String value = getSettingValue(args);
                final boolean makeDefault = getSettingMakeDefault(args);
                insertConfigSetting(name, value, null, makeDefault, requestingUserId, false);
                insertConfigSetting(name, value, makeDefault);
                break;
            }

@@ -447,7 +447,7 @@ public class SettingsProvider extends ContentProvider {
            case Settings.CALL_METHOD_RESET_CONFIG: {
                final int mode = getResetModeEnforcingPermission(args);
                String prefix = getSettingPrefix(args);
                resetConfigSetting(requestingUserId, mode, prefix);
                resetConfigSetting(mode, prefix);
                break;
            }

@@ -466,7 +466,7 @@ public class SettingsProvider extends ContentProvider {
            }

            case Settings.CALL_METHOD_DELETE_CONFIG: {
                int rows  = deleteConfigSetting(name, requestingUserId, false) ? 1 : 0;
                int rows  = deleteConfigSetting(name) ? 1 : 0;
                Bundle result = new Bundle();
                result.putInt(RESULT_ROWS_DELETED, rows);
                return result;
@@ -1067,38 +1067,33 @@ public class SettingsProvider extends ContentProvider {
        }
    }

    private boolean insertConfigSetting(String name, String value, String tag,
            boolean makeDefault, int requestingUserId, boolean forceNotify) {
    private boolean insertConfigSetting(String name, String value, boolean makeDefault) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "insertConfigSetting(" + name + ", " + value  + ", "
                    + ", " + tag + ", " + makeDefault + ", " + requestingUserId
                    + ", " + forceNotify + ")");
                    + makeDefault + ")");
        }
        return mutateConfigSetting(name, value, tag, makeDefault, requestingUserId,
                MUTATION_OPERATION_INSERT, forceNotify, 0);
        return mutateConfigSetting(name, value, null, makeDefault,
                MUTATION_OPERATION_INSERT, 0);
    }

    private boolean deleteConfigSetting(String name, int requestingUserId, boolean forceNotify) {
    private boolean deleteConfigSetting(String name) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "deleteConfigSetting(" + name + ", " + requestingUserId
                    + ", " + forceNotify + ")");
            Slog.v(LOG_TAG, "deleteConfigSetting(" + name + ")");
        }
        return mutateConfigSetting(name, null, null, false, requestingUserId,
                MUTATION_OPERATION_DELETE, forceNotify, 0);
        return mutateConfigSetting(name, null, null, false,
                MUTATION_OPERATION_DELETE, 0);
    }

    private void resetConfigSetting(int requestingUserId, int mode, String prefix) {
    private void resetConfigSetting(int mode, String prefix) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "resetConfigSetting(" + requestingUserId + ", "
                    + mode + ", " + prefix + ")");
            Slog.v(LOG_TAG, "resetConfigSetting(" + mode + ", " + prefix + ")");
        }
        mutateConfigSetting(null, null, prefix, false, requestingUserId,
                MUTATION_OPERATION_RESET, false, mode);
        mutateConfigSetting(null, null, prefix, false,
                MUTATION_OPERATION_RESET, mode);
    }

    private boolean mutateConfigSetting(String name, String value, String prefix,
            boolean makeDefault, int requestingUserId, int operation, boolean forceNotify,
            int mode) {
            boolean makeDefault, int operation, int mode) {
        // TODO(b/117663715): check the new permission when it's added.
        // enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS);

@@ -1107,13 +1102,13 @@ public class SettingsProvider extends ContentProvider {
            switch (operation) {
                case MUTATION_OPERATION_INSERT: {
                    return mSettingsRegistry.insertSettingLocked(SETTINGS_TYPE_CONFIG,
                            UserHandle.USER_SYSTEM, name, value, null, makeDefault,
                            getCallingPackage(), forceNotify, null);
                            UserHandle.USER_SYSTEM, name, value, null, makeDefault, true,
                            getCallingPackage(), false, null);
                }

                case MUTATION_OPERATION_DELETE: {
                    return mSettingsRegistry.deleteSettingLocked(SETTINGS_TYPE_CONFIG,
                            UserHandle.USER_SYSTEM, name, forceNotify, null);
                            UserHandle.USER_SYSTEM, name, false, null);
                }

                case MUTATION_OPERATION_RESET: {
@@ -2631,13 +2626,20 @@ public class SettingsProvider extends ContentProvider {
        public boolean insertSettingLocked(int type, int userId, String name, String value,
                String tag, boolean makeDefault, String packageName, boolean forceNotify,
                Set<String> criticalSettings) {
            return insertSettingLocked(type, userId, name, value, tag, makeDefault, false,
                    packageName, forceNotify, criticalSettings);
        }

        public boolean insertSettingLocked(int type, int userId, String name, String value,
                String tag, boolean makeDefault, boolean forceNonSystemPackage, String packageName,
                boolean forceNotify, Set<String> criticalSettings) {
            final int key = makeKey(type, userId);

            boolean success = false;
            SettingsState settingsState = peekSettingsStateLocked(key);
            if (settingsState != null) {
                success = settingsState.insertSettingLocked(name, value,
                        tag, makeDefault, packageName);
                        tag, makeDefault, forceNonSystemPackage, packageName);
            }

            if (success && criticalSettings != null && criticalSettings.contains(name)) {
+8 −1
Original line number Diff line number Diff line
@@ -377,6 +377,13 @@ final class SettingsState {
    @GuardedBy("mLock")
    public boolean insertSettingLocked(String name, String value, String tag,
            boolean makeDefault, String packageName) {
        return insertSettingLocked(name, value, tag, makeDefault, false, packageName);
    }

    // The settings provider must hold its lock when calling here.
    @GuardedBy("mLock")
    public boolean insertSettingLocked(String name, String value, String tag,
            boolean makeDefault, boolean forceNonSystemPackage, String packageName) {
        if (TextUtils.isEmpty(name)) {
            return false;
        }
@@ -387,7 +394,7 @@ final class SettingsState {
        Setting newState;

        if (oldState != null) {
            if (!oldState.update(value, makeDefault, packageName, tag, false)) {
            if (!oldState.update(value, makeDefault, packageName, tag, forceNonSystemPackage)) {
                return false;
            }
            newState = oldState;
+8 −31
Original line number Diff line number Diff line
@@ -17,10 +17,9 @@
package com.android.providers.settings;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;

import static org.junit.Assert.assertNotNull;

import android.content.ContentResolver;
import android.net.Uri;
import android.os.Bundle;
@@ -147,10 +146,10 @@ public class DeviceConfigServiceTest {
    }

    @Test
    public void testReset_setUntrustedDefault() throws Exception {
    public void testReset() throws Exception {
        String newValue = "value2";

        // make sValue the untrusted default (set by root)
        // make sValue the default value
        executeShellCommand(
                "device_config put " + sNamespace + " " + sKey + " " + sValue + " default");
        // make newValue the current value
@@ -159,40 +158,19 @@ public class DeviceConfigServiceTest {
        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
        assertEquals(newValue, result);

        // reset values that were set by untrusted packages
        executeShellCommand("device_config reset untrusted_defaults " + sNamespace);
        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
        // back to the default
        // the default value has been restored
        assertEquals(sValue, result);

        // clear values that were set by untrusted packages
        executeShellCommand("device_config reset trusted_defaults " + sNamespace);
        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
        // not trusted default was set
        // even the default value is gone now
        assertNull(result);
    }

    @Test
    public void testReset_setTrustedDefault() throws Exception {
        String newValue = "value2";

        // make sValue the trusted default (set by system)
        putWithContentProvider(mContentResolver, sNamespace, sKey, sValue, true);
        // make newValue the current value
        executeShellCommand(
                "device_config put " + sNamespace + " " + sKey + " " + newValue);
        String result = getFromContentProvider(mContentResolver, sNamespace, sKey);
        assertEquals(newValue, result);

        executeShellCommand("device_config reset untrusted_defaults " + sNamespace);
        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
        // back to the default
        assertEquals(sValue, result);

        executeShellCommand("device_config reset trusted_defaults " + sNamespace);
        result = getFromContentProvider(mContentResolver, sNamespace, sKey);
        // our trusted default is still set
        assertEquals(sValue, result);
    }

    private static void executeShellCommand(String command) throws IOException {
        InputStream is = new FileInputStream(InstrumentationRegistry.getInstrumentation()
                .getUiAutomation().executeShellCommand(command).getFileDescriptor());
@@ -212,8 +190,7 @@ public class DeviceConfigServiceTest {
        if (makeDefault) {
            args.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
        }
        resolver.call(
                CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, compositeName, args);
        resolver.call(CONFIG_CONTENT_URI, Settings.CALL_METHOD_PUT_CONFIG, compositeName, args);
    }

    private static String getFromContentProvider(ContentResolver resolver, String namespace,