Calculate vbmetadigest of inactive slot am: 838793dc39

Original change: https://android-review.googlesource.com/c/platform/system/update_engine/+/1543621

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I83cfc98d87b98f2fb8778525ba43dee2f4c134d1
diff --git a/Android.bp b/Android.bp
index ebe43a9..be37dba 100644
--- a/Android.bp
+++ b/Android.bp
@@ -307,9 +307,12 @@
     ],
 
     static_libs: [
+        "libavb",
+        "libavb_user",
         "gkiprops",
         "libpayload_consumer",
         "libupdate_engine_boot_control",
+        "PlatformProperties",
     ],
     shared_libs: [
         "libandroid_net",
diff --git a/aosp/hardware_android.cc b/aosp/hardware_android.cc
index 6f884d4..0ac82d6 100644
--- a/aosp/hardware_android.cc
+++ b/aosp/hardware_android.cc
@@ -23,16 +23,24 @@
 #include <string_view>
 
 #include <android/sysprop/GkiProperties.sysprop.h>
-#include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <base/files/file_util.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/strings/string_util.h>
 #include <bootloader_message/bootloader_message.h>
+#include <fstab/fstab.h>
+#include <libavb/libavb.h>
+#include <libavb_user/avb_ops_user.h>
 
 #include "update_engine/common/error_code_utils.h"
 #include "update_engine/common/hardware.h"
 #include "update_engine/common/platform_constants.h"
 #include "update_engine/common/utils.h"
 
+#ifndef __ANDROID_RECOVERY__
+#include <android/sysprop/OtaProperties.sysprop.h>
+#endif
+
 using android::base::GetBoolProperty;
 using android::base::GetIntProperty;
 using android::base::GetProperty;
@@ -68,6 +76,40 @@
   return error_code;
 }
 
+void SetVbmetaDigestProp(const std::string& value) {
+#ifndef __ANDROID_RECOVERY__
+  if (!android::sysprop::OtaProperties::other_vbmeta_digest(value)) {
+    LOG(WARNING) << "Failed to set other vbmeta digest to " << value;
+  }
+#endif
+}
+
+std::string CalculateVbmetaDigestForInactiveSlot() {
+  AvbSlotVerifyData* avb_slot_data;
+
+  auto suffix = fs_mgr_get_other_slot_suffix();
+  const char* requested_partitions[] = {nullptr};
+  auto avb_ops = avb_ops_user_new();
+  auto verify_result = avb_slot_verify(avb_ops,
+                                       requested_partitions,
+                                       suffix.c_str(),
+                                       AVB_SLOT_VERIFY_FLAGS_NONE,
+                                       AVB_HASHTREE_ERROR_MODE_EIO,
+                                       &avb_slot_data);
+  if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) {
+    LOG(WARNING) << "Failed to verify avb slot data: " << verify_result;
+    return "";
+  }
+
+  uint8_t vbmeta_digest[AVB_SHA256_DIGEST_SIZE];
+  avb_slot_verify_data_calculate_vbmeta_digest(
+      avb_slot_data, AVB_DIGEST_TYPE_SHA256, vbmeta_digest);
+
+  std::string encoded_digest =
+      base::HexEncode(vbmeta_digest, AVB_SHA256_DIGEST_SIZE);
+  return base::ToLowerASCII(encoded_digest);
+}
+
 }  // namespace
 
 namespace hardware {
@@ -239,6 +281,30 @@
   }
 }
 
