SF: Unify data types for display modes

Remove the RefreshRateConfigs::RefreshRate wrapper around DisplayMode.
Store DisplayModes as a SmallMap, so that RefreshRateConfigs uses the
same data structure for lookup by ID. Use iterators into that map for
all bookkeeping in RefreshRateConfigs.

Bug: 182939859
Bug: 185535769
Test: libsurfaceflinger_unittest
Change-Id: I7708fa997089802c45d906b17b7a073f5c82105e
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index b796dfe..93abc9f 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -55,6 +55,7 @@
 #include "renderengine/mock/RenderEngine.h"
 #include "scheduler/TimeKeeper.h"
 #include "tests/unittests/mock/DisplayHardware/MockComposer.h"
+#include "tests/unittests/mock/DisplayHardware/MockDisplayMode.h"
 #include "tests/unittests/mock/DisplayHardware/MockHWC2.h"
 #include "tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h"
 #include "tests/unittests/mock/MockEventThread.h"
@@ -207,7 +208,9 @@
     void setRefreshRateFps(Fps) override {}
     void dump(std::string &) const override {}
 };
+
 namespace scheduler {
+
 class TestableScheduler : public Scheduler, private ICompositor {
 public:
     TestableScheduler(const std::shared_ptr<scheduler::RefreshRateConfigs> &refreshRateConfigs,
@@ -216,9 +219,6 @@
                               std::make_unique<android::mock::VSyncTracker>(), refreshRateConfigs,
                               callback) {}
 
-    void scheduleFrame(){};
-    void postMessage(sp<MessageHandler> &&){};
-
     TestableScheduler(std::unique_ptr<VsyncController> controller,
                       std::unique_ptr<VSyncTracker> tracker,
                       std::shared_ptr<RefreshRateConfigs> configs, ISchedulerCallback &callback)
@@ -273,8 +273,13 @@
     bool commit(nsecs_t, int64_t, nsecs_t) override { return false; }
     void composite(nsecs_t, int64_t) override {}
     void sample() override {}
+
+    // MessageQueue overrides:
+    void scheduleFrame() override {}
+    void postMessage(sp<MessageHandler>&&) override {}
 };
-}; // namespace scheduler
+
+} // namespace scheduler
 
 namespace surfaceflinger::test {
 
@@ -405,8 +410,6 @@
         return mFlinger->onInitializeDisplays();
     }
 
-    void scheduleComposite(FrameHint){};
-
     void setGlobalShadowSettings(FuzzedDataProvider *fdp) {
         const half4 ambientColor{fdp->ConsumeFloatingPoint<float>(),
                                  fdp->ConsumeFloatingPoint<float>(),
@@ -678,31 +681,22 @@
                         std::unique_ptr<EventThread> sfEventThread,
                         scheduler::ISchedulerCallback *callback = nullptr,
                         bool hasMultipleModes = false) {
-        DisplayModes modes{DisplayMode::Builder(0)
-                                   .setId(DisplayModeId(0))
-                                   .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
-                                   .setVsyncPeriod(16'666'667)
-                                   .setGroup(0)
-                                   .build()};
+        constexpr DisplayModeId kModeId60{0};
+        DisplayModes modes = makeModes(mock::createDisplayMode(kModeId60, 60_Hz));
 
         if (hasMultipleModes) {
-            modes.emplace_back(DisplayMode::Builder(1)
-                                       .setId(DisplayModeId(1))
-                                       .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
-                                       .setVsyncPeriod(11'111'111)
-                                       .setGroup(0)
-                                       .build());
+            constexpr DisplayModeId kModeId90{1};
+            modes.try_emplace(kModeId90, mock::createDisplayMode(kModeId90, 90_Hz));
         }
 
-        const auto currMode = DisplayModeId(0);
-        mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode);
-        const auto currFps = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
-        mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);
+        mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
+        const auto fps = mRefreshRateConfigs->getActiveMode()->getFps();
+        mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
         mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
                 mFlinger->mVsyncConfiguration->getCurrentConfigs());
         mFlinger->mRefreshRateStats =
-                std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
-                                                              /*powerMode=*/hal::PowerMode::OFF);
+                std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, fps,
+                                                              hal::PowerMode::OFF);
 
         mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
                                                       std::move(vsyncTracker), mRefreshRateConfigs,
@@ -765,8 +759,6 @@
         return mFlinger->setPowerModeInternal(display, mode);
     }
 
-    auto onMessageReceived(int32_t /*what*/) { return 0; }
-
     auto &getTransactionQueue() { return mFlinger->mTransactionQueue; }
     auto &getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
 
@@ -818,15 +810,16 @@
     }
 
 private:
