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

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

Merge changes I259a3f41,Id309a941

* changes:
  Guard the preserve settings logic in SettingsBackupAgent with a flag
  Do not restore settings marked as preserved in SettingsBackupAgent
parents d8be1352 6fb2bb1b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -2417,6 +2417,10 @@ public final class Settings {
    public static class NameValueTable implements BaseColumns {
        public static final String NAME = "name";
        public static final String VALUE = "value";
        // A flag indicating whether the current value of a setting should be preserved during
        // restore.
        /** @hide */
        public static final String IS_PRESERVED_IN_RESTORE = "is_preserved_in_restore";
        protected static boolean putString(ContentResolver resolver, Uri uri,
                String name, String value) {
+6 −0
Original line number Diff line number Diff line
@@ -47,6 +47,9 @@ public class FeatureFlagUtils {
    /** @hide */
    public static final String BACKUP_NO_KV_DATA_CHANGE_CALLS =
            "backup_enable_no_data_notification_calls";
    /** @hide */
    public static final String SETTINGS_DO_NOT_RESTORE_PRESERVED =
            "settings_do_not_restore_preserved";

    private static final Map<String, String> DEFAULT_FLAGS;

@@ -68,6 +71,9 @@ public class FeatureFlagUtils {

        // Disabled until backup transports support it.
        DEFAULT_FLAGS.put(BACKUP_NO_KV_DATA_CHANGE_CALLS, "false");
        // Disabled by default until b/148278926 is resolved. This flags guards a feature
        // introduced in R and will be removed in the next release (b/148367230).
        DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "false");
    }

    /**
+127 −37
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.provider.settings.validators.Validator;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.BackupUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
@@ -280,6 +281,16 @@ public class SettingsBackupAgent extends BackupAgentHelper {
        Settings.Secure.getMovedToGlobalSettings(movedToGlobal);
        Set<String> movedToSecure = getMovedToSecureSettings();

        Set<String> preservedGlobalSettings = getSettingsToPreserveInRestore(
                Settings.Global.CONTENT_URI);
        Set<String> preservedSecureSettings = getSettingsToPreserveInRestore(
                Settings.Secure.CONTENT_URI);
        Set<String> preservedSystemSettings = getSettingsToPreserveInRestore(
                Settings.System.CONTENT_URI);
        Set<String> preservedSettings = new HashSet<>(preservedGlobalSettings);
        preservedSettings.addAll(preservedSecureSettings);
        preservedSettings.addAll(preservedSystemSettings);

        byte[] restoredWifiSupplicantData = null;
        byte[] restoredWifiIpConfigData = null;

@@ -300,7 +311,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                case KEY_SYSTEM :
                    restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal,
                            movedToSecure, R.array.restore_blocked_system_settings,
                            dynamicBlockList);
                            dynamicBlockList,
                            preservedSystemSettings);
                    mSettingsHelper.applyAudioSettings();
                    break;

@@ -311,7 +323,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                            movedToGlobal,
                            null,
                            R.array.restore_blocked_secure_settings,
                            dynamicBlockList);
                            dynamicBlockList,
                            preservedSecureSettings);
                    break;

                case KEY_GLOBAL :
@@ -321,7 +334,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                            null,
                            movedToSecure,
                            R.array.restore_blocked_global_settings,
                            dynamicBlockList);
                            dynamicBlockList,
                            preservedGlobalSettings);
                    break;

                case KEY_WIFI_SUPPLICANT :
@@ -368,7 +382,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                    restoreDeviceSpecificConfig(
                            restoredDeviceSpecificConfig,
                            R.array.restore_blocked_device_specific_settings,
                            dynamicBlockList);
                            dynamicBlockList,
                            preservedSettings);
                    break;

                default :
@@ -418,7 +433,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
            in.readFully(buffer, 0, nBytes);
            restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal,
                    movedToSecure, R.array.restore_blocked_system_settings,
                    Collections.emptySet());
                    Collections.emptySet(), Collections.emptySet());

            // secure settings
            nBytes = in.readInt();
@@ -432,7 +447,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                    movedToGlobal,
                    null,
                    R.array.restore_blocked_secure_settings,
                    Collections.emptySet());
                    Collections.emptySet(), Collections.emptySet());

            // Global only if sufficiently new
            if (version >= FULL_BACKUP_ADDED_GLOBAL) {
@@ -443,7 +458,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                movedToGlobal.clear();  // no redirection; this *is* the global namespace
                restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal,
                        movedToSecure, R.array.restore_blocked_global_settings,
                        Collections.emptySet());
                        Collections.emptySet(), Collections.emptySet());
            }

            // locale
@@ -607,6 +622,40 @@ public class SettingsBackupAgent extends BackupAgentHelper {
        }
    }

    /**
     * Get names of the settings for which the current value should be preserved during restore.
     */
    private Set<String> getSettingsToPreserveInRestore(Uri settingsUri) {
        if (!FeatureFlagUtils.isEnabled(getApplicationContext(),
                FeatureFlagUtils.SETTINGS_DO_NOT_RESTORE_PRESERVED)) {
            return Collections.emptySet();
        }

        Cursor cursor = getContentResolver().query(settingsUri, new String[] {
                Settings.NameValueTable.NAME, Settings.NameValueTable.IS_PRESERVED_IN_RESTORE },
                /* selection */ null, /* selectionArgs */ null, /* sortOrder */ null);

        if (!cursor.moveToFirst()) {
            Slog.i(TAG, "No settings to be preserved in restore");
            return Collections.emptySet();
        }

        int nameIndex = cursor.getColumnIndex(Settings.NameValueTable.NAME);
        int isPreservedIndex = cursor.getColumnIndex(
                Settings.NameValueTable.IS_PRESERVED_IN_RESTORE);

        Set<String> preservedSettings = new HashSet<>();
        while (!cursor.isAfterLast()) {
            if (Boolean.parseBoolean(cursor.getString(isPreservedIndex))) {
                preservedSettings.add(getQualifiedKeyForSetting(cursor.getString(nameIndex),
                        settingsUri));
            }
            cursor.moveToNext();
        }

        return preservedSettings;
    }

    /**
     * Serialize the owner info and other lock settings
     */
@@ -650,7 +699,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
            HashSet<String> movedToGlobal,
            Set<String> movedToSecure,
            int blockedSettingsArrayId,
            Set<String> dynamicBlockList) {
            Set<String> dynamicBlockList,
            Set<String> settingsToPreserve) {
        byte[] settings = new byte[data.getDataSize()];
        try {
            data.readEntityData(settings, 0, settings.length);
@@ -665,7 +715,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                movedToGlobal,
                movedToSecure,
                blockedSettingsArrayId,
                dynamicBlockList);
                dynamicBlockList,
                settingsToPreserve);
    }

    private void restoreSettings(
@@ -675,7 +726,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
            HashSet<String> movedToGlobal,
            Set<String> movedToSecure,
            int blockedSettingsArrayId,
            Set<String> dynamicBlockList) {
            Set<String> dynamicBlockList,
            Set<String> settingsToPreserve) {
        restoreSettings(
                settings,
                0,
@@ -684,10 +736,12 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                movedToGlobal,
                movedToSecure,
                blockedSettingsArrayId,
                dynamicBlockList);
                dynamicBlockList,
                settingsToPreserve);
    }

    private void restoreSettings(
    @VisibleForTesting
    void restoreSettings(
            byte[] settings,
            int pos,
            int bytes,
@@ -695,31 +749,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
            HashSet<String> movedToGlobal,
            Set<String> movedToSecure,
            int blockedSettingsArrayId,
            Set<String> dynamicBlockList) {
            Set<String> dynamicBlockList,
            Set<String> settingsToPreserve) {
        if (DEBUG) {
            Log.i(TAG, "restoreSettings: " + contentUri);
        }

        // Figure out the white list and redirects to the global table.  We restore anything
        // in either the backup whitelist or the legacy-restore whitelist for this table.
        final String[] whitelist;
        Map<String, Validator> validators = null;
        if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
            whitelist = ArrayUtils.concatElements(String.class, SecureSettings.SETTINGS_TO_BACKUP,
                    Settings.Secure.LEGACY_RESTORE_SETTINGS,
                    DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
            validators = SecureSettingsValidators.VALIDATORS;
        } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
            whitelist = ArrayUtils.concatElements(String.class, SystemSettings.SETTINGS_TO_BACKUP,
                    Settings.System.LEGACY_RESTORE_SETTINGS);
            validators = SystemSettingsValidators.VALIDATORS;
        } else if (contentUri.equals(Settings.Global.CONTENT_URI)) {
            whitelist = ArrayUtils.concatElements(String.class, GlobalSettings.SETTINGS_TO_BACKUP,
                    Settings.Global.LEGACY_RESTORE_SETTINGS);
            validators = GlobalSettingsValidators.VALIDATORS;
        } else {
            throw new IllegalArgumentException("Unknown URI: " + contentUri);
        }
        SettingsBackupWhitelist whitelist = getBackupWhitelist(contentUri);

        // Restore only the white list data.
        final ArrayMap<String, String> cachedEntries = new ArrayMap<>();
@@ -729,7 +765,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {

        Set<String> blockedSettings = getBlockedSettings(blockedSettingsArrayId);

        for (String key : whitelist) {
        for (String key : whitelist.mSettingsWhitelist) {
            boolean isBlockedBySystem = blockedSettings != null && blockedSettings.contains(key);
            if (isBlockedBySystem || isBlockedByDynamicList(dynamicBlockList, contentUri,  key)) {
                Log.i(
@@ -742,6 +778,12 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                continue;
            }

            if (settingsToPreserve.contains(getQualifiedKeyForSetting(key, contentUri))) {
                Log.i(TAG, "Skipping restore for setting " + key + " as it is marked as "
                        + "preserved");
                continue;
            }

            String value = null;
            boolean hasValueToRestore = false;
            if (cachedEntries.indexOfKey(key) >= 0) {
@@ -775,7 +817,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
            }

            // only restore the settings that have valid values
            if (!isValidSettingValue(key, value, validators)) {
            if (!isValidSettingValue(key, value, whitelist.mSettingsValidators)) {
                Log.w(TAG, "Attempted restore of " + key + " setting, but its value didn't pass"
                        + " validation, value: " + value);
                continue;
@@ -798,11 +840,42 @@ public class SettingsBackupAgent extends BackupAgentHelper {
        }
    }

    @VisibleForTesting
    SettingsBackupWhitelist getBackupWhitelist(Uri contentUri) {
        // Figure out the white list and redirects to the global table.  We restore anything
        // in either the backup whitelist or the legacy-restore whitelist for this table.
        String[] whitelist;
        Map<String, Validator> validators = null;
        if (contentUri.equals(Settings.Secure.CONTENT_URI)) {
            whitelist = ArrayUtils.concatElements(String.class, SecureSettings.SETTINGS_TO_BACKUP,
                    Settings.Secure.LEGACY_RESTORE_SETTINGS,
                    DeviceSpecificSettings.DEVICE_SPECIFIC_SETTINGS_TO_BACKUP);
            validators = SecureSettingsValidators.VALIDATORS;
        } else if (contentUri.equals(Settings.System.CONTENT_URI)) {
            whitelist = ArrayUtils.concatElements(String.class, SystemSettings.SETTINGS_TO_BACKUP,
                    Settings.System.LEGACY_RESTORE_SETTINGS);
            validators = SystemSettingsValidators.VALIDATORS;
        } else if (contentUri.equals(Settings.Global.CONTENT_URI)) {
            whitelist = ArrayUtils.concatElements(String.class, GlobalSettings.SETTINGS_TO_BACKUP,
                    Settings.Global.LEGACY_RESTORE_SETTINGS);
            validators = GlobalSettingsValidators.VALIDATORS;
        } else {
            throw new IllegalArgumentException("Unknown URI: " + contentUri);
        }

        return new SettingsBackupWhitelist(whitelist, validators);
    }

    private boolean isBlockedByDynamicList(Set<String> dynamicBlockList, Uri areaUri, String key) {
        String contentKey = Uri.withAppendedPath(areaUri, key).toString();
        return dynamicBlockList.contains(contentKey);
    }

    @VisibleForTesting
    static String getQualifiedKeyForSetting(String settingName, Uri settingUri) {
        return Uri.withAppendedPath(settingUri, settingName).toString();
    }

    // There may be other sources of blocked settings, so I'm separating out this
    // code to make it easy to modify in the future.
    @VisibleForTesting
@@ -1089,7 +1162,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
     */
    @VisibleForTesting
    boolean restoreDeviceSpecificConfig(byte[] data, int blockedSettingsArrayId,
            Set<String> dynamicBlocklist) {
            Set<String> dynamicBlocklist, Set<String> preservedSettings) {
        // We're using an AtomicInteger to wrap the position int and allow called methods to
        // modify it.
        AtomicInteger pos = new AtomicInteger(0);
@@ -1108,7 +1181,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                null,
                null,
                blockedSettingsArrayId,
                dynamicBlocklist);
                dynamicBlocklist,
                preservedSettings);

        updateWindowManagerIfNeeded(originalDensity);

@@ -1240,4 +1314,20 @@ public class SettingsBackupAgent extends BackupAgentHelper {
                | ((in[pos + 3] & 0xFF) <<  0);
        return result;
    }

    /**
     * Store the whitelist of settings to be backed up and validators for them.
     */
    @VisibleForTesting
    static class SettingsBackupWhitelist {
        final String[] mSettingsWhitelist;
        final Map<String, Validator> mSettingsValidators;


        SettingsBackupWhitelist(String[] settingsWhitelist,
                Map<String, Validator> settingsValidators) {
            mSettingsWhitelist = settingsWhitelist;
            mSettingsValidators = settingsValidators;
        }
    }
}
+13 −2
Original line number Diff line number Diff line
@@ -180,10 +180,17 @@ public class SettingsProvider extends ContentProvider {
    private static final int MUTATION_OPERATION_UPDATE = 3;
    private static final int MUTATION_OPERATION_RESET = 4;

    private static final String[] LEGACY_SQL_COLUMNS = new String[] {
            Settings.NameValueTable._ID,
            Settings.NameValueTable.NAME,
            Settings.NameValueTable.VALUE,
    };

    private static final String[] ALL_COLUMNS = new String[] {
            Settings.NameValueTable._ID,
            Settings.NameValueTable.NAME,
            Settings.NameValueTable.VALUE
            Settings.NameValueTable.VALUE,
            Settings.NameValueTable.IS_PRESERVED_IN_RESTORE,
    };

    public static final int SETTINGS_TYPE_GLOBAL = SettingsState.SETTINGS_TYPE_GLOBAL;
@@ -2353,6 +2360,10 @@ public class SettingsProvider extends ContentProvider {
                case Settings.NameValueTable.VALUE: {
                    values[i] = setting.getValue();
                } break;

                case Settings.NameValueTable.IS_PRESERVED_IN_RESTORE: {
                    values[i] = String.valueOf(setting.isValuePreservedInRestore());
                } break;
            }
        }

@@ -3097,7 +3108,7 @@ public class SettingsProvider extends ContentProvider {
            SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
            queryBuilder.setTables(table);

            Cursor cursor = queryBuilder.query(database, ALL_COLUMNS,
            Cursor cursor = queryBuilder.query(database, LEGACY_SQL_COLUMNS,
                    null, null, null, null, null);

            if (cursor == null) {
+79 −7
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.provider.settings.validators.SettingsValidators;
import android.provider.settings.validators.Validator;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;

@@ -43,6 +45,7 @@ import org.junit.runner.RunWith;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -55,12 +58,24 @@ import java.util.concurrent.atomic.AtomicInteger;
/** Tests for the SettingsHelperTest */
@RunWith(AndroidJUnit4.class)
public class SettingsBackupAgentTest extends BaseSettingsProviderTest {

    private static final Uri TEST_URI = Uri.EMPTY;
    private static final String TEST_DISPLAY_DENSITY_FORCED = "123";
    private static final String OVERRIDDEN_TEST_SETTING = "overridden_setting";
    private static final String PRESERVED_TEST_SETTING = "preserved_setting";
    private static final Map<String, String> DEVICE_SPECIFIC_TEST_VALUES = new HashMap<>();
    private static final Map<String, String> TEST_VALUES = new HashMap<>();
    private static final Map<String, Validator> TEST_VALUES_VALIDATORS = new HashMap<>();

    static {
        TEST_VALUES.put(Settings.Secure.DISPLAY_DENSITY_FORCED, TEST_DISPLAY_DENSITY_FORCED);
        DEVICE_SPECIFIC_TEST_VALUES.put(Settings.Secure.DISPLAY_DENSITY_FORCED,
                TEST_DISPLAY_DENSITY_FORCED);

        TEST_VALUES.put(OVERRIDDEN_TEST_SETTING, "123");
        TEST_VALUES.put(PRESERVED_TEST_SETTING, "124");

        TEST_VALUES_VALIDATORS.put(OVERRIDDEN_TEST_SETTING,
                SettingsValidators.ANY_STRING_VALIDATOR);
        TEST_VALUES_VALIDATORS.put(PRESERVED_TEST_SETTING, SettingsValidators.ANY_STRING_VALIDATOR);
    }

    private TestFriendlySettingsBackupAgent mAgentUnderTest;
@@ -83,14 +98,15 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {

        byte[] settingsBackup = mAgentUnderTest.getDeviceSpecificConfiguration();

        assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries);
        assertEquals("Not all values backed up.", DEVICE_SPECIFIC_TEST_VALUES.keySet(), helper.mReadEntries);

        mAgentUnderTest.restoreDeviceSpecificConfig(
                settingsBackup,
                R.array.restore_blocked_device_specific_settings,
                Collections.emptySet(),
                Collections.emptySet());

        assertEquals("Not all values were restored.", TEST_VALUES, helper.mWrittenValues);
        assertEquals("Not all values were restored.", DEVICE_SPECIFIC_TEST_VALUES, helper.mWrittenValues);
    }

    @Test
@@ -100,12 +116,13 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {

        byte[] settingsBackup = mAgentUnderTest.getDeviceSpecificConfiguration();

        assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries);
        mAgentUnderTest.setBlockedSettings(TEST_VALUES.keySet().toArray(new String[0]));
        assertEquals("Not all values backed up.", DEVICE_SPECIFIC_TEST_VALUES.keySet(), helper.mReadEntries);
        mAgentUnderTest.setBlockedSettings(DEVICE_SPECIFIC_TEST_VALUES.keySet().toArray(new String[0]));

        mAgentUnderTest.restoreDeviceSpecificConfig(
                settingsBackup,
                R.array.restore_blocked_device_specific_settings,
                Collections.emptySet(),
                Collections.emptySet());

        assertTrue("Not all values were blocked.", helper.mWrittenValues.isEmpty());
@@ -172,9 +189,50 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
                mAgentUnderTest.restoreDeviceSpecificConfig(
                        data,
                        R.array.restore_blocked_device_specific_settings,
                        Collections.emptySet(),
                        Collections.emptySet()));
    }

    @Test
    public void testOnRestore_preservedSettingsAreNotRestored() {
        SettingsBackupAgent.SettingsBackupWhitelist whitelist =
                new SettingsBackupAgent.SettingsBackupWhitelist(
                        new String[] { OVERRIDDEN_TEST_SETTING, PRESERVED_TEST_SETTING },
                        TEST_VALUES_VALIDATORS);
        mAgentUnderTest.setSettingsWhitelist(whitelist);
        mAgentUnderTest.setBlockedSettings();
        TestSettingsHelper settingsHelper = new TestSettingsHelper(mContext);
        mAgentUnderTest.mSettingsHelper = settingsHelper;

        byte[] backupData = generateBackupData(TEST_VALUES);
        mAgentUnderTest.restoreSettings(backupData, /* pos */ 0, backupData.length, TEST_URI, new HashSet<>(),
                Collections.emptySet(), /* blockedSettingsArrayId */ 0, Collections.emptySet(),
                new HashSet<>(Collections.singletonList(SettingsBackupAgent.getQualifiedKeyForSetting(PRESERVED_TEST_SETTING, TEST_URI))));

        assertTrue(settingsHelper.mWrittenValues.containsKey(OVERRIDDEN_TEST_SETTING));
        assertFalse(settingsHelper.mWrittenValues.containsKey(PRESERVED_TEST_SETTING));
    }

    private byte[] generateBackupData(Map<String, String> keyValueData) {
        int totalBytes = 0;
        for (String key : keyValueData.keySet()) {
            totalBytes += 2 * Integer.BYTES + key.getBytes().length
                    + keyValueData.get(key).getBytes().length;
        }

        ByteBuffer buffer = ByteBuffer.allocate(totalBytes);
        for (String key : keyValueData.keySet()) {
            byte[] keyBytes = key.getBytes();
            byte[] valueBytes = keyValueData.get(key).getBytes();
            buffer.putInt(keyBytes.length);
            buffer.put(keyBytes);
            buffer.putInt(valueBytes.length);
            buffer.put(valueBytes);
        }

        return buffer.array();
    }

    private byte[] generateUncorruptedHeader() throws IOException {
        try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
            mAgentUnderTest.writeHeader(os);
@@ -219,6 +277,7 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
    private static class TestFriendlySettingsBackupAgent extends SettingsBackupAgent {
        private Boolean mForcedDeviceInfoRestoreAcceptability = null;
        private String[] mBlockedSettings = null;
        private SettingsBackupWhitelist mSettingsWhitelist = null;

        void setForcedDeviceInfoRestoreAcceptability(boolean value) {
            mForcedDeviceInfoRestoreAcceptability = value;
@@ -228,6 +287,10 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
            mBlockedSettings = blockedSettings;
        }

        void setSettingsWhitelist(SettingsBackupWhitelist settingsWhitelist) {
            mSettingsWhitelist = settingsWhitelist;
        }

        @Override
        protected Set<String> getBlockedSettings(int blockedSettingsArrayId) {
            return mBlockedSettings == null
@@ -241,6 +304,15 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
                    ? super.isSourceAcceptable(data, pos)
                    : mForcedDeviceInfoRestoreAcceptability;
        }

        @Override
        SettingsBackupWhitelist getBackupWhitelist(Uri contentUri) {
            if (mSettingsWhitelist == null) {
                return super.getBackupWhitelist(contentUri);
            }

            return mSettingsWhitelist;
        }
    }

    /** The TestSettingsHelper tracks which values have been backed up and/or restored. */
@@ -257,7 +329,7 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
        @Override
        public String onBackupValue(String key, String value) {
            mReadEntries.add(key);
            String readValue = TEST_VALUES.get(key);
            String readValue = DEVICE_SPECIFIC_TEST_VALUES.get(key);
            assert readValue != null;
            return readValue;
        }