Make FullBackup::BackupScheme aware of operation type

We currently maintain an instance of FullBackup::BackupScheme
(encapsulates full backup policies, including include / exclude rules)
per package. In line with the new include / exclude config format, where
the rules for each operation types are separate, create BackupScheme per
(package; operation type) pair to  make sure we're only dealing with the
policies relevant to the current operation.

Bug: 174216309
Test: atest FullBackupRulesHostSideTest
Change-Id: I627584186a1d1faf3d699e734e45f5e943ec1f84
This commit is contained in:
Ruslan Tkhakokhov
2021-02-11 15:03:39 +00:00
parent 5b94267c37
commit 4f60c64516
2 changed files with 57 additions and 13 deletions

View File

@@ -401,7 +401,8 @@ public abstract class BackupAgent extends ContextWrapper {
* @see #onRestoreFile(ParcelFileDescriptor, long, File, int, long, long)
*/
public void onFullBackup(FullBackupDataOutput data) throws IOException {
FullBackup.BackupScheme backupScheme = FullBackup.getBackupScheme(this);
FullBackup.BackupScheme backupScheme = FullBackup.getBackupScheme(this,
mOperationType);
if (!isDeviceToDeviceMigration() && !backupScheme.isFullBackupContentEnabled()) {
return;
}
@@ -624,7 +625,8 @@ public abstract class BackupAgent extends ContextWrapper {
if (includeMap == null || includeMap.size() == 0) {
// Do entire sub-tree for the provided token.
fullBackupFileTree(packageName, domainToken,
FullBackup.getBackupScheme(this).tokenToDirectoryPath(domainToken),
FullBackup.getBackupScheme(this, mOperationType)
.tokenToDirectoryPath(domainToken),
filterSet, traversalExcludeSet, data);
} else if (includeMap.get(domainToken) != null) {
// This will be null if the xml parsing didn't yield any rules for
@@ -795,7 +797,8 @@ public abstract class BackupAgent extends ContextWrapper {
ArraySet<String> systemExcludes,
FullBackupDataOutput output) {
// Pull out the domain and set it aside to use when making the tarball.
String domainPath = FullBackup.getBackupScheme(this).tokenToDirectoryPath(domain);
String domainPath = FullBackup.getBackupScheme(this, mOperationType)
.tokenToDirectoryPath(domain);
if (domainPath == null) {
// Should never happen.
return;
@@ -911,7 +914,7 @@ public abstract class BackupAgent extends ContextWrapper {
return true;
}
FullBackup.BackupScheme bs = FullBackup.getBackupScheme(this);
FullBackup.BackupScheme bs = FullBackup.getBackupScheme(this, mOperationType);
if (!bs.isFullBackupContentEnabled()) {
if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
Log.v(FullBackup.TAG_XML_PARSER,
@@ -985,7 +988,8 @@ public abstract class BackupAgent extends ContextWrapper {
+ " domain=" + domain + " relpath=" + path + " mode=" + mode
+ " mtime=" + mtime);
basePath = FullBackup.getBackupScheme(this).tokenToDirectoryPath(domain);
basePath = FullBackup.getBackupScheme(this, mOperationType).tokenToDirectoryPath(
domain);
if (domain.equals(FullBackup.MANAGED_EXTERNAL_TREE_TOKEN)) {
mode = -1; // < 0 is a token to skip attempting a chmod()
}

View File

@@ -16,6 +16,9 @@
package android.app.backup;
import static android.app.backup.BackupManager.OperationType;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -41,6 +44,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -89,6 +93,38 @@ public class FullBackup {
public static final String FLAG_REQUIRED_FAKE_CLIENT_SIDE_ENCRYPTION =
"fakeClientSideEncryption";
/**
* Identify {@link BackupScheme} object by package and operation type
* (see {@link OperationType}) it corresponds to.
*/
private static class BackupSchemeId {
final String mPackageName;
@OperationType final int mOperationType;
BackupSchemeId(String packageName, @OperationType int operationType) {
mPackageName = packageName;
mOperationType = operationType;
}
@Override
public int hashCode() {
return Objects.hash(mPackageName, mOperationType);
}
@Override
public boolean equals(@Nullable Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
BackupSchemeId that = (BackupSchemeId) object;
return Objects.equals(mPackageName, that.mPackageName) &&
Objects.equals(mOperationType, that.mOperationType);
}
}
/**
* @hide
*/
@@ -96,21 +132,23 @@ public class FullBackup {
static public native int backupToTar(String packageName, String domain,
String linkdomain, String rootpath, String path, FullBackupDataOutput output);
private static final Map<String, BackupScheme> kPackageBackupSchemeMap =
new ArrayMap<String, BackupScheme>();
private static final Map<BackupSchemeId, BackupScheme> kPackageBackupSchemeMap =
new ArrayMap<>();
static synchronized BackupScheme getBackupScheme(Context context) {
static synchronized BackupScheme getBackupScheme(Context context,
@OperationType int operationType) {
BackupSchemeId backupSchemeId = new BackupSchemeId(context.getPackageName(), operationType);
BackupScheme backupSchemeForPackage =
kPackageBackupSchemeMap.get(context.getPackageName());
kPackageBackupSchemeMap.get(backupSchemeId);
if (backupSchemeForPackage == null) {
backupSchemeForPackage = new BackupScheme(context);
kPackageBackupSchemeMap.put(context.getPackageName(), backupSchemeForPackage);
backupSchemeForPackage = new BackupScheme(context, operationType);
kPackageBackupSchemeMap.put(backupSchemeId, backupSchemeForPackage);
}
return backupSchemeForPackage;
}
public static BackupScheme getBackupSchemeForTest(Context context) {
BackupScheme testing = new BackupScheme(context);
BackupScheme testing = new BackupScheme(context, OperationType.BACKUP);
testing.mExcludes = new ArraySet();
testing.mIncludes = new ArrayMap();
return testing;
@@ -236,6 +274,7 @@ public class FullBackup {
private final static String TAG_EXCLUDE = "exclude";
final int mFullBackupContent;
@OperationType final int mOperationType;
final PackageManager mPackageManager;
final StorageManager mStorageManager;
final String mPackageName;
@@ -354,8 +393,9 @@ public class FullBackup {
*/
ArraySet<PathWithRequiredFlags> mExcludes;
BackupScheme(Context context) {
BackupScheme(Context context, @OperationType int operationType) {
mFullBackupContent = context.getApplicationInfo().fullBackupContent;
mOperationType = operationType;
mStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
mPackageManager = context.getPackageManager();
mPackageName = context.getPackageName();