aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYifan Hong <elsk@google.com>2020-04-08 19:42:18 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-04-08 19:42:18 +0000
commitd5300af3758c23bf4966daddb5db8309e7fcb573 (patch)
tree7a2738e3aa27f36ea63cd59a03fa523a56ff8b72
parentb447317e4e71f22c11c132a4d81398fcdb8344ce (diff)
parentf7339988c6b09dcbb2d0e3847ced760f813adf41 (diff)
downloadupdate_engine-d5300af3758c23bf4966daddb5db8309e7fcb573.tar.gz
Add DynamicPartitionControl::EraseSystemOtherAvbFooter am: cba9c46108 am: f7339988c6
Change-Id: I94c71ebc6dfc5958aea871fc5f91e45baa45b6ab
-rw-r--r--Android.bp3
-rw-r--r--dynamic_partition_control_android.cc214
-rw-r--r--dynamic_partition_control_android.h37
-rw-r--r--dynamic_partition_control_android_unittest.cc141
-rw-r--r--dynamic_partition_test_utils.h4
-rw-r--r--mock_dynamic_partition_control.h24
6 files changed, 413 insertions, 10 deletions
diff --git a/Android.bp b/Android.bp
index e3116f57..07eee639 100644
--- a/Android.bp
+++ b/Android.bp
@@ -211,6 +211,9 @@ cc_defaults {
"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 09f61adb..1e92f45b 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 @@ constexpr char kRetrfoitDynamicPartitions[] =
"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 @@ bool DynamicPartitionControlAndroid::PreparePartitionsForUpdate(
<< "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 @@ bool DynamicPartitionControlAndroid::PreparePartitionsForUpdate(
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 @@ bool DynamicPartitionControlAndroid::PreparePartitionsForUpdate(
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 6dbe3704..9dcdcf1a 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -136,6 +136,43 @@ class DynamicPartitionControlAndroid : public DynamicPartitionControlInterface {
// 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 457ea108..20819182 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::AnyOf;
using testing::Invoke;
using testing::NiceMock;
using testing::Not;
+using testing::Optional;
using testing::Return;
namespace chromeos_update_engine {
@@ -64,6 +69,9 @@ class DynamicPartitionControlAndroidTest : public ::testing::Test {
*device = GetDmDevice(partition_name_suffix);
return true;
}));
+
+ ON_CALL(dynamicControl(), EraseSystemOtherAvbFooter(_, _))
+ .WillByDefault(Return(true));
}
// Return the mocked DynamicPartitionControlInterface.
@@ -90,12 +98,15 @@ class DynamicPartitionControlAndroidTest : public ::testing::Test {
// 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 @@ TEST_F(DynamicPartitionControlAndroidTest, ResetUpdate) {
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 346998fc..70a176b5 100644
--- a/dynamic_partition_test_utils.h
+++ b/dynamic_partition_test_utils.h
@@ -175,7 +175,7 @@ inline DeltaArchiveManifest PartitionSizesToManifest(
}
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 @@ inline std::unique_ptr<MetadataBuilder> NewFakeMetadata(
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 169c2657..1e4e5fd8 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -77,10 +77,34 @@ class MockDynamicPartitionControlAndroid
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