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