-    void scheduleRefresh(FrameHint) {}
+    void scheduleComposite(FrameHint) override {}
     void setVsyncEnabled(bool) override {}
-    void changeRefreshRate(const RefreshRate &, DisplayModeEvent) override {}
+    void requestDisplayMode(DisplayModePtr, DisplayModeEvent) override {}
     void kernelTimerChanged(bool) override {}
-    void triggerOnFrameRateOverridesChanged() {}
+    void triggerOnFrameRateOverridesChanged() override {}
 
     surfaceflinger::test::Factory mFactory;
     sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
     scheduler::TestableScheduler *mScheduler = nullptr;
     std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
 };
+
 } // namespace android
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index d504155..da60a69 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -15,22 +15,31 @@
  *
  */
 
-#include "surfaceflinger_scheduler_fuzzer.h"
+#include <ftl/enum.h>
 #include <fuzzer/FuzzedDataProvider.h>
 #include <processgroup/sched_policy.h>
+
 #include "Scheduler/DispSyncSource.h"
 #include "Scheduler/OneShotTimer.h"
 #include "Scheduler/VSyncDispatchTimerQueue.h"
 #include "Scheduler/VSyncPredictor.h"
 #include "Scheduler/VSyncReactor.h"
+
 #include "surfaceflinger_fuzzers_utils.h"
+#include "surfaceflinger_scheduler_fuzzer.h"
 
 namespace android::fuzz {
 
 using hardware::graphics::composer::hal::PowerMode;
 
-static constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF,
-                                            PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND};
+constexpr nsecs_t kVsyncPeriods[] = {(30_Hz).getPeriodNsecs(), (60_Hz).getPeriodNsecs(),
+                                     (72_Hz).getPeriodNsecs(), (90_Hz).getPeriodNsecs(),
+                                     (120_Hz).getPeriodNsecs()};
+
+constexpr auto kLayerVoteTypes = ftl::enum_range<scheduler::RefreshRateConfigs::LayerVoteType>();
+
+constexpr PowerMode kPowerModes[] = {PowerMode::ON, PowerMode::DOZE, PowerMode::OFF,
+                                     PowerMode::DOZE_SUSPEND, PowerMode::ON_SUSPEND};
 
 constexpr uint16_t kRandomStringLength = 256;
 constexpr std::chrono::duration kSyncPeriod(16ms);
@@ -319,39 +328,42 @@
     using RefreshRateConfigs = scheduler::RefreshRateConfigs;
     using LayerRequirement = RefreshRateConfigs::LayerRequirement;
     using RefreshRateStats = scheduler::RefreshRateStats;
-    uint16_t minRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX >> 1);
-    uint16_t maxRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(minRefreshRate + 1, UINT16_MAX);
 
-    DisplayModeId hwcConfigIndexType = DisplayModeId(mFdp.ConsumeIntegralInRange<uint8_t>(0, 10));
+    const uint16_t minRefreshRate = mFdp.ConsumeIntegralInRange<uint16_t>(1, UINT16_MAX >> 1);
+    const uint16_t maxRefreshRate =
+            mFdp.ConsumeIntegralInRange<uint16_t>(minRefreshRate + 1, UINT16_MAX);
+
+    const DisplayModeId modeId{mFdp.ConsumeIntegralInRange<uint8_t>(0, 10)};
 
     DisplayModes displayModes;
     for (uint16_t fps = minRefreshRate; fps < maxRefreshRate; ++fps) {
-        constexpr int32_t kGroup = 0;
-        const auto refreshRate = Fps::fromValue(static_cast<float>(fps));
-        displayModes.push_back(scheduler::createDisplayMode(hwcConfigIndexType, kGroup,
-                                                            refreshRate.getPeriodNsecs()));
+        displayModes.try_emplace(modeId,
+                                 mock::createDisplayMode(modeId,
+                                                         Fps::fromValue(static_cast<float>(fps))));
     }
-    auto refreshRateConfigs =
-            std::make_unique<RefreshRateConfigs>(displayModes, hwcConfigIndexType);
+
+    RefreshRateConfigs refreshRateConfigs(displayModes, modeId);
+
     const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false};
-    auto layers = std::vector<LayerRequirement>{
-            LayerRequirement{.weight = mFdp.ConsumeFloatingPoint<float>()}};
-    refreshRateConfigs->getBestRefreshRate(layers, globalSignals);
+    std::vector<LayerRequirement> layers = {{.weight = mFdp.ConsumeFloatingPoint<float>()}};
+
+    refreshRateConfigs.getBestRefreshRate(layers, globalSignals);
+
     layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength);
     layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>();
     layers[0].desiredRefreshRate = Fps::fromValue(mFdp.ConsumeFloatingPoint<float>());
