libsnapshot: Add GetSnapshotMergeStatsInstance

This is preferred over SnapshotMergeStats::GetInstance because
the latter needs a concrete SnapshotManager, not the ISnapshotManager
interface.

SnapshotManagerStub::GetSnapshotMergeStatsInstance returns
a SnapshotMergeStatsStub instance.

Test: vts_libsnapshot_test
Bug: 148956645
Change-Id: Ife0ad6d3ce85333cbf395d07f74dedc9ca3fe675
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index c73ed2c..fff667e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -70,6 +70,8 @@
 struct AutoDeleteSnapshot;
 struct AutoDeviceList;
 struct PartitionCowCreator;
+class ISnapshotMergeStats;
+class SnapshotMergeStats;
 class SnapshotStatus;
 
 static constexpr const std::string_view kCowGroupName = "cow";
@@ -235,6 +237,9 @@
     //   b.reset() // unmounts
     //   a.reset() // does nothing
     virtual std::unique_ptr<AutoDevice> EnsureMetadataMounted() = 0;
+
+    // Return the associated ISnapshotMergeStats instance. Never null.
+    virtual ISnapshotMergeStats* GetSnapshotMergeStatsInstance() = 0;
 };
 
 class SnapshotManager final : public ISnapshotManager {
@@ -289,6 +294,7 @@
             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);
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
index 91dd34f..4caf632 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
@@ -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 @@
         // 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();
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
index 924f26d..9b2590c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
@@ -46,6 +46,7 @@
             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
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index c9fa28e..eafeea2 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -2685,5 +2685,9 @@
     return true;
 }
 
+ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() {
+    return SnapshotMergeStats::GetInstance(*this);
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp
index 6c82f61..2747b03 100644
--- a/fs_mgr/libsnapshot/snapshot_stub.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stub.cpp
@@ -16,6 +16,8 @@
 
 #include <android-base/logging.h>
 
+#include <libsnapshot/snapshot_stats.h>
+
 using android::fs_mgr::CreateLogicalPartitionParams;
 using chromeos_update_engine::DeltaArchiveManifest;
 
@@ -108,4 +110,16 @@
     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