Merge "Skip QD1A.190821.011 in stage-aosp-master" into stage-aosp-master
diff --git a/Android.bp b/Android.bp
index a691e7e..54fd0c2 100644
--- a/Android.bp
+++ b/Android.bp
@@ -204,6 +204,7 @@
"liblp",
"libutils",
"android.hardware.boot@1.0",
+ "android.hardware.boot@1.1",
],
target: {
recovery: {
@@ -306,7 +307,7 @@
static_libs: ["libupdate_engine_android"],
required: [
"cacerts_google",
- "update_engine_payload_key",
+ "otacerts",
],
srcs: ["main.cc"],
@@ -380,7 +381,7 @@
},
required: [
- "update_engine_payload_key.recovery",
+ "otacerts.recovery",
],
}
diff --git a/boot_control_android.cc b/boot_control_android.cc
index 4a010bd..b1d775e 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -308,12 +308,8 @@
return true;
}
- if (!update_metadata) {
- return true;
- }
-
return dynamic_control_->PreparePartitionsForUpdate(
- source_slot, target_slot, manifest);
+ source_slot, target_slot, manifest, update_metadata);
}
} // namespace chromeos_update_engine
diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc
index f090de2..e44af15 100644
--- a/boot_control_android_unittest.cc
+++ b/boot_control_android_unittest.cc
@@ -197,6 +197,9 @@
{T("system"), 2_GiB},
{T("vendor"), 1_GiB}});
+ EXPECT_CALL(dynamicControl(), PreparePartitionsForUpdate(_, _, _, false))
+ .WillOnce(Return(true));
+
EXPECT_TRUE(PreparePartitionsForUpdate(
target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc
index 8dcf343..e194670 100644
--- a/dynamic_partition_control_android.cc
+++ b/dynamic_partition_control_android.cc
@@ -62,13 +62,6 @@
// needs to be mapped, this timeout is longer than |kMapTimeout|.
constexpr std::chrono::milliseconds kMapSnapshotTimeout{5000};
-DynamicPartitionControlAndroid::DynamicPartitionControlAndroid() {
- if (GetVirtualAbFeatureFlag().IsEnabled()) {
- snapshot_ = android::snapshot::SnapshotManager::New();
- CHECK(snapshot_ != nullptr) << "Cannot initialize SnapshotManager.";
- }
-}
-
DynamicPartitionControlAndroid::~DynamicPartitionControlAndroid() {
CleanupInternal(false /* wait */);
}
@@ -91,12 +84,22 @@
return FeatureFlag(FeatureFlag::Value::NONE);
}
+DynamicPartitionControlAndroid::DynamicPartitionControlAndroid()
+ : dynamic_partitions_(
+ GetFeatureFlag(kUseDynamicPartitions, kRetrfoitDynamicPartitions)),
+ virtual_ab_(GetFeatureFlag(kVirtualAbEnabled, kVirtualAbRetrofit)) {
+ if (GetVirtualAbFeatureFlag().IsEnabled()) {
+ snapshot_ = android::snapshot::SnapshotManager::New();
+ CHECK(snapshot_ != nullptr) << "Cannot initialize SnapshotManager.";
+ }
+}
+
FeatureFlag DynamicPartitionControlAndroid::GetDynamicPartitionsFeatureFlag() {
- return GetFeatureFlag(kUseDynamicPartitions, kRetrfoitDynamicPartitions);
+ return dynamic_partitions_;
}
FeatureFlag DynamicPartitionControlAndroid::GetVirtualAbFeatureFlag() {
- return GetFeatureFlag(kVirtualAbEnabled, kVirtualAbRetrofit);
+ return virtual_ab_;
}
bool DynamicPartitionControlAndroid::MapPartitionInternal(
@@ -112,7 +115,8 @@
.force_writable = force_writable,
};
bool success = false;
- if (GetVirtualAbFeatureFlag().IsEnabled() && force_writable) {
+ if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_ &&
+ force_writable) {
// Only target partitions are mapped with force_writable. On Virtual
// A/B devices, target partitions may overlap with source partitions, so
// they must be mapped with snapshot.
@@ -256,8 +260,12 @@
builder =
MetadataBuilder::New(PartitionOpener(), super_device, source_slot);
} else {
- builder = MetadataBuilder::NewForUpdate(
- PartitionOpener(), super_device, source_slot, target_slot);
+ bool always_keep_source_slot = !target_supports_snapshot_;
+ builder = MetadataBuilder::NewForUpdate(PartitionOpener(),
+ super_device,
+ source_slot,
+ target_slot,
+ always_keep_source_slot);
}
if (builder == nullptr) {
@@ -343,13 +351,35 @@
bool DynamicPartitionControlAndroid::PreparePartitionsForUpdate(
uint32_t source_slot,
uint32_t target_slot,
- const DeltaArchiveManifest& manifest) {
- // TODO(elsk): Also call PrepareDynamicPartitionsForUpdate when applying
- // downgrade packages on retrofit Virtual A/B devices and when applying
- // secondary OTA. b/138258570
+ const DeltaArchiveManifest& manifest,
+ bool update) {
+ target_supports_snapshot_ =
+ manifest.dynamic_partition_metadata().snapshot_enabled();
+
+ if (!update)
+ return true;
+
if (GetVirtualAbFeatureFlag().IsEnabled()) {
- return PrepareSnapshotPartitionsForUpdate(
- source_slot, target_slot, manifest);
+ // On Virtual A/B device, either CancelUpdate() or BeginUpdate() must be
+ // called before calling UnmapUpdateSnapshot.
+ // - If target_supports_snapshot_, PrepareSnapshotPartitionsForUpdate()
+ // calls BeginUpdate() which resets update state
+ // - If !target_supports_snapshot_, explicitly CancelUpdate().
+ if (target_supports_snapshot_) {
+ return PrepareSnapshotPartitionsForUpdate(
+ source_slot, target_slot, manifest);
+ }
+
+ if (GetVirtualAbFeatureFlag().IsLaunch() && !target_supports_snapshot_) {
+ LOG(ERROR) << "Cannot downgrade to a build that does not support "
+ << "snapshots because this device launches with Virtual A/B.";
+ return false;
+ }
+
+ if (!snapshot_->CancelUpdate()) {
+ LOG(ERROR) << "Cannot cancel previous update.";
+ return false;
+ }
}
return PrepareDynamicPartitionsForUpdate(source_slot, target_slot, manifest);
}
@@ -418,6 +448,11 @@
MetadataBuilder* builder,
uint32_t target_slot,
const DeltaArchiveManifest& manifest) {
+ // If applying downgrade from Virtual A/B to non-Virtual A/B, the left-over
+ // COW group needs to be deleted to ensure there are enough space to create
+ // target partitions.
+ builder->RemoveGroupAndPartitions(android::snapshot::kCowGroupName);
+
const std::string target_suffix = SlotSuffixForSlotNumber(target_slot);
DeleteGroupsWithSuffix(builder, target_suffix);
@@ -491,10 +526,11 @@
}
bool DynamicPartitionControlAndroid::FinishUpdate() {
- if (!GetVirtualAbFeatureFlag().IsEnabled())
- return true;
- LOG(INFO) << "Snapshot writes are done.";
- return snapshot_->FinishedSnapshotWrites();
+ if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_) {
+ LOG(INFO) << "Snapshot writes are done.";
+ return snapshot_->FinishedSnapshotWrites();
+ }
+ return true;
}
} // namespace chromeos_update_engine
diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h
index f9dfd89..d70a2aa 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -46,10 +46,10 @@
std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder(
const std::string& super_device, uint32_t source_slot) override;
- bool PreparePartitionsForUpdate(
- uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest) override;
+ bool PreparePartitionsForUpdate(uint32_t source_slot,
+ uint32_t target_slot,
+ const DeltaArchiveManifest& manifest,
+ bool update) override;
bool GetDeviceDir(std::string* path) override;
std::string GetSuperPartitionName(uint32_t slot) override;
bool FinishUpdate() override;
@@ -112,7 +112,10 @@
const DeltaArchiveManifest& manifest);
std::set<std::string> mapped_devices_;
+ const FeatureFlag dynamic_partitions_;
+ const FeatureFlag virtual_ab_;
std::unique_ptr<android::snapshot::SnapshotManager> snapshot_;
+ bool target_supports_snapshot_ = false;
DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid);
};
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
index 552774e..e8ef1f9 100644
--- a/dynamic_partition_control_android_unittest.cc
+++ b/dynamic_partition_control_android_unittest.cc
@@ -112,7 +112,7 @@
}
bool PreparePartitionsForUpdate(const PartitionSizes& partition_sizes) {
return dynamicControl().PreparePartitionsForUpdate(
- source(), target(), PartitionSizesToManifest(partition_sizes));
+ source(), target(), PartitionSizesToManifest(partition_sizes), true);
}
void SetSlots(const TestParam& slots) { slots_ = slots; }
diff --git a/dynamic_partition_control_interface.h b/dynamic_partition_control_interface.h
index 0ccfcd6..9c18973 100644
--- a/dynamic_partition_control_interface.h
+++ b/dynamic_partition_control_interface.h
@@ -36,6 +36,7 @@
constexpr explicit FeatureFlag(Value value) : value_(value) {}
constexpr bool IsEnabled() const { return value_ != Value::NONE; }
constexpr bool IsRetrofit() const { return value_ == Value::RETROFIT; }
+ constexpr bool IsLaunch() const { return value_ == Value::LAUNCH; }
private:
Value value_;
@@ -92,10 +93,11 @@
// Prepare all partitions for an update specified in |manifest|.
// This is needed before calling MapPartitionOnDeviceMapper(), otherwise the
// device would be mapped in an inconsistent way.
- virtual bool PreparePartitionsForUpdate(
- uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest) = 0;
+ // If |update| is set, create snapshots and writes super partition metadata.
+ virtual bool PreparePartitionsForUpdate(uint32_t source_slot,
+ uint32_t target_slot,
+ const DeltaArchiveManifest& manifest,
+ bool update) = 0;
// Return a possible location for devices listed by name.
virtual bool GetDeviceDir(std::string* path) = 0;
diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h
index 1af6cfe..8146e0f 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -44,8 +44,8 @@
const std::string&, uint32_t));
MOCK_METHOD1(GetDeviceDir, bool(std::string*));
MOCK_METHOD0(GetDynamicPartitionsFeatureFlag, FeatureFlag());
- MOCK_METHOD3(PreparePartitionsForUpdate,
- bool(uint32_t, uint32_t, const DeltaArchiveManifest&));
+ MOCK_METHOD4(PreparePartitionsForUpdate,
+ bool(uint32_t, uint32_t, const DeltaArchiveManifest&, bool));
MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
MOCK_METHOD0(FinishUpdate, bool());
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 4b80ae6..4aec00b 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -527,18 +527,19 @@
<< "Trusting metadata size in payload = " << metadata_size_;
}
- // Perform the verification unconditionally.
auto [payload_verifier, perform_verification] = CreatePayloadVerifier();
if (!payload_verifier) {
LOG(ERROR) << "Failed to create payload verifier.";
*error = ErrorCode::kDownloadMetadataSignatureVerificationError;
- return MetadataParseResult::kError;
+ if (perform_verification) {
+ return MetadataParseResult::kError;
+ }
+ } else {
+ // We have the full metadata in |payload|. Verify its integrity
+ // and authenticity based on the information we have in Omaha response.
+ *error = payload_metadata_.ValidateMetadataSignature(
+ payload, payload_->metadata_signature, *payload_verifier);
}
-
- // We have the full metadata in |payload|. Verify its integrity
- // and authenticity based on the information we have in Omaha response.
- *error = payload_metadata_.ValidateMetadataSignature(
- payload, payload_->metadata_signature, *payload_verifier);
if (*error != ErrorCode::kSuccess) {
if (install_plan_->hash_checks_mandatory) {
// The autoupdate_CatchBadSignatures test checks for this string