Merge changes from topic "sideload_logging" into rvc-dev

* changes:
  sideload: fix duplicated logging
  Revert "Setup android-base logging in sideload."
diff --git a/Android.bp b/Android.bp
index 0d5469c..3287b7b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -211,6 +211,9 @@
         "android.hardware.boot@1.0",
         "android.hardware.boot@1.1",
     ],
+    header_libs: [
+        "avb_headers",
+    ],
     target: {
         recovery: {
             static_libs: [
diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc
index 09f61ad..1e92f45 100644
--- a/dynamic_partition_control_android.cc
+++ b/dynamic_partition_control_android.cc
@@ -32,6 +32,7 @@
 #include <fs_mgr.h>
 #include <fs_mgr_dm_linear.h>
 #include <fs_mgr_overlayfs.h>
+#include <libavb/libavb.h>
 #include <libdm/dm.h>
 #include <libsnapshot/snapshot.h>
 
@@ -42,12 +43,14 @@
 #include "update_engine/payload_consumer/delta_performer.h"
 
 using android::base::GetBoolProperty;
+using android::base::GetProperty;
 using android::base::Join;
 using android::dm::DeviceMapper;
 using android::dm::DmDeviceState;
 using android::fs_mgr::CreateLogicalPartition;
 using android::fs_mgr::CreateLogicalPartitionParams;
 using android::fs_mgr::DestroyLogicalPartition;
+using android::fs_mgr::Fstab;
 using android::fs_mgr::MetadataBuilder;
 using android::fs_mgr::Partition;
 using android::fs_mgr::PartitionOpener;
@@ -64,6 +67,7 @@
     "ro.boot.dynamic_partitions_retrofit";
 constexpr char kVirtualAbEnabled[] = "ro.virtual_ab.enabled";
 constexpr char kVirtualAbRetrofit[] = "ro.virtual_ab.retrofit";
+constexpr char kPostinstallFstabPrefix[] = "ro.postinstall.fstab.prefix";
 // Map timeout for dynamic partitions.
 constexpr std::chrono::milliseconds kMapTimeout{1000};
 // Map timeout for dynamic partitions with snapshots. Since several devices
@@ -401,6 +405,15 @@
         << "run adb enable-verity to deactivate if required and try again.";
   }
 
+  if (GetVirtualAbFeatureFlag().IsEnabled() && metadata_device_ == nullptr) {
+    metadata_device_ = snapshot_->EnsureMetadataMounted();
+    TEST_AND_RETURN_FALSE(metadata_device_ != nullptr);
+  }
+
+  if (update) {
+    TEST_AND_RETURN_FALSE(EraseSystemOtherAvbFooter(source_slot, target_slot));
+  }
+
   if (!GetDynamicPartitionsFeatureFlag().IsEnabled()) {
     return true;
   }
@@ -421,11 +434,6 @@
   target_supports_snapshot_ =
       manifest.dynamic_partition_metadata().snapshot_enabled();
 
-  if (GetVirtualAbFeatureFlag().IsEnabled()) {
-    metadata_device_ = snapshot_->EnsureMetadataMounted();
-    TEST_AND_RETURN_FALSE(metadata_device_ != nullptr);
-  }
-
   if (!update)
     return true;
 
@@ -471,6 +479,202 @@
       source_slot, target_slot, manifest, delete_source);
 }
 
