summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Beatrice Marchegiani <beatricemarch@google.com> 2024-05-27 08:02:06 +0000
committer Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> 2024-05-27 08:02:06 +0000
commit1b3b8c1cb3d8332e36cdf641332ae79bc7fb523e (patch)
tree76452a734e05639d8e9eb39aece24260fcb1f15a
parent617a314a5fd7027bcdbb4a8c40ec305bbc1971db (diff)
parent0753af02fc618e830dddbe41689c7949d00ace71 (diff)
Merge "Fix downgrade wallpaper restore bug" into 24D1-dev am: 0753af02fc
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/27486895 Change-Id: I552392cf12b59ba0c931cbc246bd3791f799162b Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java3
-rw-r--r--services/backup/java/com/android/server/backup/utils/TarBackupReader.java51
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java149
3 files changed, 199 insertions, 4 deletions
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index b414b252cc37..2d99c96452da 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -270,7 +270,8 @@ public class FullRestoreEngine extends RestoreEngine {
PackageManagerInternal.class);
RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy(
mBackupManagerService.getPackageManager(), allowApks, info, signatures,
- pmi, mUserId, mBackupEligibilityRules);
+ pmi, mUserId, mBackupEligibilityRules,
+ mBackupManagerService.getContext());
mManifestSignatures.put(info.packageName, signatures);
mPackagePolicies.put(pkg, restorePolicy);
mPackageInstallers.put(pkg, info.installerPackageName);
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index 78a9952d066d..4860a274cfa8 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -31,6 +31,7 @@ import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_FULL_RESTORE_
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_MISSING_SIGNATURE;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_VERSION;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_V_TO_U_RESTORE_PKG_ELIGIBLE;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
@@ -53,17 +54,22 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
+import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
+import android.provider.Settings;
import android.util.Slog;
import com.android.server.backup.FileMetadata;
+import com.android.server.backup.Flags;
import com.android.server.backup.restore.RestorePolicy;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
/**
* Utility methods to read backup tar file.
@@ -390,7 +396,7 @@ public class TarBackupReader {
boolean allowApks, FileMetadata info, Signature[] signatures,
PackageManagerInternal pmi, int userId, Context context) {
return chooseRestorePolicy(packageManager, allowApks, info, signatures, pmi, userId,
- BackupEligibilityRules.forBackup(packageManager, pmi, userId, context));
+ BackupEligibilityRules.forBackup(packageManager, pmi, userId, context), context);
}
/**
@@ -406,7 +412,8 @@ public class TarBackupReader {
*/
public RestorePolicy chooseRestorePolicy(PackageManager packageManager,
boolean allowApks, FileMetadata info, Signature[] signatures,
- PackageManagerInternal pmi, int userId, BackupEligibilityRules eligibilityRules) {
+ PackageManagerInternal pmi, int userId, BackupEligibilityRules eligibilityRules,
+ Context context) {
if (signatures == null) {
return RestorePolicy.IGNORE;
}
@@ -448,6 +455,16 @@ public class TarBackupReader {
pkgInfo,
LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
null);
+ } else if (isAllowlistedForVToURestore(info, pkgInfo, userId, context)) {
+ Slog.i(TAG, "Performing a V to U downgrade; package: "
+ + info.packageName
+ + " is allowlisted");
+ policy = RestorePolicy.ACCEPT;
+ mBackupManagerMonitorEventSender.monitorEvent(
+ LOG_EVENT_ID_V_TO_U_RESTORE_PKG_ELIGIBLE,
+ pkgInfo,
+ LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY,
+ null);
} else {
// The data is from a newer version of the app than
// is presently installed. That means we can only
@@ -751,6 +768,36 @@ public class TarBackupReader {
return true;
}
+ // checks the sdk of the target/source device for a B&R operation.
+ // system components can opt in of V->U restore via allowlist.
+ @SuppressWarnings("AndroidFrameworkCompatChange")
+ private boolean isAllowlistedForVToURestore(FileMetadata backupFileInfo,
+ PackageInfo installedPackageInfo,
+ int userId, Context context) {
+ // We assume that the package version matches the sdk (e.g. version 35 means V).
+ // This is true for most of the system components ( and it is specifically true for those
+ // that are in the allowlist)
+ // In order to check if this is a V to U transfer we check if the package version from the
+ // backup is 35 and on the target is 34.
+ // We don't need to check the V to U denylist here since a package can only make it
+ // to TarBackupReader if allowed and not denied (from PerformUnifiedRestoreTask)
+
+ String vToUAllowlist = getVToUAllowlist(context, userId);
+ List<String> mVToUAllowlist = Arrays.asList(vToUAllowlist.split(","));
+ return Flags.enableVToURestoreForSystemComponentsInAllowlist()
+ && (installedPackageInfo.getLongVersionCode()
+ == Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ && (backupFileInfo.version > Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ && (mVToUAllowlist.contains(installedPackageInfo.packageName));
+ }
+
+ private String getVToUAllowlist(Context context, int userId) {
+ return Settings.Secure.getStringForUser(
+ context.getContentResolver(),
+ Settings.Secure.V_TO_U_RESTORE_ALLOWLIST,
+ userId);
+ }
+
private static long extractRadix(byte[] data, int offset, int maxChars, int radix)
throws IOException {
long value = 0;
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 33995653870e..396f4da75172 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -25,6 +25,7 @@ import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_RESTORE_ANY_V
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_SYSTEM_APP_NO_AGENT;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSIONS_MATCH;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER;
+import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_V_TO_U_RESTORE_PKG_ELIGIBLE;
import static com.google.common.truth.Truth.assertThat;
@@ -42,17 +43,23 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
import android.content.pm.SigningInfo;
+import android.os.Build;
import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
+import android.testing.TestableContext;
import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.mockingservicestests.R;
import com.android.server.backup.FileMetadata;
+import com.android.server.backup.Flags;
import com.android.server.backup.UserBackupManagerService;
import com.android.server.backup.restore.PerformAdbRestoreTask;
import com.android.server.backup.restore.RestorePolicy;
@@ -61,6 +68,7 @@ import com.android.server.backup.testutils.PackageManagerStub;
import com.google.common.hash.Hashing;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -86,6 +94,8 @@ public class TarBackupReaderTest {
@Mock private BytesReadListener mBytesReadListenerMock;
@Mock private IBackupManagerMonitor mBackupManagerMonitorMock;
@Mock private PackageManagerInternal mMockPackageManagerInternal;
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private final PackageManagerStub mPackageManagerStub = new PackageManagerStub();
private Context mContext;
@@ -95,7 +105,7 @@ public class TarBackupReaderTest {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mContext = InstrumentationRegistry.getContext();
+ mContext = new TestableContext(ApplicationProvider.getApplicationContext());
mUserId = UserHandle.USER_SYSTEM;
}
@@ -515,6 +525,107 @@ public class TarBackupReaderTest {
@Test
public void
+ chooseRestorePolicy_flagOnNotRestoreAnyVersionVToURestoreAndInAllowlist_returnsIgnore()
+ throws Exception {
+
+ mSetFlagsRule.enableFlags(
+ Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST);
+
+ TarBackupReader tarBackupReader = createTarBackupReader();
+
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, "test");
+
+ Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+ FileMetadata info = new FileMetadata();
+ info.version = Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1;
+
+ PackageInfo packageInfo = createNonRestoreAnyVersionUPackage();
+ PackageManagerStub.sPackageInfo = packageInfo;
+
+ doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+ packageInfo.packageName);
+ RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+ false /* allowApks */, info, signatures, mMockPackageManagerInternal,
+ mUserId, mContext);
+
+ assertThat(policy).isEqualTo(RestorePolicy.ACCEPT);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+ assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+ LOG_EVENT_ID_V_TO_U_RESTORE_PKG_ELIGIBLE);
+ }
+
+
+ @Test
+ public void
+ chooseRestorePolicy_flagOffNotRestoreAnyVersionVToURestoreAndInAllowlist_returnsAccept()
+ throws Exception {
+
+ mSetFlagsRule.disableFlags(
+ Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST);
+
+ TarBackupReader tarBackupReader = createTarBackupReader();
+
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, "test");
+
+ Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+ FileMetadata info = new FileMetadata();
+ info.version = Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1;
+
+ PackageInfo packageInfo = createNonRestoreAnyVersionUPackage();
+ PackageManagerStub.sPackageInfo = packageInfo;
+
+ doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+ packageInfo.packageName);
+ RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+ false /* allowApks */, info, signatures, mMockPackageManagerInternal,
+ mUserId, mContext);
+
+ assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+ assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+ LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
+
+ }
+
+ @Test
+ public void
+ chooseRestorePolicy_flagOnNotRestoreAnyVersionVToURestoreAndNotInAllowlist_returnsIgnore()
+ throws Exception {
+
+ mSetFlagsRule.enableFlags(
+ Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST);
+
+ TarBackupReader tarBackupReader = createTarBackupReader();
+
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, "pkg");
+
+ Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+ FileMetadata info = new FileMetadata();
+ info.version = Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1;
+
+ PackageInfo packageInfo = createNonRestoreAnyVersionUPackage();
+ PackageManagerStub.sPackageInfo = packageInfo;
+
+ doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+ packageInfo.packageName);
+ RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+ false /* allowApks */, info, signatures, mMockPackageManagerInternal,
+ mUserId, mContext);
+
+ assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+ assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+ LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
+ }
+
+ @Test
+ public void
chooseRestorePolicy_notRestoreAnyVersionAndVersionMismatchButAllowApksAndHasApk_returnsAcceptIfApk()
throws Exception {
InputStream inputStream = mContext.getResources().openRawResource(
@@ -523,6 +634,10 @@ public class TarBackupReaderTest {
inputStream, null);
TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
mBytesReadListenerMock, mBackupManagerMonitorMock);
+
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, "pkg");
+
Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
FileMetadata info = new FileMetadata();
info.version = 2;
@@ -564,6 +679,10 @@ public class TarBackupReaderTest {
inputStream, null);
TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
mBytesReadListenerMock, mBackupManagerMonitorMock);
+
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.V_TO_U_RESTORE_ALLOWLIST, "pkg");
+
Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
FileMetadata info = new FileMetadata();
info.version = 2;
@@ -596,5 +715,33 @@ public class TarBackupReaderTest {
assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
}
+
+ private TarBackupReader createTarBackupReader() throws Exception {
+ InputStream inputStream = mContext.getResources().openRawResource(
+ R.raw.backup_telephony_no_password);
+ InputStream tarInputStream = PerformAdbRestoreTask.parseBackupFileHeaderAndReturnTarStream(
+ inputStream, null);
+ TarBackupReader tarBackupReader = new TarBackupReader(tarInputStream,
+ mBytesReadListenerMock, mBackupManagerMonitorMock);
+ return tarBackupReader;
+ }
+
+ private PackageInfo createNonRestoreAnyVersionUPackage(){
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = "test";
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+ packageInfo.applicationInfo.flags &= ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
+ packageInfo.applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+ packageInfo.applicationInfo.backupAgentName = null;
+ packageInfo.signingInfo = new SigningInfo(
+ new SigningDetails(
+ new Signature[]{FAKE_SIGNATURE_1},
+ SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
+ null,
+ null));
+ packageInfo.versionCode = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+ return packageInfo;
+ }
}