-    layers[0].vote = mFdp.PickValueInArray(kLayerVoteTypes);
+    layers[0].vote = mFdp.PickValueInArray(kLayerVoteTypes.values);
     auto frameRateOverrides =
-            refreshRateConfigs->getFrameRateOverrides(layers,
-                                                      Fps::fromValue(
-                                                              mFdp.ConsumeFloatingPoint<float>()),
-                                                      globalSignals);
+            refreshRateConfigs.getFrameRateOverrides(layers,
+                                                     Fps::fromValue(
+                                                             mFdp.ConsumeFloatingPoint<float>()),
+                                                     globalSignals);
 
-    refreshRateConfigs->setDisplayManagerPolicy(
-            {hwcConfigIndexType,
+    refreshRateConfigs.setDisplayManagerPolicy(
+            {modeId,
              {Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
               Fps::fromValue(mFdp.ConsumeFloatingPoint<float>())}});
-    refreshRateConfigs->setCurrentModeId(hwcConfigIndexType);
+    refreshRateConfigs.setActiveModeId(modeId);
 
     RefreshRateConfigs::isFractionalPairOrMultiple(Fps::fromValue(
                                                            mFdp.ConsumeFloatingPoint<float>()),
@@ -361,13 +373,13 @@
                                             Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()));
 
     android::mock::TimeStats timeStats;
-    std::unique_ptr<RefreshRateStats> refreshRateStats =
-            std::make_unique<RefreshRateStats>(timeStats,
-                                               Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
-                                               PowerMode::OFF);
-    refreshRateStats->setRefreshRate(
-            refreshRateConfigs->getRefreshRateFromModeId(hwcConfigIndexType).getFps());
-    refreshRateStats->setPowerMode(mFdp.PickValueInArray(kPowerModes));
+    RefreshRateStats refreshRateStats(timeStats, Fps::fromValue(mFdp.ConsumeFloatingPoint<float>()),
+                                      PowerMode::OFF);
+
+    const auto fpsOpt = displayModes.get(modeId, [](const auto& mode) { return mode->getFps(); });
+    refreshRateStats.setRefreshRate(*fpsOpt);
+
+    refreshRateStats.setPowerMode(mFdp.PickValueInArray(kPowerModes));
 }
 
 void SchedulerFuzzer::process() {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
index 84b3912..1a49ead 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.h
@@ -22,6 +22,8 @@
 
 #pragma once
 
+#include <scheduler/TimeKeeper.h>
+
 #include "Clock.h"
 #include "Layer.h"
 #include "Scheduler/EventThread.h"
@@ -29,24 +31,9 @@
 #include "Scheduler/Scheduler.h"
 #include "Scheduler/VSyncTracker.h"
 #include "Scheduler/VsyncModulator.h"
-#include "scheduler/TimeKeeper.h"
 
 namespace android::fuzz {
 
-constexpr int64_t kVsyncPeriods[] = {static_cast<int64_t>(1e9f / 30),
-                                     static_cast<int64_t>(1e9f / 60),
-                                     static_cast<int64_t>(1e9f / 72),
-                                     static_cast<int64_t>(1e9f / 90),
-                                     static_cast<int64_t>(1e9f / 120)};
-
-android::scheduler::RefreshRateConfigs::LayerVoteType kLayerVoteTypes[] =
-        {android::scheduler::RefreshRateConfigs::LayerVoteType::NoVote,
-         android::scheduler::RefreshRateConfigs::LayerVoteType::Min,
-         android::scheduler::RefreshRateConfigs::LayerVoteType::Max,
-         android::scheduler::RefreshRateConfigs::LayerVoteType::Heuristic,
-         android::scheduler::RefreshRateConfigs::LayerVoteType::ExplicitDefault,
-         android::scheduler::RefreshRateConfigs::LayerVoteType::ExplicitExactOrMultiple};
-
 class FuzzImplClock : public android::scheduler::Clock {
 public:
     nsecs_t now() const { return 1; }
@@ -168,18 +155,6 @@
 
 namespace android::scheduler {
 
-DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod,
-                                 ui::Size resolution = ui::Size()) {
-    return DisplayMode::Builder(hal::HWConfigId(modeId.value()))
-            .setId(modeId)
-            .setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
-            .setVsyncPeriod(int32_t(vsyncPeriod))
-            .setGroup(group)
-            .setHeight(resolution.height)
-            .setWidth(resolution.width)
-            .build();
-}
-
 class ControllableClock : public TimeKeeper {
 public:
     nsecs_t now() const { return 1; };