+namespace {
+// Try our best to erase AVB footer.
+class AvbFooterEraser {
+ public:
+  explicit AvbFooterEraser(const std::string& path) : path_(path) {}
+  bool Erase() {
+    // Try to mark the block device read-only. Ignore any
+    // failure since this won't work when passing regular files.
+    ignore_result(utils::SetBlockDeviceReadOnly(path_, false /* readonly */));
+
+    fd_.reset(new EintrSafeFileDescriptor());
+    int flags = O_WRONLY | O_TRUNC | O_CLOEXEC | O_SYNC;
+    TEST_AND_RETURN_FALSE(fd_->Open(path_.c_str(), flags));
+
+    // Need to write end-AVB_FOOTER_SIZE to end.
+    static_assert(AVB_FOOTER_SIZE > 0);
+    off64_t offset = fd_->Seek(-AVB_FOOTER_SIZE, SEEK_END);
+    TEST_AND_RETURN_FALSE_ERRNO(offset >= 0);
+    uint64_t write_size = AVB_FOOTER_SIZE;
+    LOG(INFO) << "Zeroing " << path_ << " @ [" << offset << ", "
+              << (offset + write_size) << "] (" << write_size << " bytes)";
+    brillo::Blob zeros(write_size);
+    TEST_AND_RETURN_FALSE(utils::WriteAll(fd_, zeros.data(), zeros.size()));
+    return true;
+  }
+  ~AvbFooterEraser() {
+    TEST_AND_RETURN(fd_ != nullptr && fd_->IsOpen());
+    if (!fd_->Close()) {
+      LOG(WARNING) << "Failed to close fd for " << path_;
+    }
+  }
+
+ private:
+  std::string path_;
+  FileDescriptorPtr fd_;
+};
+
+}  // namespace
+
+std::optional<bool>
+DynamicPartitionControlAndroid::IsAvbEnabledOnSystemOther() {
+  auto prefix = GetProperty(kPostinstallFstabPrefix, "");
+  if (prefix.empty()) {
+    LOG(WARNING) << "Cannot get " << kPostinstallFstabPrefix;
+    return std::nullopt;
+  }
+  auto path = base::FilePath(prefix).Append("etc/fstab.postinstall").value();
+  return IsAvbEnabledInFstab(path);
+}
+
+std::optional<bool> DynamicPartitionControlAndroid::IsAvbEnabledInFstab(
+    const std::string& path) {
+  Fstab fstab;
+  if (!ReadFstabFromFile(path, &fstab)) {
+    LOG(WARNING) << "Cannot read fstab from " << path;
+    return std::nullopt;
+  }
+  for (const auto& entry : fstab) {
+    if (!entry.avb_keys.empty()) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool DynamicPartitionControlAndroid::GetSystemOtherPath(
+    uint32_t source_slot,
+    uint32_t target_slot,
+    const std::string& partition_name_suffix,
+    std::string* path,
+    bool* should_unmap) {
+  path->clear();
+  *should_unmap = false;
+
+  // In recovery, just erase no matter what.
+  //   - On devices with retrofit dynamic partitions, no logical partitions
+  //     should be mounted at this point. Hence it should be safe to erase.
+  // Otherwise, do check that AVB is enabled on system_other before erasing.
+  if (!IsRecovery()) {
+    auto has_avb = IsAvbEnabledOnSystemOther();
+    TEST_AND_RETURN_FALSE(has_avb.has_value());
+    if (!has_avb.value()) {
+      LOG(INFO) << "AVB is not enabled on system_other. Skip erasing.";
+      return true;
+    }
+
+    // Found unexpected avb_keys for system_other on devices retrofitting
+    // dynamic partitions. Previous crash in update_engine may leave logical
+    // partitions mapped on physical system_other partition. It is difficult to
+    // handle these cases. Just fail.
+    if (GetDynamicPartitionsFeatureFlag().IsRetrofit()) {
+      LOG(ERROR) << "Cannot erase AVB footer on system_other on devices with "
+                 << "retrofit dynamic partitions. They should not have AVB "
+                 << "enabled on system_other.";
+      return false;
+    }
+  }
+
+  std::string device_dir_str;
+  TEST_AND_RETURN_FALSE(GetDeviceDir(&device_dir_str));
+  base::FilePath device_dir(device_dir_str);
+
+  // On devices without dynamic partition, search for static partitions.
+  if (!GetDynamicPartitionsFeatureFlag().IsEnabled()) {
+    *path = device_dir.Append(partition_name_suffix).value();
+    TEST_AND_RETURN_FALSE(DeviceExists(*path));
+    return true;
+  }
+
+  auto source_super_device =
+      device_dir.Append(GetSuperPartitionName(source_slot)).value();
+
+  auto builder = LoadMetadataBuilder(source_super_device, source_slot);
+  if (builder == nullptr) {
+    if (IsRecovery()) {
+      // It might be corrupted for some reason. It should still be able to
+      // sideload.
+      LOG(WARNING) << "Super partition metadata cannot be read from the source "
+                   << "slot, skip erasing.";
+      return true;
+    } else {
+      // Device has booted into Android mode, indicating that the super
+      // partition metadata should be there.
+      LOG(ERROR) << "Super partition metadata cannot be read from the source "
+                 << "slot. This is unexpected on devices with dynamic "
+                 << "partitions enabled.";
+      return false;
+    }
+  }
+  auto p = builder->FindPartition(partition_name_suffix);
+  if (p == nullptr) {
+    // If the source slot is flashed without system_other, it does not exist
+    // in super partition metadata at source slot. It is safe to skip it.
+    LOG(INFO) << "Can't find " << partition_name_suffix
+              << " in metadata source slot, skip erasing.";
+    return true;
+  }
+  // System_other created by flashing tools should be erased.
+  // If partition is created by update_engine (via NewForUpdate), it is a
+  // left-over partition from the previous update and does not contain
+  // system_other, hence there is no need to erase.
+  // Note the reverse is not necessary true. If the flag is not set, we don't
+  // know if the partition is created by update_engine or by flashing tools
+  // because older versions of super partition metadata does not contain this
+  // flag. It is okay to erase the AVB footer anyways.
+  if (p->attributes() & LP_PARTITION_ATTR_UPDATED) {
+    LOG(INFO) << partition_name_suffix
+              << " does not contain system_other, skip erasing.";
+    return true;
+  }
+
+  // Delete any pre-existing device with name |partition_name_suffix| and
+  // also remove it from |mapped_devices_|.
+  TEST_AND_RETURN_FALSE(UnmapPartitionOnDeviceMapper(partition_name_suffix));
+  // Use CreateLogicalPartition directly to avoid mapping with existing
+  // snapshots.
+  CreateLogicalPartitionParams params = {
+      .block_device = source_super_device,
+      .metadata_slot = source_slot,
+      .partition_name = partition_name_suffix,
+      .force_writable = true,
+      .timeout_ms = kMapTimeout,
+  };
+  TEST_AND_RETURN_FALSE(CreateLogicalPartition(params, path));
+  *should_unmap = true;
+  return true;
+}
+
+bool DynamicPartitionControlAndroid::EraseSystemOtherAvbFooter(
+    uint32_t source_slot, uint32_t target_slot) {
+  LOG(INFO) << "Erasing AVB footer of system_other partition before update.";
+
+  const std::string target_suffix = SlotSuffixForSlotNumber(target_slot);
+  const std::string partition_name_suffix = "system" + target_suffix;
+
+  std::string path;
+  bool should_unmap = false;
+
+  TEST_AND_RETURN_FALSE(GetSystemOtherPath(
+      source_slot, target_slot, partition_name_suffix, &path, &should_unmap));
+
+  if (path.empty()) {
+    return true;
+  }
+
+  bool ret = AvbFooterEraser(path).Erase();
+
+  // Delete |partition_name_suffix| from device mapper and from
+  // |mapped_devices_| again so that it does not interfere with update process.
+  if (should_unmap) {
+    TEST_AND_RETURN_FALSE(UnmapPartitionOnDeviceMapper(partition_name_suffix));
+  }
+
+  return ret;
+}
+
 bool DynamicPartitionControlAndroid::PrepareDynamicPartitionsForUpdate(
     uint32_t source_slot,
     uint32_t target_slot,
diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h
index 6dbe370..9dcdcf1 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -136,6 +136,43 @@
   // Allow mock objects to override this to test recovery mode.
   virtual bool IsRecovery();
 
+  // Determine path for system_other partition.
+  // |source_slot| should be current slot.
+  // |target_slot| should be "other" slot.
+  // |partition_name_suffix| should be "system" + suffix(|target_slot|).
+  // Return true and set |path| if successful.
+  // Set |path| to empty if no need to erase system_other.
+  // Set |should_unmap| to true if path needs to be unmapped later.
+  //
+  // Note: system_other cannot use GetPartitionDevice or
+  // GetDynamicPartitionDevice because:
+  // - super partition metadata may be loaded from the source slot
+  // - UPDATED flag needs to be check to skip erasing if partition is not
+  //   created by flashing tools
+  // - Snapshots from previous update attempts should not be used.
+  virtual bool GetSystemOtherPath(uint32_t source_slot,
+                                  uint32_t target_slot,
+                                  const std::string& partition_name_suffix,
+                                  std::string* path,
+                                  bool* should_unmap);
+
+  // Returns true if any entry in the fstab file in |path| has AVB enabled,
+  // false if not enabled, and nullopt for any error.
+  virtual std::optional<bool> IsAvbEnabledInFstab(const std::string& path);
+
+  // Returns true if system_other has AVB enabled, false if not enabled, and
+  // nullopt for any error.
+  virtual std::optional<bool> IsAvbEnabledOnSystemOther();
+
+  // Erase system_other partition that may contain system_other.img.
+  // After the update, the content of system_other may be corrupted but with
+  // valid AVB footer. If the update is rolled back and factory data reset is
+  // triggered, system_b fails to be mapped with verity errors (see
+  // b/152444348). Erase the system_other so that mapping system_other is
+  // skipped.
+  virtual bool EraseSystemOtherAvbFooter(uint32_t source_slot,
+                                         uint32_t target_slot);
+
  private:
   friend class DynamicPartitionControlAndroidTest;
 
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
index 457ea10..2081918 100644
--- a/dynamic_partition_control_android_unittest.cc
+++ b/dynamic_partition_control_android_unittest.cc
@@ -23,12 +23,16 @@
 #include <base/strings/string_util.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <libavb/libavb.h>
 
 #include "update_engine/common/mock_prefs.h"
+#include "update_engine/common/test_utils.h"
 #include "update_engine/dynamic_partition_test_utils.h"
 #include "update_engine/mock_dynamic_partition_control.h"
 
 using android::dm::DmDeviceState;
+using chromeos_update_engine::test_utils::ScopedLoopbackDeviceBinder;
+using chromeos_update_engine::test_utils::ScopedTempFile;
 using std::string;
 using testing::_;
 using testing::AnyNumber;
@@ -36,6 +40,7 @@
 using testing::Invoke;
 using testing::NiceMock;
 using testing::Not;
+using testing::Optional;
 using testing::Return;
 
 namespace chromeos_update_engine {
@@ -64,6 +69,9 @@
           *device = GetDmDevice(partition_name_suffix);
           return true;
         }));
+
+    ON_CALL(dynamicControl(), EraseSystemOtherAvbFooter(_, _))
+        .WillByDefault(Return(true));
   }
 
   // Return the mocked DynamicPartitionControlInterface.
