Merge changes from topics "sm_mock", "sm_stub" am: 96174857f2 am: 89881e434c

Change-Id: I1c56b753157a903026fa71650cb8dd6508031ab8
This commit is contained in:
Yifan Hong 2020-04-20 19:21:22 +00:00 committed by Automerger Merge Worker
commit c86ca3f5ff
9 changed files with 381 additions and 56 deletions

View file

@ -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",

View file

@ -0,0 +1,37 @@
// 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

View file

@ -0,0 +1,54 @@
// 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

View file

@ -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);

View file

@ -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();

View file

@ -0,0 +1,52 @@
// 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>
namespace android::snapshot {
class SnapshotManagerStub : public ISnapshotManager {
public:
// Create a stubbed snapshot manager. All calls into the stub fails.
static std::unique_ptr<ISnapshotManager> New();
// 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 chromeos_update_engine::DeltaArchiveManifest& manifest) override;
bool MapUpdateSnapshot(const android::fs_mgr::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;
};
} // namespace android::snapshot

View file

@ -2685,5 +2685,9 @@ bool SnapshotManager::UpdateForwardMergeIndicator(bool wipe) {
return true;
}
ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() {
return SnapshotMergeStats::GetInstance(*this);
}
} // namespace snapshot
} // namespace android

View file

@ -0,0 +1,125 @@
// 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.
#include <libsnapshot/snapshot_stub.h>
#include <android-base/logging.h>
#include <libsnapshot/snapshot_stats.h>
using android::fs_mgr::CreateLogicalPartitionParams;
using chromeos_update_engine::DeltaArchiveManifest;
namespace android::snapshot {
std::unique_ptr<ISnapshotManager> SnapshotManagerStub::New() {
return std::make_unique<SnapshotManagerStub>();
}
bool SnapshotManagerStub::BeginUpdate() {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
bool SnapshotManagerStub::CancelUpdate() {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
bool SnapshotManagerStub::FinishedSnapshotWrites(bool) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
bool SnapshotManagerStub::InitiateMerge() {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
UpdateState SnapshotManagerStub::ProcessUpdateState(const std::function<bool()>&,
const std::function<bool()>&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return UpdateState::None;
}
UpdateState SnapshotManagerStub::GetUpdateState(double*) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return UpdateState::None;
}
Return SnapshotManagerStub::CreateUpdateSnapshots(const DeltaArchiveManifest&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return Return::Error();
}
bool SnapshotManagerStub::MapUpdateSnapshot(const CreateLogicalPartitionParams&, std::string*) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
bool SnapshotManagerStub::UnmapUpdateSnapshot(const std::string&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
bool SnapshotManagerStub::NeedSnapshotsInFirstStageMount() {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
bool SnapshotManagerStub::CreateLogicalAndSnapshotPartitions(const std::string&,
const std::chrono::milliseconds&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
bool SnapshotManagerStub::HandleImminentDataWipe(const std::function<void()>&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
CreateResult SnapshotManagerStub::RecoveryCreateSnapshotDevices() {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return CreateResult::ERROR;
}
CreateResult SnapshotManagerStub::RecoveryCreateSnapshotDevices(
const std::unique_ptr<AutoDevice>&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return CreateResult::ERROR;
}
bool SnapshotManagerStub::Dump(std::ostream&) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
std::unique_ptr<AutoDevice> SnapshotManagerStub::EnsureMetadataMounted() {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return nullptr;
}
class SnapshotMergeStatsStub : public ISnapshotMergeStats {
bool Start() override { return false; }
void set_state(android::snapshot::UpdateState) override {}
std::unique_ptr<Result> Finish() override { return nullptr; }
};
ISnapshotMergeStats* SnapshotManagerStub::GetSnapshotMergeStatsInstance() {
static SnapshotMergeStatsStub snapshot_merge_stats;
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return &snapshot_merge_stats;
}
} // namespace android::snapshot

View file

@ -41,6 +41,11 @@
#include <libsnapshot/test_helpers.h>
#include "utility.h"
// Mock classes are not used. Header included to ensure mocked class definition aligns with the
// class itself.
#include <libsnapshot/mock_device_info.h>
#include <libsnapshot/mock_snapshot.h>
namespace android {
namespace snapshot {