Loading packages/SettingsProvider/res/values/blocked_settings.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2019 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <!-- These are arrays of settings which should not be restored to this device --> <resources> <string-array name="restore_blocked_device_specific_settings" /> <string-array name="restore_blocked_global_settings" /> <string-array name="restore_blocked_secure_settings" /> <string-array name="restore_blocked_system_settings" /> </resources> No newline at end of file packages/SettingsProvider/res/values/overlayable.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8" ?> <!-- Copyright (C) 2019 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <overlayable name="SettingsToNotRestore"> <policy type="product|system|vendor"> <item type="array" name="restore_blocked_device_specific_settings" /> <item type="array" name="restore_blocked_global_settings" /> <item type="array" name="restore_blocked_secure_settings" /> <item type="array" name="restore_blocked_system_settings" /> </policy> </overlayable> </resources> packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +121 −22 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import java.io.IOException; import java.io.OutputStream; import java.time.DateTimeException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Objects; Loading Loading @@ -250,7 +251,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { ParcelFileDescriptor newState) { throw new RuntimeException("SettingsBackupAgent has been migrated to use key exclusion"); } @Override public void onRestore(BackupDataInput data, long appVersionCode, ParcelFileDescriptor newState, Set<String> dynamicBlockList) throws IOException { if (DEBUG) { Log.d(TAG, "onRestore(): appVersionCode: " + appVersionCode Loading @@ -266,7 +273,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // versionCode of com.android.providers.settings corresponds to SDK_INT mRestoredFromSdkInt = appVersionCode; mRestoredFromSdkInt = (int) appVersionCode; HashSet<String> movedToGlobal = new HashSet<String>(); Settings.System.getMovedToGlobalSettings(movedToGlobal); Loading @@ -292,16 +299,29 @@ public class SettingsBackupAgent extends BackupAgentHelper { switch (key) { case KEY_SYSTEM : restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal, movedToSecure); movedToSecure, R.array.restore_blocked_system_settings, dynamicBlockList); mSettingsHelper.applyAudioSettings(); break; case KEY_SECURE : restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal, null); restoreSettings( data, Settings.Secure.CONTENT_URI, movedToGlobal, null, R.array.restore_blocked_secure_settings, dynamicBlockList); break; case KEY_GLOBAL : restoreSettings(data, Settings.Global.CONTENT_URI, null, movedToSecure); restoreSettings( data, Settings.Global.CONTENT_URI, null, movedToSecure, R.array.restore_blocked_global_settings, dynamicBlockList); break; case KEY_WIFI_SUPPLICANT : Loading Loading @@ -345,7 +365,10 @@ public class SettingsBackupAgent extends BackupAgentHelper { case KEY_DEVICE_SPECIFIC_CONFIG: byte[] restoredDeviceSpecificConfig = new byte[size]; data.readEntityData(restoredDeviceSpecificConfig, 0, size); restoreDeviceSpecificConfig(restoredDeviceSpecificConfig); restoreDeviceSpecificConfig( restoredDeviceSpecificConfig, R.array.restore_blocked_device_specific_settings, dynamicBlockList); break; default : Loading Loading @@ -394,14 +417,22 @@ public class SettingsBackupAgent extends BackupAgentHelper { byte[] buffer = new byte[nBytes]; in.readFully(buffer, 0, nBytes); restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal, movedToSecure); movedToSecure, R.array.restore_blocked_system_settings, Collections.emptySet()); // secure settings nBytes = in.readInt(); if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data"); if (nBytes > buffer.length) buffer = new byte[nBytes]; in.readFully(buffer, 0, nBytes); restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, null); restoreSettings( buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, null, R.array.restore_blocked_secure_settings, Collections.emptySet()); // Global only if sufficiently new if (version >= FULL_BACKUP_ADDED_GLOBAL) { Loading @@ -411,7 +442,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { in.readFully(buffer, 0, nBytes); movedToGlobal.clear(); // no redirection; this *is* the global namespace restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal, movedToSecure); movedToSecure, R.array.restore_blocked_global_settings, Collections.emptySet()); } // locale Loading Loading @@ -612,8 +644,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { return baos.toByteArray(); } private void restoreSettings(BackupDataInput data, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure) { private void restoreSettings( BackupDataInput data, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure, int blockedSettingsArrayId, Set<String> dynamicBlockList) { byte[] settings = new byte[data.getDataSize()]; try { data.readEntityData(settings, 0, settings.length); Loading @@ -621,16 +658,44 @@ public class SettingsBackupAgent extends BackupAgentHelper { Log.e(TAG, "Couldn't read entity data"); return; } restoreSettings(settings, settings.length, contentUri, movedToGlobal, movedToSecure); } private void restoreSettings(byte[] settings, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure) { restoreSettings(settings, 0, bytes, contentUri, movedToGlobal, movedToSecure); } private void restoreSettings(byte[] settings, int pos, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure) { restoreSettings( settings, settings.length, contentUri, movedToGlobal, movedToSecure, blockedSettingsArrayId, dynamicBlockList); } private void restoreSettings( byte[] settings, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure, int blockedSettingsArrayId, Set<String> dynamicBlockList) { restoreSettings( settings, 0, bytes, contentUri, movedToGlobal, movedToSecure, blockedSettingsArrayId, dynamicBlockList); } private void restoreSettings( byte[] settings, int pos, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure, int blockedSettingsArrayId, Set<String> dynamicBlockList) { if (DEBUG) { Log.i(TAG, "restoreSettings: " + contentUri); } Loading Loading @@ -662,9 +727,20 @@ public class SettingsBackupAgent extends BackupAgentHelper { SettingsHelper settingsHelper = mSettingsHelper; ContentResolver cr = getContentResolver(); final int whiteListSize = whitelist.length; for (int i = 0; i < whiteListSize; i++) { String key = whitelist[i]; Set<String> blockedSettings = getBlockedSettings(blockedSettingsArrayId); for (String key : whitelist) { boolean isBlockedBySystem = blockedSettings != null && blockedSettings.contains(key); if (isBlockedBySystem || isBlockedByDynamicList(dynamicBlockList, contentUri, key)) { Log.i( TAG, "Key " + key + " removed from restore by " + (isBlockedBySystem ? "system" : "dynamic") + " block list"); continue; } String value = null; boolean hasValueToRestore = false; Loading Loading @@ -722,6 +798,19 @@ public class SettingsBackupAgent extends BackupAgentHelper { } } private boolean isBlockedByDynamicList(Set<String> dynamicBlockList, Uri areaUri, String key) { String contentKey = Uri.withAppendedPath(areaUri, key).toString(); return dynamicBlockList.contains(contentKey); } // 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 protected Set<String> getBlockedSettings(int blockedSettingsArrayId) { String[] blockedSettings = getResources().getStringArray(blockedSettingsArrayId); return new HashSet<>(Arrays.asList(blockedSettings)); } private boolean isValidSettingValue(String key, String value, Map<String, Validator> validators) { if (key == null || validators == null) { Loading Loading @@ -998,10 +1087,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { * Restore the device specific settings. * * @param data The byte array holding a backed up version of another devices settings. * @param blockedSettingsArrayId The string array resource holding the settings not to restore. * @param dynamicBlocklist The dynamic list of settings not to restore fed into this agent. * @return true if the restore succeeded, false if it was stopped. */ @VisibleForTesting boolean restoreDeviceSpecificConfig(byte[] data) { boolean restoreDeviceSpecificConfig(byte[] data, int blockedSettingsArrayId, Set<String> dynamicBlocklist) { // We're using an AtomicInteger to wrap the position int and allow called methods to // modify it. AtomicInteger pos = new AtomicInteger(0); Loading @@ -1013,7 +1105,14 @@ public class SettingsBackupAgent extends BackupAgentHelper { int dataStart = pos.get(); restoreSettings( data, dataStart, data.length, Settings.Secure.CONTENT_URI, null, null); data, dataStart, data.length, Settings.Secure.CONTENT_URI, null, null, blockedSettingsArrayId, dynamicBlocklist); updateWindowManagerIfNeeded(originalDensity); Loading packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java +49 −5 Original line number Diff line number Diff line Loading @@ -37,14 +37,14 @@ import android.test.mock.MockContentResolver; import androidx.test.runner.AndroidJUnit4; import com.android.internal.annotations.VisibleForTesting; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; Loading Loading @@ -85,11 +85,32 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest { assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries); mAgentUnderTest.restoreDeviceSpecificConfig(settingsBackup); mAgentUnderTest.restoreDeviceSpecificConfig( settingsBackup, R.array.restore_blocked_device_specific_settings, Collections.emptySet()); assertEquals("Not all values were restored.", TEST_VALUES, helper.mWrittenValues); } @Test public void testRoundTripDeviceSpecificSettingsWithBlock() throws IOException { TestSettingsHelper helper = new TestSettingsHelper(mContext); mAgentUnderTest.mSettingsHelper = helper; byte[] settingsBackup = mAgentUnderTest.getDeviceSpecificConfiguration(); assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries); mAgentUnderTest.setBlockedSettings(TEST_VALUES.keySet().toArray(new String[0])); mAgentUnderTest.restoreDeviceSpecificConfig( settingsBackup, R.array.restore_blocked_device_specific_settings, Collections.emptySet()); assertTrue("Not all values were blocked.", helper.mWrittenValues.isEmpty()); } @Test public void testGeneratedHeaderMatchesCurrentDevice() throws IOException { mAgentUnderTest.mSettingsHelper = new TestSettingsHelper(mContext); Loading Loading @@ -148,7 +169,10 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest { assertFalse( "Blocking isSourceAcceptable did not stop restore", mAgentUnderTest.restoreDeviceSpecificConfig(data)); mAgentUnderTest.restoreDeviceSpecificConfig( data, R.array.restore_blocked_device_specific_settings, Collections.emptySet())); } private byte[] generateUncorruptedHeader() throws IOException { Loading Loading @@ -184,14 +208,34 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest { } } private byte[] generateSingleKeyTestBackupData(String key, String value) throws IOException { try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { os.write(SettingsBackupAgent.toByteArray(key)); os.write(SettingsBackupAgent.toByteArray(value)); return os.toByteArray(); } } private static class TestFriendlySettingsBackupAgent extends SettingsBackupAgent { private Boolean mForcedDeviceInfoRestoreAcceptability = null; private String[] mBlockedSettings = null; void setForcedDeviceInfoRestoreAcceptability(boolean value) { mForcedDeviceInfoRestoreAcceptability = value; } @VisibleForTesting void setBlockedSettings(String... blockedSettings) { mBlockedSettings = blockedSettings; } @Override protected Set<String> getBlockedSettings(int blockedSettingsArrayId) { return mBlockedSettings == null ? super.getBlockedSettings(blockedSettingsArrayId) : new HashSet<>(Arrays.asList(mBlockedSettings)); } @Override boolean isSourceAcceptable(byte[] data, AtomicInteger pos) { return mForcedDeviceInfoRestoreAcceptability == null ? super.isSourceAcceptable(data, pos) Loading Loading
packages/SettingsProvider/res/values/blocked_settings.xml 0 → 100644 +24 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2019 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <!-- These are arrays of settings which should not be restored to this device --> <resources> <string-array name="restore_blocked_device_specific_settings" /> <string-array name="restore_blocked_global_settings" /> <string-array name="restore_blocked_secure_settings" /> <string-array name="restore_blocked_system_settings" /> </resources> No newline at end of file
packages/SettingsProvider/res/values/overlayable.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8" ?> <!-- Copyright (C) 2019 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <resources xmlns:android="http://schemas.android.com/apk/res/android"> <overlayable name="SettingsToNotRestore"> <policy type="product|system|vendor"> <item type="array" name="restore_blocked_device_specific_settings" /> <item type="array" name="restore_blocked_global_settings" /> <item type="array" name="restore_blocked_secure_settings" /> <item type="array" name="restore_blocked_system_settings" /> </policy> </overlayable> </resources>
packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java +121 −22 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ import java.io.IOException; import java.io.OutputStream; import java.time.DateTimeException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Objects; Loading Loading @@ -250,7 +251,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { ParcelFileDescriptor newState) { throw new RuntimeException("SettingsBackupAgent has been migrated to use key exclusion"); } @Override public void onRestore(BackupDataInput data, long appVersionCode, ParcelFileDescriptor newState, Set<String> dynamicBlockList) throws IOException { if (DEBUG) { Log.d(TAG, "onRestore(): appVersionCode: " + appVersionCode Loading @@ -266,7 +273,7 @@ public class SettingsBackupAgent extends BackupAgentHelper { } // versionCode of com.android.providers.settings corresponds to SDK_INT mRestoredFromSdkInt = appVersionCode; mRestoredFromSdkInt = (int) appVersionCode; HashSet<String> movedToGlobal = new HashSet<String>(); Settings.System.getMovedToGlobalSettings(movedToGlobal); Loading @@ -292,16 +299,29 @@ public class SettingsBackupAgent extends BackupAgentHelper { switch (key) { case KEY_SYSTEM : restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal, movedToSecure); movedToSecure, R.array.restore_blocked_system_settings, dynamicBlockList); mSettingsHelper.applyAudioSettings(); break; case KEY_SECURE : restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal, null); restoreSettings( data, Settings.Secure.CONTENT_URI, movedToGlobal, null, R.array.restore_blocked_secure_settings, dynamicBlockList); break; case KEY_GLOBAL : restoreSettings(data, Settings.Global.CONTENT_URI, null, movedToSecure); restoreSettings( data, Settings.Global.CONTENT_URI, null, movedToSecure, R.array.restore_blocked_global_settings, dynamicBlockList); break; case KEY_WIFI_SUPPLICANT : Loading Loading @@ -345,7 +365,10 @@ public class SettingsBackupAgent extends BackupAgentHelper { case KEY_DEVICE_SPECIFIC_CONFIG: byte[] restoredDeviceSpecificConfig = new byte[size]; data.readEntityData(restoredDeviceSpecificConfig, 0, size); restoreDeviceSpecificConfig(restoredDeviceSpecificConfig); restoreDeviceSpecificConfig( restoredDeviceSpecificConfig, R.array.restore_blocked_device_specific_settings, dynamicBlockList); break; default : Loading Loading @@ -394,14 +417,22 @@ public class SettingsBackupAgent extends BackupAgentHelper { byte[] buffer = new byte[nBytes]; in.readFully(buffer, 0, nBytes); restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal, movedToSecure); movedToSecure, R.array.restore_blocked_system_settings, Collections.emptySet()); // secure settings nBytes = in.readInt(); if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data"); if (nBytes > buffer.length) buffer = new byte[nBytes]; in.readFully(buffer, 0, nBytes); restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, null); restoreSettings( buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, null, R.array.restore_blocked_secure_settings, Collections.emptySet()); // Global only if sufficiently new if (version >= FULL_BACKUP_ADDED_GLOBAL) { Loading @@ -411,7 +442,8 @@ public class SettingsBackupAgent extends BackupAgentHelper { in.readFully(buffer, 0, nBytes); movedToGlobal.clear(); // no redirection; this *is* the global namespace restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal, movedToSecure); movedToSecure, R.array.restore_blocked_global_settings, Collections.emptySet()); } // locale Loading Loading @@ -612,8 +644,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { return baos.toByteArray(); } private void restoreSettings(BackupDataInput data, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure) { private void restoreSettings( BackupDataInput data, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure, int blockedSettingsArrayId, Set<String> dynamicBlockList) { byte[] settings = new byte[data.getDataSize()]; try { data.readEntityData(settings, 0, settings.length); Loading @@ -621,16 +658,44 @@ public class SettingsBackupAgent extends BackupAgentHelper { Log.e(TAG, "Couldn't read entity data"); return; } restoreSettings(settings, settings.length, contentUri, movedToGlobal, movedToSecure); } private void restoreSettings(byte[] settings, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure) { restoreSettings(settings, 0, bytes, contentUri, movedToGlobal, movedToSecure); } private void restoreSettings(byte[] settings, int pos, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure) { restoreSettings( settings, settings.length, contentUri, movedToGlobal, movedToSecure, blockedSettingsArrayId, dynamicBlockList); } private void restoreSettings( byte[] settings, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure, int blockedSettingsArrayId, Set<String> dynamicBlockList) { restoreSettings( settings, 0, bytes, contentUri, movedToGlobal, movedToSecure, blockedSettingsArrayId, dynamicBlockList); } private void restoreSettings( byte[] settings, int pos, int bytes, Uri contentUri, HashSet<String> movedToGlobal, Set<String> movedToSecure, int blockedSettingsArrayId, Set<String> dynamicBlockList) { if (DEBUG) { Log.i(TAG, "restoreSettings: " + contentUri); } Loading Loading @@ -662,9 +727,20 @@ public class SettingsBackupAgent extends BackupAgentHelper { SettingsHelper settingsHelper = mSettingsHelper; ContentResolver cr = getContentResolver(); final int whiteListSize = whitelist.length; for (int i = 0; i < whiteListSize; i++) { String key = whitelist[i]; Set<String> blockedSettings = getBlockedSettings(blockedSettingsArrayId); for (String key : whitelist) { boolean isBlockedBySystem = blockedSettings != null && blockedSettings.contains(key); if (isBlockedBySystem || isBlockedByDynamicList(dynamicBlockList, contentUri, key)) { Log.i( TAG, "Key " + key + " removed from restore by " + (isBlockedBySystem ? "system" : "dynamic") + " block list"); continue; } String value = null; boolean hasValueToRestore = false; Loading Loading @@ -722,6 +798,19 @@ public class SettingsBackupAgent extends BackupAgentHelper { } } private boolean isBlockedByDynamicList(Set<String> dynamicBlockList, Uri areaUri, String key) { String contentKey = Uri.withAppendedPath(areaUri, key).toString(); return dynamicBlockList.contains(contentKey); } // 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 protected Set<String> getBlockedSettings(int blockedSettingsArrayId) { String[] blockedSettings = getResources().getStringArray(blockedSettingsArrayId); return new HashSet<>(Arrays.asList(blockedSettings)); } private boolean isValidSettingValue(String key, String value, Map<String, Validator> validators) { if (key == null || validators == null) { Loading Loading @@ -998,10 +1087,13 @@ public class SettingsBackupAgent extends BackupAgentHelper { * Restore the device specific settings. * * @param data The byte array holding a backed up version of another devices settings. * @param blockedSettingsArrayId The string array resource holding the settings not to restore. * @param dynamicBlocklist The dynamic list of settings not to restore fed into this agent. * @return true if the restore succeeded, false if it was stopped. */ @VisibleForTesting boolean restoreDeviceSpecificConfig(byte[] data) { boolean restoreDeviceSpecificConfig(byte[] data, int blockedSettingsArrayId, Set<String> dynamicBlocklist) { // We're using an AtomicInteger to wrap the position int and allow called methods to // modify it. AtomicInteger pos = new AtomicInteger(0); Loading @@ -1013,7 +1105,14 @@ public class SettingsBackupAgent extends BackupAgentHelper { int dataStart = pos.get(); restoreSettings( data, dataStart, data.length, Settings.Secure.CONTENT_URI, null, null); data, dataStart, data.length, Settings.Secure.CONTENT_URI, null, null, blockedSettingsArrayId, dynamicBlocklist); updateWindowManagerIfNeeded(originalDensity); Loading
packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java +49 −5 Original line number Diff line number Diff line Loading @@ -37,14 +37,14 @@ import android.test.mock.MockContentResolver; import androidx.test.runner.AndroidJUnit4; import com.android.internal.annotations.VisibleForTesting; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; Loading Loading @@ -85,11 +85,32 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest { assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries); mAgentUnderTest.restoreDeviceSpecificConfig(settingsBackup); mAgentUnderTest.restoreDeviceSpecificConfig( settingsBackup, R.array.restore_blocked_device_specific_settings, Collections.emptySet()); assertEquals("Not all values were restored.", TEST_VALUES, helper.mWrittenValues); } @Test public void testRoundTripDeviceSpecificSettingsWithBlock() throws IOException { TestSettingsHelper helper = new TestSettingsHelper(mContext); mAgentUnderTest.mSettingsHelper = helper; byte[] settingsBackup = mAgentUnderTest.getDeviceSpecificConfiguration(); assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries); mAgentUnderTest.setBlockedSettings(TEST_VALUES.keySet().toArray(new String[0])); mAgentUnderTest.restoreDeviceSpecificConfig( settingsBackup, R.array.restore_blocked_device_specific_settings, Collections.emptySet()); assertTrue("Not all values were blocked.", helper.mWrittenValues.isEmpty()); } @Test public void testGeneratedHeaderMatchesCurrentDevice() throws IOException { mAgentUnderTest.mSettingsHelper = new TestSettingsHelper(mContext); Loading Loading @@ -148,7 +169,10 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest { assertFalse( "Blocking isSourceAcceptable did not stop restore", mAgentUnderTest.restoreDeviceSpecificConfig(data)); mAgentUnderTest.restoreDeviceSpecificConfig( data, R.array.restore_blocked_device_specific_settings, Collections.emptySet())); } private byte[] generateUncorruptedHeader() throws IOException { Loading Loading @@ -184,14 +208,34 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest { } } private byte[] generateSingleKeyTestBackupData(String key, String value) throws IOException { try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { os.write(SettingsBackupAgent.toByteArray(key)); os.write(SettingsBackupAgent.toByteArray(value)); return os.toByteArray(); } } private static class TestFriendlySettingsBackupAgent extends SettingsBackupAgent { private Boolean mForcedDeviceInfoRestoreAcceptability = null; private String[] mBlockedSettings = null; void setForcedDeviceInfoRestoreAcceptability(boolean value) { mForcedDeviceInfoRestoreAcceptability = value; } @VisibleForTesting void setBlockedSettings(String... blockedSettings) { mBlockedSettings = blockedSettings; } @Override protected Set<String> getBlockedSettings(int blockedSettingsArrayId) { return mBlockedSettings == null ? super.getBlockedSettings(blockedSettingsArrayId) : new HashSet<>(Arrays.asList(mBlockedSettings)); } @Override boolean isSourceAcceptable(byte[] data, AtomicInteger pos) { return mForcedDeviceInfoRestoreAcceptability == null ? super.isSourceAcceptable(data, pos) Loading