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

Commit 96174857 authored by Yifan Hong's avatar Yifan Hong Committed by Gerrit Code Review
Browse files

Merge changes from topics "sm_mock", "sm_stub"

* changes:
  libsnapshot: Add MockSnapshotManager and MockDeviceInfo.
  libsnapshot: Add GetSnapshotMergeStatsInstance
  libsnapshot: Add SnapshotManagerStub.
  libsnapshot: Add ISnapshotManager.
parents 6b9b468d 2dcca524
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ filegroup {
        "device_info.cpp",
        "snapshot.cpp",
        "snapshot_stats.cpp",
        "snapshot_stub.cpp",
        "snapshot_metadata_updater.cpp",
        "partition_cow_creator.cpp",
        "return.cpp",
+37 −0
Original line number Diff line number Diff line
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <libsnapshot/snapshot.h>

#include <gmock/gmock.h>

namespace android::snapshot {

class MockDeviceInfo : public SnapshotManager::IDeviceInfo {
  public:
    MOCK_METHOD(std::string, GetGsidDir, (), (const, override));
    MOCK_METHOD(std::string, GetMetadataDir, (), (const, override));
    MOCK_METHOD(std::string, GetSlotSuffix, (), (const, override));
    MOCK_METHOD(std::string, GetOtherSlotSuffix, (), (const, override));
    MOCK_METHOD(std::string, GetSuperDevice, (uint32_t slot), (const, override));
    MOCK_METHOD(const android::fs_mgr::IPartitionOpener&, GetPartitionOpener, (), (const));
    MOCK_METHOD(bool, IsOverlayfsSetup, (), (const, override));
    MOCK_METHOD(bool, SetBootControlMergeStatus, (MergeStatus status), (override));
    MOCK_METHOD(bool, SetSlotAsUnbootable, (unsigned int slot), (override));
    MOCK_METHOD(bool, IsRecovery, (), (const, override));
};

}  // namespace android::snapshot
+54 −0
Original line number Diff line number Diff line
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <libsnapshot/snapshot.h>

#include <gmock/gmock.h>

namespace android::snapshot {

class MockSnapshotManager : public ISnapshotManager {
  public:
    MOCK_METHOD(bool, BeginUpdate, (), (override));
    MOCK_METHOD(bool, CancelUpdate, (), (override));
    MOCK_METHOD(bool, FinishedSnapshotWrites, (bool wipe), (override));
    MOCK_METHOD(bool, InitiateMerge, (), (override));

    MOCK_METHOD(UpdateState, ProcessUpdateState,
                (const std::function<bool()>& callback, const std::function<bool()>& before_cancel),
                (override));
    MOCK_METHOD(UpdateState, GetUpdateState, (double* progress), (override));
    MOCK_METHOD(Return, CreateUpdateSnapshots,
                (const chromeos_update_engine::DeltaArchiveManifest& manifest), (override));
    MOCK_METHOD(bool, MapUpdateSnapshot,
                (const android::fs_mgr::CreateLogicalPartitionParams& params,
                 std::string* snapshot_path),
                (override));
    MOCK_METHOD(bool, UnmapUpdateSnapshot, (const std::string& target_partition_name), (override));
    MOCK_METHOD(bool, NeedSnapshotsInFirstStageMount, (), (override));
    MOCK_METHOD(bool, CreateLogicalAndSnapshotPartitions,
                (const std::string& super_device, const std::chrono::milliseconds& timeout_ms),
                (override));
    MOCK_METHOD(bool, HandleImminentDataWipe, (const std::function<void()>& callback), (override));
    MOCK_METHOD(CreateResult, RecoveryCreateSnapshotDevices, (), (override));
    MOCK_METHOD(CreateResult, RecoveryCreateSnapshotDevices,
                (const std::unique_ptr<AutoDevice>& metadata_device), (override));
    MOCK_METHOD(bool, Dump, (std::ostream & os), (override));
    MOCK_METHOD(std::unique_ptr<AutoDevice>, EnsureMetadataMounted, (), (override));
    MOCK_METHOD(ISnapshotMergeStats*, GetSnapshotMergeStatsInstance, (), (override));
};

}  // namespace android::snapshot
+86 −49
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@ struct AutoDeleteCowImage;
struct AutoDeleteSnapshot;
struct AutoDeviceList;
struct PartitionCowCreator;
class ISnapshotMergeStats;
class SnapshotMergeStats;
class SnapshotStatus;

static constexpr const std::string_view kCowGroupName = "cow";
@@ -83,17 +85,7 @@ enum class CreateResult : unsigned int {
    NOT_CREATED,
};

class SnapshotManager final {
    using CreateLogicalPartitionParams = android::fs_mgr::CreateLogicalPartitionParams;
    using IPartitionOpener = android::fs_mgr::IPartitionOpener;
    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;
    using FiemapStatus = android::fiemap::FiemapStatus;

    friend class SnapshotMergeStats;

class ISnapshotManager {
  public:
    // Dependency injection for testing.
    class IDeviceInfo {
@@ -104,39 +96,23 @@ class SnapshotManager final {
        virtual std::string GetSlotSuffix() const = 0;
        virtual std::string GetOtherSlotSuffix() const = 0;
        virtual std::string GetSuperDevice(uint32_t slot) const = 0;
        virtual const IPartitionOpener& GetPartitionOpener() const = 0;
        virtual const android::fs_mgr::IPartitionOpener& GetPartitionOpener() const = 0;
        virtual bool IsOverlayfsSetup() const = 0;
        virtual bool SetBootControlMergeStatus(MergeStatus status) = 0;
        virtual bool SetBootControlMergeStatus(
                android::hardware::boot::V1_1::MergeStatus status) = 0;
        virtual bool SetSlotAsUnbootable(unsigned int slot) = 0;
        virtual bool IsRecovery() const = 0;
    };

    ~SnapshotManager();

    // Return a new SnapshotManager instance, or null on error. The device
    // pointer is owned for the lifetime of SnapshotManager. If null, a default
    // instance will be created.
    static std::unique_ptr<SnapshotManager> New(IDeviceInfo* device = nullptr);

    // This is similar to New(), except designed specifically for first-stage
    // init or recovery.
    static std::unique_ptr<SnapshotManager> NewForFirstStageMount(IDeviceInfo* device = nullptr);

    // Helper function for first-stage init to check whether a SnapshotManager
    // might be needed to perform first-stage mounts.
    static bool IsSnapshotManagerNeeded();

    // Helper function for second stage init to restorecon on the rollback indicator.
    static std::string GetGlobalRollbackIndicatorPath();
    virtual ~ISnapshotManager() = default;

    // Begin an update. This must be called before creating any snapshots. It
    // will fail if GetUpdateState() != None.
    bool BeginUpdate();
    virtual bool BeginUpdate() = 0;

    // Cancel an update; any snapshots will be deleted. This is allowed if the
    // state == Initiated, None, or Unverified (before rebooting to the new
    // slot).
    bool CancelUpdate();
    virtual bool CancelUpdate() = 0;

    // Mark snapshot writes as having completed. After this, new snapshots cannot
    // be created, and the device must either cancel the OTA (either before
@@ -144,11 +120,11 @@ class SnapshotManager final {
    // Before calling this function, all snapshots must be mapped.
    // If |wipe| is set to true, wipe is scheduled after reboot, and snapshots
    // may need to be merged before wiping.
    bool FinishedSnapshotWrites(bool wipe);
    virtual bool FinishedSnapshotWrites(bool wipe) = 0;

    // Initiate a merge on all snapshot devices. This should only be used after an
    // update has been marked successful after booting.
    bool InitiateMerge();
    virtual bool InitiateMerge() = 0;

    // Perform any necessary post-boot actions. This should be run soon after
    // /data is mounted.
@@ -178,8 +154,8 @@ class SnapshotManager final {
    //
    // The optional callback allows the caller to periodically check the
    // progress with GetUpdateState().
    UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
                                   const std::function<bool()>& before_cancel = {});
    virtual UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
                                           const std::function<bool()>& before_cancel = {}) = 0;

    // Find the status of the current update, if any.
    //
@@ -187,28 +163,30 @@ class SnapshotManager final {
    //   Merging: Value in the range [0, 100]
    //   MergeCompleted: 100
    //   Other: 0
    UpdateState GetUpdateState(double* progress = nullptr);
    virtual UpdateState GetUpdateState(double* progress = nullptr) = 0;

    // Create necessary COW device / files for OTA clients. New logical partitions will be added to
    // group "cow" in target_metadata. Regions of partitions of current_metadata will be
    // "write-protected" and snapshotted.
    Return CreateUpdateSnapshots(const DeltaArchiveManifest& manifest);
    virtual Return CreateUpdateSnapshots(
            const chromeos_update_engine::DeltaArchiveManifest& manifest) = 0;

    // Map a snapshotted partition for OTA clients to write to. Write-protected regions are
    // determined previously in CreateSnapshots.
    bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params, std::string* snapshot_path);
    virtual bool MapUpdateSnapshot(const android::fs_mgr::CreateLogicalPartitionParams& params,
                                   std::string* snapshot_path) = 0;

    // Unmap a snapshot device that's previously mapped with MapUpdateSnapshot.
    bool UnmapUpdateSnapshot(const std::string& target_partition_name);
    virtual bool UnmapUpdateSnapshot(const std::string& target_partition_name) = 0;

    // If this returns true, first-stage mount must call
    // CreateLogicalAndSnapshotPartitions rather than CreateLogicalPartitions.
    bool NeedSnapshotsInFirstStageMount();
    virtual bool NeedSnapshotsInFirstStageMount() = 0;

    // Perform first-stage mapping of snapshot targets. This replaces init's
    // call to CreateLogicalPartitions when snapshots are present.
    bool CreateLogicalAndSnapshotPartitions(const std::string& super_device,
                                            const std::chrono::milliseconds& timeout_ms = {});
    virtual bool CreateLogicalAndSnapshotPartitions(
            const std::string& super_device, const std::chrono::milliseconds& timeout_ms = {}) = 0;

    // This method should be called preceding any wipe or flash of metadata or
    // userdata. It is only valid in recovery or fastbootd, and it ensures that
@@ -221,7 +199,7 @@ class SnapshotManager final {
    //
    // Returns true on success (or nothing to do), false on failure. The
    // optional callback fires periodically to query progress via GetUpdateState.
    bool HandleImminentDataWipe(const std::function<void()>& callback = {});
    virtual bool HandleImminentDataWipe(const std::function<void()>& callback = {}) = 0;

    // This method is only allowed in recovery and is used as a helper to
    // initialize the snapshot devices as a requirement to mount a snapshotted
@@ -234,14 +212,15 @@ class SnapshotManager final {
    // be aborted.
    // This function mounts /metadata when called, and unmounts /metadata upon
    // return.
    CreateResult RecoveryCreateSnapshotDevices();
    virtual CreateResult RecoveryCreateSnapshotDevices() = 0;

    // Same as RecoveryCreateSnapshotDevices(), but does not auto mount/umount
    // /metadata.
    CreateResult RecoveryCreateSnapshotDevices(const std::unique_ptr<AutoDevice>& metadata_device);
    virtual CreateResult RecoveryCreateSnapshotDevices(
            const std::unique_ptr<AutoDevice>& metadata_device) = 0;

    // Dump debug information.
    bool Dump(std::ostream& os);
    virtual bool Dump(std::ostream& os) = 0;

    // Ensure metadata directory is mounted in recovery. When the returned
    // AutoDevice is destroyed, the metadata directory is automatically
@@ -257,7 +236,65 @@ class SnapshotManager final {
    //   auto b = mgr->EnsureMetadataMounted(); // does nothing
    //   b.reset() // unmounts
    //   a.reset() // does nothing
    std::unique_ptr<AutoDevice> EnsureMetadataMounted();
    virtual std::unique_ptr<AutoDevice> EnsureMetadataMounted() = 0;

    // Return the associated ISnapshotMergeStats instance. Never null.
    virtual ISnapshotMergeStats* GetSnapshotMergeStatsInstance() = 0;
};

class SnapshotManager final : public ISnapshotManager {
    using CreateLogicalPartitionParams = android::fs_mgr::CreateLogicalPartitionParams;
    using IPartitionOpener = android::fs_mgr::IPartitionOpener;
    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;
    using FiemapStatus = android::fiemap::FiemapStatus;

    friend class SnapshotMergeStats;

  public:
    ~SnapshotManager();

    // Return a new SnapshotManager instance, or null on error. The device
    // pointer is owned for the lifetime of SnapshotManager. If null, a default
    // instance will be created.
    static std::unique_ptr<SnapshotManager> New(IDeviceInfo* device = nullptr);

    // This is similar to New(), except designed specifically for first-stage
    // init or recovery.
    static std::unique_ptr<SnapshotManager> NewForFirstStageMount(IDeviceInfo* device = nullptr);

    // Helper function for first-stage init to check whether a SnapshotManager
    // might be needed to perform first-stage mounts.
    static bool IsSnapshotManagerNeeded();

    // Helper function for second stage init to restorecon on the rollback indicator.
    static std::string GetGlobalRollbackIndicatorPath();

    // ISnapshotManager overrides.
    bool BeginUpdate() override;
    bool CancelUpdate() override;
    bool FinishedSnapshotWrites(bool wipe) override;
    bool InitiateMerge() override;
    UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
                                   const std::function<bool()>& before_cancel = {}) override;
    UpdateState GetUpdateState(double* progress = nullptr) override;
    Return CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) override;
    bool MapUpdateSnapshot(const CreateLogicalPartitionParams& params,
                           std::string* snapshot_path) override;
    bool UnmapUpdateSnapshot(const std::string& target_partition_name) override;
    bool NeedSnapshotsInFirstStageMount() override;
    bool CreateLogicalAndSnapshotPartitions(
            const std::string& super_device,
            const std::chrono::milliseconds& timeout_ms = {}) override;
    bool HandleImminentDataWipe(const std::function<void()>& callback = {}) override;
    CreateResult RecoveryCreateSnapshotDevices() override;
    CreateResult RecoveryCreateSnapshotDevices(
            const std::unique_ptr<AutoDevice>& metadata_device) override;
    bool Dump(std::ostream& os) override;
    std::unique_ptr<AutoDevice> EnsureMetadataMounted() override;
    ISnapshotMergeStats* GetSnapshotMergeStatsInstance() override;

  private:
    FRIEND_TEST(SnapshotTest, CleanFirstStageMount);
+17 −7
Original line number Diff line number Diff line
@@ -23,14 +23,12 @@
namespace android {
namespace snapshot {

class SnapshotMergeStats {
class ISnapshotMergeStats {
  public:
    // Not thread safe.
    static SnapshotMergeStats* GetInstance(SnapshotManager& manager);

    virtual ~ISnapshotMergeStats() = default;
    // Called when merge starts or resumes.
    bool Start();
    void set_state(android::snapshot::UpdateState state);
    virtual bool Start() = 0;
    virtual void set_state(android::snapshot::UpdateState state) = 0;

    // Called when merge ends. Properly clean up permanent storage.
    class Result {
@@ -40,7 +38,19 @@ class SnapshotMergeStats {
        // Time between successful Start() / Resume() to Finish().
        virtual std::chrono::steady_clock::duration merge_time() const = 0;
    };
    std::unique_ptr<Result> Finish();
    // Return nullptr if any failure.
    virtual std::unique_ptr<Result> Finish() = 0;
};

class SnapshotMergeStats : public ISnapshotMergeStats {
  public:
    // Not thread safe.
    static SnapshotMergeStats* GetInstance(SnapshotManager& manager);

    // ISnapshotMergeStats overrides
    bool Start() override;
    void set_state(android::snapshot::UpdateState state) override;
    std::unique_ptr<Result> Finish() override;

  private:
    bool ReadState();
Loading