@@ -90,12 +98,15 @@
 
   // Set the fake metadata to return when LoadMetadataBuilder is called on
   // |slot|.
-  void SetMetadata(uint32_t slot, const PartitionSuffixSizes& sizes) {
+  void SetMetadata(uint32_t slot,
+                   const PartitionSuffixSizes& sizes,
+                   uint32_t partition_attr = 0) {
     EXPECT_CALL(dynamicControl(),
                 LoadMetadataBuilder(GetSuperDevice(slot), slot, _))
         .Times(AnyNumber())
-        .WillRepeatedly(Invoke([sizes](auto, auto, auto) {
-          return NewFakeMetadata(PartitionSuffixSizesToManifest(sizes));
+        .WillRepeatedly(Invoke([sizes, partition_attr](auto, auto, auto) {
+          return NewFakeMetadata(PartitionSuffixSizesToManifest(sizes),
+                                 partition_attr);
         }));
   }
 
@@ -757,4 +768,128 @@
   ASSERT_TRUE(dynamicControl().ResetUpdate(&prefs));
 }
 
+TEST_F(DynamicPartitionControlAndroidTest, IsAvbNotEnabledInFstab) {
+  // clang-format off
+  std::string fstab_content =
+      "system /postinstall ext4 ro,nosuid,nodev,noexec slotselect_other,logical\n"  // NOLINT(whitespace/line_length)
+      "/dev/block/by-name/system /postinstall ext4 ro,nosuid,nodev,noexec slotselect_other\n";  // NOLINT(whitespace/line_length)
+  // clang-format on
+  ScopedTempFile fstab;
+  ASSERT_TRUE(test_utils::WriteFileString(fstab.path(), fstab_content));
+  ASSERT_THAT(dynamicControl().RealIsAvbEnabledInFstab(fstab.path()),
+              Optional(false));
+}
+
+TEST_F(DynamicPartitionControlAndroidTest, IsAvbEnabledInFstab) {
+  // clang-format off
+  std::string fstab_content =
+      "system /postinstall ext4 ro,nosuid,nodev,noexec slotselect_other,logical,avb_keys=/foo\n";  // NOLINT(whitespace/line_length)
+  // clang-format on
+  ScopedTempFile fstab;
+  ASSERT_TRUE(test_utils::WriteFileString(fstab.path(), fstab_content));
+  ASSERT_THAT(dynamicControl().RealIsAvbEnabledInFstab(fstab.path()),
+              Optional(true));
+}
+
+TEST_P(DynamicPartitionControlAndroidTestP, AvbNotEnabledOnSystemOther) {
+  ON_CALL(dynamicControl(), GetSystemOtherPath(_, _, _, _, _))
+      .WillByDefault(Invoke([&](auto source_slot,
+                                auto target_slot,
+                                const auto& name,
+                                auto path,
+                                auto should_unmap) {
+        return dynamicControl().RealGetSystemOtherPath(
+            source_slot, target_slot, name, path, should_unmap);
+      }));
+  ON_CALL(dynamicControl(), IsAvbEnabledOnSystemOther())
+      .WillByDefault(Return(false));
+  EXPECT_TRUE(
+      dynamicControl().RealEraseSystemOtherAvbFooter(source(), target()));
+}
+
+TEST_P(DynamicPartitionControlAndroidTestP, NoSystemOtherToErase) {
+  SetMetadata(source(), {{S("system"), 100_MiB}});
+  ON_CALL(dynamicControl(), IsAvbEnabledOnSystemOther())
+      .WillByDefault(Return(true));
+  std::string path;
+  bool should_unmap;
+  ASSERT_TRUE(dynamicControl().RealGetSystemOtherPath(
+      source(), target(), T("system"), &path, &should_unmap));
+  ASSERT_TRUE(path.empty()) << path;
+  ASSERT_FALSE(should_unmap);
+  ON_CALL(dynamicControl(), GetSystemOtherPath(_, _, _, _, _))
+      .WillByDefault(Invoke([&](auto source_slot,
+                                auto target_slot,
+                                const auto& name,
+                                auto path,
+                                auto should_unmap) {
+        return dynamicControl().RealGetSystemOtherPath(
+            source_slot, target_slot, name, path, should_unmap);
+      }));
+  EXPECT_TRUE(
+      dynamicControl().RealEraseSystemOtherAvbFooter(source(), target()));
+}
+
+TEST_P(DynamicPartitionControlAndroidTestP, SkipEraseUpdatedSystemOther) {
+  PartitionSuffixSizes sizes{{S("system"), 100_MiB}, {T("system"), 100_MiB}};
+  SetMetadata(source(), sizes, LP_PARTITION_ATTR_UPDATED);
+  ON_CALL(dynamicControl(), IsAvbEnabledOnSystemOther())
+      .WillByDefault(Return(true));
+  std::string path;
+  bool should_unmap;
+  ASSERT_TRUE(dynamicControl().RealGetSystemOtherPath(
+      source(), target(), T("system"), &path, &should_unmap));
+  ASSERT_TRUE(path.empty()) << path;
+  ASSERT_FALSE(should_unmap);
+  ON_CALL(dynamicControl(), GetSystemOtherPath(_, _, _, _, _))
+      .WillByDefault(Invoke([&](auto source_slot,
+                                auto target_slot,
+                                const auto& name,
+                                auto path,
+                                auto should_unmap) {
+        return dynamicControl().RealGetSystemOtherPath(
+            source_slot, target_slot, name, path, should_unmap);
+      }));
+  EXPECT_TRUE(
+      dynamicControl().RealEraseSystemOtherAvbFooter(source(), target()));
+}
+
+TEST_P(DynamicPartitionControlAndroidTestP, EraseSystemOtherAvbFooter) {
+  constexpr uint64_t file_size = 1_MiB;
+  static_assert(file_size > AVB_FOOTER_SIZE);
+  ScopedTempFile system_other;
+  brillo::Blob original(file_size, 'X');
+  ASSERT_TRUE(test_utils::WriteFileVector(system_other.path(), original));
+  std::string mnt_path;
+  ScopedLoopbackDeviceBinder dev(system_other.path(), true, &mnt_path);
+  ASSERT_TRUE(dev.is_bound());
+
+  brillo::Blob device_content;
+  ASSERT_TRUE(utils::ReadFile(mnt_path, &device_content));
+  ASSERT_EQ(original, device_content);
+
+  PartitionSuffixSizes sizes{{S("system"), 100_MiB}, {T("system"), file_size}};
+  SetMetadata(source(), sizes);
+  ON_CALL(dynamicControl(), IsAvbEnabledOnSystemOther())
+      .WillByDefault(Return(true));
+  EXPECT_CALL(dynamicControl(),
+              GetSystemOtherPath(source(), target(), T("system"), _, _))
+      .WillRepeatedly(
+          Invoke([&](auto, auto, const auto&, auto path, auto should_unmap) {
+            *path = mnt_path;
+            *should_unmap = false;
+            return true;
+          }));
+  ASSERT_TRUE(
+      dynamicControl().RealEraseSystemOtherAvbFooter(source(), target()));
+
+  device_content.clear();
+  ASSERT_TRUE(utils::ReadFile(mnt_path, &device_content));
+  brillo::Blob new_expected(original);
+  // Clear the last AVB_FOOTER_SIZE bytes.
+  new_expected.resize(file_size - AVB_FOOTER_SIZE);
+  new_expected.resize(file_size, '\0');
+  ASSERT_EQ(new_expected, device_content);
+}
+
 }  // namespace chromeos_update_engine
diff --git a/dynamic_partition_test_utils.h b/dynamic_partition_test_utils.h
index 346998f..70a176b 100644
--- a/dynamic_partition_test_utils.h
+++ b/dynamic_partition_test_utils.h
@@ -175,7 +175,7 @@
 }
 
 inline std::unique_ptr<MetadataBuilder> NewFakeMetadata(
-    const DeltaArchiveManifest& manifest) {
+    const DeltaArchiveManifest& manifest, uint32_t partition_attr = 0) {
   auto builder =
       MetadataBuilder::New(kDefaultSuperSize, kFakeMetadataSize, kMaxNumSlots);
   for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
@@ -183,7 +183,7 @@
     for (const auto& partition_name : group.partition_names()) {
       EXPECT_NE(
           nullptr,
-          builder->AddPartition(partition_name, group.name(), 0 /* attr */));
+          builder->AddPartition(partition_name, group.name(), partition_attr));
     }
   }
   for (const auto& partition : manifest.partitions()) {
diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h
index 169c265..1e4e5fd 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -77,10 +77,34 @@
   MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
   MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
   MOCK_METHOD1(FinishUpdate, bool(bool));
+  MOCK_METHOD5(
+      GetSystemOtherPath,
+      bool(uint32_t, uint32_t, const std::string&, std::string*, bool*));
+  MOCK_METHOD2(EraseSystemOtherAvbFooter, bool(uint32_t, uint32_t));
+  MOCK_METHOD0(IsAvbEnabledOnSystemOther, std::optional<bool>());
 
   void set_fake_mapped_devices(const std::set<std::string>& fake) override {
     DynamicPartitionControlAndroid::set_fake_mapped_devices(fake);
   }
+
+  bool RealGetSystemOtherPath(uint32_t source_slot,
+                              uint32_t target_slot,
+                              const std::string& partition_name_suffix,
+                              std::string* path,
+                              bool* should_unmap) {
+    return DynamicPartitionControlAndroid::GetSystemOtherPath(
+        source_slot, target_slot, partition_name_suffix, path, should_unmap);
+  }
+
+  bool RealEraseSystemOtherAvbFooter(uint32_t source_slot,
+                                     uint32_t target_slot) {
+    return DynamicPartitionControlAndroid::EraseSystemOtherAvbFooter(
+        source_slot, target_slot);
+  }
+
+  std::optional<bool> RealIsAvbEnabledInFstab(const std::string& path) {
+    return DynamicPartitionControlAndroid::IsAvbEnabledInFstab(path);
+  }
 };
 
 }  // namespace chromeos_update_engine