Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b5678e0 authored by David Anderson's avatar David Anderson Committed by android-build-merger
Browse files

Merge "Integrate libsnapshot with the boot control HAL."

am: c243e199

Change-Id: Id4a9a5e8733d939c238d783e2550d033b28d5dff
parents bd3586f7 c243e199
Loading
Loading
Loading
Loading
+37 −3
Original line number Diff line number Diff line
@@ -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",
+13 −0
Original line number Diff line number Diff line
@@ -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;
+61 −0
Original line number Diff line number Diff line
@@ -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;
}

+25 −0
Original line number Diff line number Diff line
@@ -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 {
+8 −0
Original line number Diff line number Diff line
@@ -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 {
Loading