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; };