Support disableIfNoEncryptionCapabilities attribute
Support disableIfNoEncryptionCapabilities attribute in the XML config specified by android:dataExtractionRules.The attribute, only applicable to <cloudBackup>, will disable cloud backup if the transport doesn't offer encryption. Bug: 180523028 Test: atest FullbackupRulesHostSideTest Change-Id: Ic6dab65834b51ff62c1e1a17b34b850f720681a1
This commit is contained in:
@@ -403,7 +403,7 @@ public abstract class BackupAgent extends ContextWrapper {
|
||||
public void onFullBackup(FullBackupDataOutput data) throws IOException {
|
||||
FullBackup.BackupScheme backupScheme = FullBackup.getBackupScheme(this,
|
||||
mOperationType);
|
||||
if (!isDeviceToDeviceMigration() && !backupScheme.isFullBackupContentEnabled()) {
|
||||
if (!backupScheme.isFullBackupEnabled(data.getTransportFlags())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -911,7 +911,7 @@ public abstract class BackupAgent extends ContextWrapper {
|
||||
}
|
||||
|
||||
FullBackup.BackupScheme bs = FullBackup.getBackupScheme(this, mOperationType);
|
||||
if (!bs.isFullBackupContentEnabled()) {
|
||||
if (!bs.isFullRestoreEnabled()) {
|
||||
if (Log.isLoggable(FullBackup.TAG_XML_PARSER, Log.VERBOSE)) {
|
||||
Log.v(FullBackup.TAG_XML_PARSER,
|
||||
"onRestoreFile \"" + destination.getCanonicalPath()
|
||||
|
||||
@@ -99,6 +99,8 @@ public class FullBackup {
|
||||
public static final String FLAG_REQUIRED_DEVICE_TO_DEVICE_TRANSFER = "deviceToDeviceTransfer";
|
||||
public static final String FLAG_REQUIRED_FAKE_CLIENT_SIDE_ENCRYPTION =
|
||||
"fakeClientSideEncryption";
|
||||
private static final String FLAG_DISABLE_IF_NO_ENCRYPTION_CAPABILITIES
|
||||
= "disableIfNoEncryptionCapabilities";
|
||||
|
||||
/**
|
||||
* When this change is enabled, include / exclude rules specified via
|
||||
@@ -307,6 +309,10 @@ public class FullBackup {
|
||||
// lazy initialized, only when needed
|
||||
private StorageVolume[] mVolumes = null;
|
||||
|
||||
// Properties the transport must have (e.g. encryption) for the operation to go ahead.
|
||||
@Nullable private Integer mRequiredTransportFlags;
|
||||
@Nullable private Boolean mIsUsingNewScheme;
|
||||
|
||||
/**
|
||||
* Parse out the semantic domains into the correct physical location.
|
||||
*/
|
||||
@@ -453,6 +459,35 @@ public class FullBackup {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isFullBackupEnabled(int transportFlags) {
|
||||
try {
|
||||
if (isUsingNewScheme()) {
|
||||
int requiredTransportFlags = getRequiredTransportFlags();
|
||||
// All bits that are set in requiredTransportFlags must be set in
|
||||
// transportFlags.
|
||||
return (transportFlags & requiredTransportFlags) == requiredTransportFlags;
|
||||
}
|
||||
} catch (IOException | XmlPullParserException e) {
|
||||
Slog.w(TAG, "Failed to interpret the backup scheme: " + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return isFullBackupContentEnabled();
|
||||
}
|
||||
|
||||
boolean isFullRestoreEnabled() {
|
||||
try {
|
||||
if (isUsingNewScheme()) {
|
||||
return true;
|
||||
}
|
||||
} catch (IOException | XmlPullParserException e) {
|
||||
Slog.w(TAG, "Failed to interpret the backup scheme: " + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return isFullBackupContentEnabled();
|
||||
}
|
||||
|
||||
boolean isFullBackupContentEnabled() {
|
||||
if (mFullBackupContent < 0) {
|
||||
// android:fullBackupContent="false", bail.
|
||||
@@ -491,10 +526,30 @@ public class FullBackup {
|
||||
return mExcludes;
|
||||
}
|
||||
|
||||
private synchronized int getRequiredTransportFlags()
|
||||
throws IOException, XmlPullParserException {
|
||||
if (mRequiredTransportFlags == null) {
|
||||
maybeParseBackupSchemeLocked();
|
||||
}
|
||||
|
||||
return mRequiredTransportFlags;
|
||||
}
|
||||
|
||||
private synchronized boolean isUsingNewScheme()
|
||||
throws IOException, XmlPullParserException {
|
||||
if (mIsUsingNewScheme == null) {
|
||||
maybeParseBackupSchemeLocked();
|
||||
}
|
||||
|
||||
return mIsUsingNewScheme;
|
||||
}
|
||||
|
||||
private void maybeParseBackupSchemeLocked() throws IOException, XmlPullParserException {
|
||||
// This not being null is how we know that we've tried to parse the xml already.
|
||||
mIncludes = new ArrayMap<String, Set<PathWithRequiredFlags>>();
|
||||
mExcludes = new ArraySet<PathWithRequiredFlags>();
|
||||
mRequiredTransportFlags = 0;
|
||||
mIsUsingNewScheme = false;
|
||||
|
||||
if (mFullBackupContent == 0 && mDataExtractionRules == 0) {
|
||||
// No scheme specified via either new or legacy config, will copy everything.
|
||||
@@ -535,12 +590,14 @@ public class FullBackup {
|
||||
}
|
||||
if (!mExcludes.isEmpty() || !mIncludes.isEmpty()) {
|
||||
// Found configuration in the new config, we will use it.
|
||||
mIsUsingNewScheme = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (operationType == OperationType.MIGRATION
|
||||
&& CompatChanges.isChangeEnabled(IGNORE_FULL_BACKUP_CONTENT_IN_D2D)) {
|
||||
mIsUsingNewScheme = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -584,13 +641,24 @@ public class FullBackup {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO(b/180523028): Parse required attributes for rules (e.g. encryption).
|
||||
parseRequiredTransportFlags(parser, configSection);
|
||||
parseRules(parser, excludes, includes, Optional.of(0), configSection);
|
||||
}
|
||||
|
||||
logParsingResults(excludes, includes);
|
||||
}
|
||||
|
||||
private void parseRequiredTransportFlags(XmlPullParser parser,
|
||||
@ConfigSection String configSection) {
|
||||
if (ConfigSection.CLOUD_BACKUP.equals(configSection)) {
|
||||
String encryptionAttribute = parser.getAttributeValue(/* namespace */ null,
|
||||
FLAG_DISABLE_IF_NO_ENCRYPTION_CAPABILITIES);
|
||||
if ("true".equals(encryptionAttribute)) {
|
||||
mRequiredTransportFlags = BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void parseBackupSchemeFromXmlLocked(XmlPullParser parser,
|
||||
Set<PathWithRequiredFlags> excludes,
|
||||
|
||||
@@ -165,6 +165,9 @@ public class LocalTransport extends BackupTransport {
|
||||
if (mParameters.isDeviceTransfer()) {
|
||||
flags |= BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER;
|
||||
}
|
||||
if (mParameters.isEncrypted()) {
|
||||
flags |= BackupAgent.FLAG_CLIENT_SIDE_ENCRYPTION_ENABLED;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,10 +28,12 @@ public class LocalTransportParameters extends KeyValueSettingObserver {
|
||||
private static final String KEY_FAKE_ENCRYPTION_FLAG = "fake_encryption_flag";
|
||||
private static final String KEY_NON_INCREMENTAL_ONLY = "non_incremental_only";
|
||||
private static final String KEY_IS_DEVICE_TRANSFER = "is_device_transfer";
|
||||
private static final String KEY_IS_ENCRYPTED = "is_encrypted";
|
||||
|
||||
private boolean mFakeEncryptionFlag;
|
||||
private boolean mIsNonIncrementalOnly;
|
||||
private boolean mIsDeviceTransfer;
|
||||
private boolean mIsEncrypted;
|
||||
|
||||
public LocalTransportParameters(Handler handler, ContentResolver resolver) {
|
||||
super(handler, resolver, Settings.Secure.getUriFor(SETTING));
|
||||
@@ -49,6 +51,10 @@ public class LocalTransportParameters extends KeyValueSettingObserver {
|
||||
return mIsDeviceTransfer;
|
||||
}
|
||||
|
||||
boolean isEncrypted() {
|
||||
return mIsEncrypted;
|
||||
}
|
||||
|
||||
public String getSettingValue(ContentResolver resolver) {
|
||||
return Settings.Secure.getString(resolver, SETTING);
|
||||
}
|
||||
@@ -57,5 +63,6 @@ public class LocalTransportParameters extends KeyValueSettingObserver {
|
||||
mFakeEncryptionFlag = parser.getBoolean(KEY_FAKE_ENCRYPTION_FLAG, false);
|
||||
mIsNonIncrementalOnly = parser.getBoolean(KEY_NON_INCREMENTAL_ONLY, false);
|
||||
mIsDeviceTransfer = parser.getBoolean(KEY_IS_DEVICE_TRANSFER, false);
|
||||
mIsEncrypted = parser.getBoolean(KEY_IS_ENCRYPTED, false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user