+void HardwareAndroid::SetVbmetaDigestForInactiveSlot(bool reset) {
+  if constexpr (constants::kIsRecovery) {
+    return;
+  }
+
+  if (android::base::GetProperty("ro.boot.avb_version", "").empty() &&
+      android::base::GetProperty("ro.boot.vbmeta.avb_version", "").empty()) {
+    LOG(INFO) << "Device doesn't use avb, skipping setting vbmeta digest";
+    return;
+  }
+
+  if (reset) {
+    SetVbmetaDigestProp("");
+    return;
+  }
+
+  std::string digest = CalculateVbmetaDigestForInactiveSlot();
+  if (digest.empty()) {
+    LOG(WARNING) << "Failed to calculate the vbmeta digest for the other slot";
+    return;
+  }
+  SetVbmetaDigestProp(digest);
+}
+
 string HardwareAndroid::GetVersionForLogging(
     const string& partition_name) const {
   if (partition_name == "boot") {
diff --git a/aosp/hardware_android.h b/aosp/hardware_android.h
index 5ffd7c5..78f056e 100644
--- a/aosp/hardware_android.h
+++ b/aosp/hardware_android.h
@@ -58,6 +58,7 @@
   bool GetFirstActiveOmahaPingSent() const override;
   bool SetFirstActiveOmahaPingSent() override;
   void SetWarmReset(bool warm_reset) override;
+  void SetVbmetaDigestForInactiveSlot(bool reset) override;
   [[nodiscard]] std::string GetVersionForLogging(
       const std::string& partition_name) const override;
   [[nodiscard]] ErrorCode IsPartitionUpdateValid(
diff --git a/aosp/update_attempter_android.cc b/aosp/update_attempter_android.cc
index eb1ebe0..96bb67c 100644
--- a/aosp/update_attempter_android.cc
+++ b/aosp/update_attempter_android.cc
@@ -374,6 +374,9 @@
       // Resets the warm reset property since we won't switch the slot.
       hardware_->SetWarmReset(false);
 
+      // Resets the vbmeta digest.
+      hardware_->SetVbmetaDigestForInactiveSlot(true /* reset */);
+
       // Remove update progress for DeltaPerformer and remove snapshots.
       if (!boot_control_->GetDynamicPartitionControl()->ResetUpdate(prefs_))
         ret_value = false;
diff --git a/common/fake_hardware.h b/common/fake_hardware.h
index 00a212e..29ba607 100644
--- a/common/fake_hardware.h
+++ b/common/fake_hardware.h
@@ -194,6 +194,8 @@
 
   void SetWarmReset(bool warm_reset) override { warm_reset_ = warm_reset; }
 
+  void SetVbmetaDigestForInactiveSlot(bool reset) override {}
+
   // Getters to verify state.
   int GetMaxKernelKeyRollforward() const { return kernel_max_rollforward_; }
 
diff --git a/common/hardware_interface.h b/common/hardware_interface.h
index cad32fc..7460097 100644
--- a/common/hardware_interface.h
+++ b/common/hardware_interface.h
@@ -137,6 +137,10 @@
   // needed on the next reboot. Otherwise, clears the flag.
   virtual void SetWarmReset(bool warm_reset) = 0;
 
+  // If not reset, sets the vbmeta digest of the inactive slot as a sysprop.
+  // Otherwise, clears the sysprop.
+  virtual void SetVbmetaDigestForInactiveSlot(bool reset) = 0;
+
   // Return the version/timestamp for partition `partition_name`.
   // Don't make any assumption about the formatting of returned string.
   // Only used for logging/debugging purposes.
diff --git a/cros/hardware_chromeos.cc b/cros/hardware_chromeos.cc
index 14f2497..a57cd78 100644
--- a/cros/hardware_chromeos.cc
+++ b/cros/hardware_chromeos.cc
@@ -349,6 +349,8 @@
 
 void HardwareChromeOS::SetWarmReset(bool warm_reset) {}
 
+void HardwareChromeOS::SetVbmetaDigestForInactiveSlot(bool reset) {}
+
 std::string HardwareChromeOS::GetVersionForLogging(
     const std::string& partition_name) const {
   // TODO(zhangkelvin) Implement per-partition timestamp for Chrome OS.
diff --git a/cros/hardware_chromeos.h b/cros/hardware_chromeos.h
index de84d78..8a920ef 100644
--- a/cros/hardware_chromeos.h
+++ b/cros/hardware_chromeos.h
@@ -62,6 +62,7 @@
   bool GetFirstActiveOmahaPingSent() const override;
   bool SetFirstActiveOmahaPingSent() override;
   void SetWarmReset(bool warm_reset) override;
+  void SetVbmetaDigestForInactiveSlot(bool reset) override;
   std::string GetVersionForLogging(
       const std::string& partition_name) const override;
   ErrorCode IsPartitionUpdateValid(
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index dc444c7..58d045b 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -374,6 +374,8 @@
       } else {
         // Schedules warm reset on next reboot, ignores the error.
         hardware_->SetWarmReset(true);
+        // Sets the vbmeta digest for the other slot to boot into.
+        hardware_->SetVbmetaDigestForInactiveSlot(false);
       }
     } else {
       error_code = ErrorCode::kUpdatedButNotActive;