Loading services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +19 −8 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -697,11 +698,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { mStageName = new File(backupManagerService.getDataDir(), packageName + ".stage"); mNewStateName = new File(mStateDir, packageName + ".new"); // don't stage the 'android' package where the wallpaper data lives. this is // an optimization: we know there's no widget data hosted/published by that // package, and this way we avoid doing a spurious copy of MB-sized wallpaper // data following the download. boolean staging = !packageName.equals(PLATFORM_PACKAGE_NAME); boolean staging = shouldStageBackupData(packageName); ParcelFileDescriptor stage; File downloadFile = (staging) ? mStageName : mBackupDataName; boolean startedAgentRestore = false; Loading Loading @@ -768,8 +765,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { startedAgentRestore = true; mAgent.doRestoreWithExcludedKeys(mBackupData, appVersionCode, mNewState, mEphemeralOpToken, backupManagerService.getBackupManagerBinder(), mExcludedKeys.containsKey(packageName) ? new ArrayList<>(mExcludedKeys.get(packageName)) : null); new ArrayList<>(getExcludedKeysForPackage(packageName))); } catch (Exception e) { Slog.e(TAG, "Unable to call app for restore: " + packageName, e); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, Loading @@ -784,10 +780,25 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { } } @VisibleForTesting boolean shouldStageBackupData(String packageName) { // Backup data is staged for 2 reasons: // 1. We might need to exclude keys from the data before passing it to the agent // 2. Widget metadata needs to be separated from the rest to be handled separately // But 'android' package doesn't contain widget metadata so we want to skip staging for it // when there are no keys to be excluded either. return !packageName.equals(PLATFORM_PACKAGE_NAME) || !getExcludedKeysForPackage(PLATFORM_PACKAGE_NAME).isEmpty(); } private Set<String> getExcludedKeysForPackage(String packageName) { return mExcludedKeys.getOrDefault(packageName, Collections.emptySet()); } @VisibleForTesting void filterExcludedKeys(String packageName, BackupDataInput in, BackupDataOutput out) throws Exception { Set<String> excludedKeysForPackage = mExcludedKeys.get(packageName); Set<String> excludedKeysForPackage = getExcludedKeysForPackage(packageName); byte[] buffer = new byte[8192]; // will grow when needed while (in.readNextHeader()) { Loading services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java +34 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.when; Loading Loading @@ -55,6 +54,8 @@ public class PerformUnifiedRestoreTaskTest { private static final String INCLUDED_KEY = "included_key"; private static final String EXCLUDED_KEY_1 = "excluded_key_1"; private static final String EXCLUDED_KEY_2 = "excluded_key_2"; private static final String SYSTEM_PACKAGE_NAME = "android"; private static final String NON_SYSTEM_PACKAGE_NAME = "package"; @Mock private BackupDataInput mBackupDataInput; @Mock private BackupDataOutput mBackupDataOutput; Loading Loading @@ -98,9 +99,6 @@ public class PerformUnifiedRestoreTaskTest { return null; } }); mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); } private void populateTestData() { Loading @@ -116,6 +114,8 @@ public class PerformUnifiedRestoreTaskTest { @Test public void testFilterExcludedKeys() throws Exception { mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); mRestoreTask.filterExcludedKeys(PACKAGE_NAME, mBackupDataInput, mBackupDataOutput); // Verify only the correct were written into BackupDataOutput object. Loading @@ -123,4 +123,34 @@ public class PerformUnifiedRestoreTaskTest { allowedBackupKeys.removeAll(mExcludedkeys); assertEquals(allowedBackupKeys, mBackupDataDump); } @Test public void testStageBackupData_stageForNonSystemPackageWithKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME)); } @Test public void testStageBackupData_stageForNonSystemPackageWithNoKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap()); assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME)); } @Test public void testStageBackupData_doNotStageForSystemPackageWithNoKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap()); assertFalse(mRestoreTask.shouldStageBackupData(SYSTEM_PACKAGE_NAME)); } @Test public void testStageBackupData_stageForSystemPackageWithKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME)); } } Loading
services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java +19 −8 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; Loading Loading @@ -697,11 +698,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { mStageName = new File(backupManagerService.getDataDir(), packageName + ".stage"); mNewStateName = new File(mStateDir, packageName + ".new"); // don't stage the 'android' package where the wallpaper data lives. this is // an optimization: we know there's no widget data hosted/published by that // package, and this way we avoid doing a spurious copy of MB-sized wallpaper // data following the download. boolean staging = !packageName.equals(PLATFORM_PACKAGE_NAME); boolean staging = shouldStageBackupData(packageName); ParcelFileDescriptor stage; File downloadFile = (staging) ? mStageName : mBackupDataName; boolean startedAgentRestore = false; Loading Loading @@ -768,8 +765,7 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { startedAgentRestore = true; mAgent.doRestoreWithExcludedKeys(mBackupData, appVersionCode, mNewState, mEphemeralOpToken, backupManagerService.getBackupManagerBinder(), mExcludedKeys.containsKey(packageName) ? new ArrayList<>(mExcludedKeys.get(packageName)) : null); new ArrayList<>(getExcludedKeysForPackage(packageName))); } catch (Exception e) { Slog.e(TAG, "Unable to call app for restore: " + packageName, e); EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, Loading @@ -784,10 +780,25 @@ public class PerformUnifiedRestoreTask implements BackupRestoreTask { } } @VisibleForTesting boolean shouldStageBackupData(String packageName) { // Backup data is staged for 2 reasons: // 1. We might need to exclude keys from the data before passing it to the agent // 2. Widget metadata needs to be separated from the rest to be handled separately // But 'android' package doesn't contain widget metadata so we want to skip staging for it // when there are no keys to be excluded either. return !packageName.equals(PLATFORM_PACKAGE_NAME) || !getExcludedKeysForPackage(PLATFORM_PACKAGE_NAME).isEmpty(); } private Set<String> getExcludedKeysForPackage(String packageName) { return mExcludedKeys.getOrDefault(packageName, Collections.emptySet()); } @VisibleForTesting void filterExcludedKeys(String packageName, BackupDataInput in, BackupDataOutput out) throws Exception { Set<String> excludedKeysForPackage = mExcludedKeys.get(packageName); Set<String> excludedKeysForPackage = getExcludedKeysForPackage(packageName); byte[] buffer = new byte[8192]; // will grow when needed while (in.readNextHeader()) { Loading
services/tests/servicestests/src/com/android/server/backup/restore/PerformUnifiedRestoreTaskTest.java +34 −4 Original line number Diff line number Diff line Loading @@ -20,7 +20,6 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.when; Loading Loading @@ -55,6 +54,8 @@ public class PerformUnifiedRestoreTaskTest { private static final String INCLUDED_KEY = "included_key"; private static final String EXCLUDED_KEY_1 = "excluded_key_1"; private static final String EXCLUDED_KEY_2 = "excluded_key_2"; private static final String SYSTEM_PACKAGE_NAME = "android"; private static final String NON_SYSTEM_PACKAGE_NAME = "package"; @Mock private BackupDataInput mBackupDataInput; @Mock private BackupDataOutput mBackupDataOutput; Loading Loading @@ -98,9 +99,6 @@ public class PerformUnifiedRestoreTaskTest { return null; } }); mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); } private void populateTestData() { Loading @@ -116,6 +114,8 @@ public class PerformUnifiedRestoreTaskTest { @Test public void testFilterExcludedKeys() throws Exception { mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); mRestoreTask.filterExcludedKeys(PACKAGE_NAME, mBackupDataInput, mBackupDataOutput); // Verify only the correct were written into BackupDataOutput object. Loading @@ -123,4 +123,34 @@ public class PerformUnifiedRestoreTaskTest { allowedBackupKeys.removeAll(mExcludedkeys); assertEquals(allowedBackupKeys, mBackupDataDump); } @Test public void testStageBackupData_stageForNonSystemPackageWithKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME)); } @Test public void testStageBackupData_stageForNonSystemPackageWithNoKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap()); assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME)); } @Test public void testStageBackupData_doNotStageForSystemPackageWithNoKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.emptyMap()); assertFalse(mRestoreTask.shouldStageBackupData(SYSTEM_PACKAGE_NAME)); } @Test public void testStageBackupData_stageForSystemPackageWithKeysToExclude() { mRestoreTask = new PerformUnifiedRestoreTask(Collections.singletonMap( PACKAGE_NAME, mExcludedkeys)); assertTrue(mRestoreTask.shouldStageBackupData(NON_SYSTEM_PACKAGE_NAME)); } }