SurfaceFlinger: Make LayerHistory virtual class

This is a base CL for refresh rate selection algorithm enhancements
by allowing a different implementation of LayerHistory which will be
controlled by a switch.

Test: watch 24fps video and observe refresh rate at 60Hz
Bug: 147516364
Change-Id: Ifd12f6683bc96cd5aba04a8960b9235729820b49
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 146ec1b..cf79d9f 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -34,7 +34,7 @@
 #include "LayerInfo.h"
 #include "SchedulerUtils.h"
 
-namespace android::scheduler {
+namespace android::scheduler::impl {
 
 namespace {
 
@@ -157,4 +157,4 @@
     mActiveLayersEnd = 0;
 }
 
-} // namespace android::scheduler
+} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 745c4c1..d92e5c3 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -32,33 +32,51 @@
 
 namespace scheduler {
 
+class LayerHistoryTest;
 class LayerInfo;
 
-// Records per-layer history of scheduling-related information (primarily present time),
-// heuristically categorizes layers as active or inactive, and summarizes stats about
-// active layers (primarily maximum refresh rate). See go/content-fps-detection-in-scheduler.
 class LayerHistory {
 public:
-    LayerHistory();
-    ~LayerHistory();
+    virtual ~LayerHistory() = default;
 
     // Layers are unregistered when the weak reference expires.
-    void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate);
+    virtual void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate) = 0;
 
     // Marks the layer as active, and records the given state to its history.
-    void record(Layer*, nsecs_t presentTime, nsecs_t now);
+    virtual void record(Layer*, nsecs_t presentTime, nsecs_t now) = 0;
 
     struct Summary {
         float maxRefreshRate; // Maximum refresh rate among recently active layers.
     };
 
     // Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
-    Summary summarize(nsecs_t now);
+    virtual Summary summarize(nsecs_t now) = 0;
 
-    void clear();
+    virtual void clear() = 0;
+};
+
+namespace impl {
+// Records per-layer history of scheduling-related information (primarily present time),
+// heuristically categorizes layers as active or inactive, and summarizes stats about
+// active layers (primarily maximum refresh rate). See go/content-fps-detection-in-scheduler.
+class LayerHistory : public android::scheduler::LayerHistory {
+public:
+    LayerHistory();
+    virtual ~LayerHistory();
+
+    // Layers are unregistered when the weak reference expires.
+    void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate) override;
+
+    // Marks the layer as active, and records the given state to its history.
+    void record(Layer*, nsecs_t presentTime, nsecs_t now) override;
+
+    // Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
+    android::scheduler::LayerHistory::Summary summarize(nsecs_t now) override;
+
+    void clear() override;
 
 private:
-    friend class LayerHistoryTest;
+    friend class android::scheduler::LayerHistoryTest;
     friend TestableScheduler;
 
     using LayerPair = std::pair<wp<Layer>, std::unique_ptr<LayerInfo>>;
@@ -90,5 +108,6 @@
     const bool mTraceEnabled;
 };
 
+} // namespace impl
 } // namespace scheduler
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index ff9cf86..73dc753 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -108,7 +108,7 @@
     using namespace sysprop;
 
     if (property_get_bool("debug.sf.use_smart_90_for_video", 0) || use_smart_90_for_video(false)) {
-        mLayerHistory.emplace();
+        mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
     }
 
     const int setIdleTimerMs = property_get_int32("debug.sf.set_idle_timer_ms", 0);
@@ -493,7 +493,7 @@
 
     const bool supported = mRefreshRateConfigs.refreshRateSwitchingSupported();
     StringAppendF(&result, "+  Refresh rate switching: %s\n", states[supported]);
-    StringAppendF(&result, "+  Content detection: %s\n", states[mLayerHistory.has_value()]);
+    StringAppendF(&result, "+  Content detection: %s\n", states[mLayerHistory != nullptr]);
 
     StringAppendF(&result, "+  Idle timer: %s\n",
                   mIdleTimer ? mIdleTimer->dump().c_str() : states[0]);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 2cdb757..c6430c3 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -193,7 +193,7 @@
     std::unique_ptr<EventControlThread> mEventControlThread;
 
     // Used to choose refresh rate if content detection is enabled.
-    std::optional<scheduler::LayerHistory> mLayerHistory;
+    std::unique_ptr<scheduler::LayerHistory> mLayerHistory;
 
     // Whether to use idle timer callbacks that support the kernel timer.
     const bool mSupportKernelTimer;
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index d95252b..f055fe7 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -29,8 +29,8 @@
 
     LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); }
 
-    LayerHistory& history() { return *mScheduler->mutableLayerHistory(); }
-    const LayerHistory& history() const { return *mScheduler->mutableLayerHistory(); }
+    impl::LayerHistory& history() { return *mScheduler->mutableLayerHistory(); }
+    const impl::LayerHistory& history() const { return *mScheduler->mutableLayerHistory(); }
 
     size_t layerCount() const { return mScheduler->layerHistorySize(); }
     size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; }
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index fa095aa..a67c24c 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -30,14 +30,14 @@
 public:
     explicit TestableScheduler(const scheduler::RefreshRateConfigs& configs)
           : Scheduler([](bool) {}, configs, *this) {
-        mLayerHistory.emplace();
+        mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
     }
 
     TestableScheduler(std::unique_ptr<DispSync> primaryDispSync,
                       std::unique_ptr<EventControlThread> eventControlThread,
                       const scheduler::RefreshRateConfigs& configs)
           : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this) {
-        mLayerHistory.emplace();
+        mLayerHistory = std::make_unique<scheduler::impl::LayerHistory>();
     }
 
     // Used to inject mock event thread.
@@ -46,7 +46,7 @@
     }
 
     size_t layerHistorySize() const NO_THREAD_SAFETY_ANALYSIS {
-        return mLayerHistory->mLayerInfos.size();
+        return static_cast<scheduler::impl::LayerHistory*>(mLayerHistory.get())->mLayerInfos.size();
     }
 
     /* ------------------------------------------------------------------------
@@ -57,7 +57,9 @@
     auto& mutableEventControlThread() { return mEventControlThread; }
     auto& mutablePrimaryDispSync() { return mPrimaryDispSync; }
     auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; }
-    auto& mutableLayerHistory() { return mLayerHistory; }
+    auto mutableLayerHistory() {
+        return static_cast<scheduler::impl::LayerHistory*>(mLayerHistory.get());
+    }
 
     ~TestableScheduler() {
         // All these pointer and container clears help ensure that GMock does