Merge "Integrate libsnapshot with the boot control HAL."
This commit is contained in:
commit
c243e19936
7 changed files with 146 additions and 5 deletions
|
@ -28,6 +28,7 @@ cc_defaults {
|
|||
"liblp",
|
||||
],
|
||||
static_libs: [
|
||||
"libcutils",
|
||||
"libdm",
|
||||
"libfs_mgr",
|
||||
"libfstab",
|
||||
|
@ -56,6 +57,17 @@ cc_defaults {
|
|||
},
|
||||
}
|
||||
|
||||
cc_defaults {
|
||||
name: "libsnapshot_hal_deps",
|
||||
cflags: [
|
||||
"-DLIBSNAPSHOT_USE_HAL",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.boot@1.0",
|
||||
"android.hardware.boot@1.1",
|
||||
],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "libsnapshot_sources",
|
||||
srcs: [
|
||||
|
@ -75,7 +87,10 @@ cc_library_headers {
|
|||
|
||||
cc_library_static {
|
||||
name: "libsnapshot",
|
||||
defaults: ["libsnapshot_defaults"],
|
||||
defaults: [
|
||||
"libsnapshot_defaults",
|
||||
"libsnapshot_hal_deps",
|
||||
],
|
||||
srcs: [":libsnapshot_sources"],
|
||||
whole_static_libs: [
|
||||
"libfiemap_binder",
|
||||
|
@ -83,7 +98,7 @@ cc_library_static {
|
|||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libsnapshot_nobinder",
|
||||
name: "libsnapshot_init",
|
||||
defaults: ["libsnapshot_defaults"],
|
||||
srcs: [":libsnapshot_sources"],
|
||||
recovery_available: true,
|
||||
|
@ -92,6 +107,19 @@ cc_library_static {
|
|||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libsnapshot_nobinder",
|
||||
defaults: [
|
||||
"libsnapshot_defaults",
|
||||
"libsnapshot_hal_deps",
|
||||
],
|
||||
srcs: [":libsnapshot_sources"],
|
||||
recovery_available: true,
|
||||
whole_static_libs: [
|
||||
"libfiemap_passthrough",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "libsnapshot_test",
|
||||
defaults: ["libsnapshot_defaults"],
|
||||
|
@ -103,11 +131,13 @@ cc_test {
|
|||
],
|
||||
shared_libs: [
|
||||
"libbinder",
|
||||
"libhidlbase",
|
||||
"libprotobuf-cpp-lite",
|
||||
"libutils",
|
||||
],
|
||||
static_libs: [
|
||||
"libcutils",
|
||||
"android.hardware.boot@1.0",
|
||||
"android.hardware.boot@1.1",
|
||||
"libcrypto_static",
|
||||
"libfs_mgr",
|
||||
"libgmock",
|
||||
|
@ -134,10 +164,14 @@ cc_binary {
|
|||
"libsnapshot",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.boot@1.0",
|
||||
"android.hardware.boot@1.1",
|
||||
"libbase",
|
||||
"libbinder",
|
||||
"libbinderthreadstate",
|
||||
"libext4_utils",
|
||||
"libfs_mgr",
|
||||
"libhidlbase",
|
||||
"liblog",
|
||||
"liblp",
|
||||
"libprotobuf-cpp-lite",
|
||||
|
|
|
@ -49,6 +49,16 @@ struct CreateLogicalPartitionParams;
|
|||
class IPartitionOpener;
|
||||
} // namespace fs_mgr
|
||||
|
||||
// Forward declare IBootControl types since we cannot include only the headers
|
||||
// with Soong. Note: keep the enum width in sync.
|
||||
namespace hardware {
|
||||
namespace boot {
|
||||
namespace V1_1 {
|
||||
enum class MergeStatus : int32_t;
|
||||
} // namespace V1_1
|
||||
} // namespace boot
|
||||
} // namespace hardware
|
||||
|
||||
namespace snapshot {
|
||||
|
||||
struct AutoDeleteCowImage;
|
||||
|
@ -94,6 +104,7 @@ class SnapshotManager final {
|
|||
using LpMetadata = android::fs_mgr::LpMetadata;
|
||||
using MetadataBuilder = android::fs_mgr::MetadataBuilder;
|
||||
using DeltaArchiveManifest = chromeos_update_engine::DeltaArchiveManifest;
|
||||
using MergeStatus = android::hardware::boot::V1_1::MergeStatus;
|
||||
|
||||
public:
|
||||
// Dependency injection for testing.
|
||||
|
@ -107,6 +118,7 @@ class SnapshotManager final {
|
|||
virtual std::string GetSuperDevice(uint32_t slot) const = 0;
|
||||
virtual const IPartitionOpener& GetPartitionOpener() const = 0;
|
||||
virtual bool IsOverlayfsSetup() const = 0;
|
||||
virtual bool SetBootControlMergeStatus(MergeStatus status) = 0;
|
||||
};
|
||||
|
||||
~SnapshotManager();
|
||||
|
@ -208,6 +220,7 @@ class SnapshotManager final {
|
|||
FRIEND_TEST(SnapshotTest, Merge);
|
||||
FRIEND_TEST(SnapshotTest, MergeCannotRemoveCow);
|
||||
FRIEND_TEST(SnapshotTest, NoMergeBeforeReboot);
|
||||
FRIEND_TEST(SnapshotTest, UpdateBootControlHal);
|
||||
FRIEND_TEST(SnapshotUpdateTest, SnapshotStatusFileWithoutCow);
|
||||
friend class SnapshotTest;
|
||||
friend class SnapshotUpdateTest;
|
||||
|
|
|
@ -29,6 +29,9 @@
|
|||
#include <android-base/parseint.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#ifdef LIBSNAPSHOT_USE_HAL
|
||||
#include <android/hardware/boot/1.1/IBootControl.h>
|
||||
#endif
|
||||
#include <ext4_utils/ext4_utils.h>
|
||||
#include <fs_mgr.h>
|
||||
#include <fs_mgr_dm_linear.h>
|
||||
|
@ -63,6 +66,7 @@ using android::fs_mgr::GetPartitionName;
|
|||
using android::fs_mgr::LpMetadata;
|
||||
using android::fs_mgr::MetadataBuilder;
|
||||
using android::fs_mgr::SlotNumberForSlotSuffix;
|
||||
using android::hardware::boot::V1_1::MergeStatus;
|
||||
using chromeos_update_engine::DeltaArchiveManifest;
|
||||
using chromeos_update_engine::InstallOperation;
|
||||
template <typename T>
|
||||
|
@ -84,11 +88,39 @@ class DeviceInfo final : public SnapshotManager::IDeviceInfo {
|
|||
return fs_mgr_get_super_partition_name(slot);
|
||||
}
|
||||
bool IsOverlayfsSetup() const override { return fs_mgr_overlayfs_is_setup(); }
|
||||
bool SetBootControlMergeStatus(MergeStatus status) override;
|
||||
|
||||
private:
|
||||
android::fs_mgr::PartitionOpener opener_;
|
||||
#ifdef LIBSNAPSHOT_USE_HAL
|
||||
android::sp<android::hardware::boot::V1_1::IBootControl> boot_control_;
|
||||
#endif
|
||||
};
|
||||
|
||||
bool DeviceInfo::SetBootControlMergeStatus([[maybe_unused]] MergeStatus status) {
|
||||
#ifdef LIBSNAPSHOT_USE_HAL
|
||||
if (!boot_control_) {
|
||||
auto hal = android::hardware::boot::V1_0::IBootControl::getService();
|
||||
if (!hal) {
|
||||
LOG(ERROR) << "Could not find IBootControl HAL";
|
||||
return false;
|
||||
}
|
||||
boot_control_ = android::hardware::boot::V1_1::IBootControl::castFrom(hal);
|
||||
if (!boot_control_) {
|
||||
LOG(ERROR) << "Could not find IBootControl 1.1 HAL";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!boot_control_->setSnapshotMergeStatus(status)) {
|
||||
LOG(ERROR) << "Unable to set the snapshot merge status";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Note: IImageManager is an incomplete type in the header, so the default
|
||||
// destructor doesn't work.
|
||||
SnapshotManager::~SnapshotManager() {}
|
||||
|
@ -1590,6 +1622,35 @@ bool SnapshotManager::WriteUpdateState(LockedFile* file, UpdateState state) {
|
|||
PLOG(ERROR) << "Could not write to state file";
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef LIBSNAPSHOT_USE_HAL
|
||||
auto merge_status = MergeStatus::UNKNOWN;
|
||||
switch (state) {
|
||||
// The needs-reboot and completed cases imply that /data and /metadata
|
||||
// can be safely wiped, so we don't report a merge status.
|
||||
case UpdateState::None:
|
||||
case UpdateState::MergeNeedsReboot:
|
||||
case UpdateState::MergeCompleted:
|
||||
merge_status = MergeStatus::NONE;
|
||||
break;
|
||||
case UpdateState::Initiated:
|
||||
case UpdateState::Unverified:
|
||||
merge_status = MergeStatus::SNAPSHOTTED;
|
||||
break;
|
||||
case UpdateState::Merging:
|
||||
case UpdateState::MergeFailed:
|
||||
merge_status = MergeStatus::MERGING;
|
||||
break;
|
||||
default:
|
||||
// Note that Cancelled flows to here - it is never written, since
|
||||
// it only communicates a transient state to the caller.
|
||||
LOG(ERROR) << "Unexpected update status: " << state;
|
||||
break;
|
||||
}
|
||||
if (!device_->SetBootControlMergeStatus(merge_status)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -617,6 +617,31 @@ TEST_F(SnapshotTest, FlashSuperDuringMerge) {
|
|||
ASSERT_EQ(sm->GetUpdateState(), UpdateState::None);
|
||||
}
|
||||
|
||||
TEST_F(SnapshotTest, UpdateBootControlHal) {
|
||||
ASSERT_TRUE(AcquireLock());
|
||||
|
||||
ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::None));
|
||||
ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
|
||||
|
||||
ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Initiated));
|
||||
ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
|
||||
|
||||
ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Unverified));
|
||||
ASSERT_EQ(test_device->merge_status(), MergeStatus::SNAPSHOTTED);
|
||||
|
||||
ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::Merging));
|
||||
ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
|
||||
|
||||
ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeNeedsReboot));
|
||||
ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
|
||||
|
||||
ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeCompleted));
|
||||
ASSERT_EQ(test_device->merge_status(), MergeStatus::NONE);
|
||||
|
||||
ASSERT_TRUE(sm->WriteUpdateState(lock_.get(), UpdateState::MergeFailed));
|
||||
ASSERT_EQ(test_device->merge_status(), MergeStatus::MERGING);
|
||||
}
|
||||
|
||||
class SnapshotUpdateTest : public SnapshotTest {
|
||||
public:
|
||||
void SetUp() override {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <android/hardware/boot/1.1/IBootControl.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <libfiemap/image_manager.h>
|
||||
|
@ -32,6 +33,7 @@ namespace snapshot {
|
|||
using android::fs_mgr::IPropertyFetcher;
|
||||
using android::fs_mgr::MetadataBuilder;
|
||||
using android::fs_mgr::testing::MockPropertyFetcher;
|
||||
using android::hardware::boot::V1_1::MergeStatus;
|
||||
using chromeos_update_engine::DeltaArchiveManifest;
|
||||
using chromeos_update_engine::PartitionUpdate;
|
||||
using testing::_;
|
||||
|
@ -81,16 +83,22 @@ class TestDeviceInfo : public SnapshotManager::IDeviceInfo {
|
|||
const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const override {
|
||||
return *opener_.get();
|
||||
}
|
||||
bool SetBootControlMergeStatus(MergeStatus status) override {
|
||||
merge_status_ = status;
|
||||
return true;
|
||||
}
|
||||
bool IsOverlayfsSetup() const override { return false; }
|
||||
|
||||
void set_slot_suffix(const std::string& suffix) { slot_suffix_ = suffix; }
|
||||
void set_fake_super(const std::string& path) {
|
||||
opener_ = std::make_unique<TestPartitionOpener>(path);
|
||||
}
|
||||
MergeStatus merge_status() const { return merge_status_; }
|
||||
|
||||
private:
|
||||
std::string slot_suffix_ = "_a";
|
||||
std::unique_ptr<TestPartitionOpener> opener_;
|
||||
MergeStatus merge_status_;
|
||||
};
|
||||
|
||||
class SnapshotTestPropertyFetcher : public android::fs_mgr::testing::MockPropertyFetcher {
|
||||
|
|
|
@ -69,7 +69,7 @@ cc_defaults {
|
|||
"libprotobuf-cpp-lite",
|
||||
"libpropertyinfoserializer",
|
||||
"libpropertyinfoparser",
|
||||
"libsnapshot_nobinder",
|
||||
"libsnapshot_init",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbacktrace",
|
||||
|
|
|
@ -114,7 +114,7 @@ LOCAL_STATIC_LIBRARIES := \
|
|||
libmodprobe \
|
||||
libext2_uuid \
|
||||
libprotobuf-cpp-lite \
|
||||
libsnapshot_nobinder \
|
||||
libsnapshot_init \
|
||||
|
||||
LOCAL_SANITIZE := signed-integer-overflow
|
||||
# First stage init is weird: it may start without stdout/stderr, and no /proc.
|
||||
|
|
Loading…
Reference in a new issue