SF: Move ownership of VsyncModulator to Scheduler
...as a prerequisite for calculating the VSYNC deadline of the leader
display (and deriving per-display state from it, e.g. present fences,
traces) in the Scheduler.
Bug: 241285475
Bug: 241285191
Test: Boot
Change-Id: Ieea136616435464dd0756525f94441b8e82ad06a
diff --git a/services/surfaceflinger/RegionSamplingThread.h b/services/surfaceflinger/RegionSamplingThread.h
index b62b15c..e8c891e 100644
--- a/services/surfaceflinger/RegionSamplingThread.h
+++ b/services/surfaceflinger/RegionSamplingThread.h
@@ -37,7 +37,6 @@
namespace android {
class Layer;
-class Scheduler;
class SurfaceFlinger;
struct SamplingOffsetCallback;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index bc465ce..1fc1519 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -60,8 +60,12 @@
namespace android::scheduler {
-Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features)
- : impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {}
+Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
+ sp<VsyncModulator> modulatorPtr)
+ : impl::MessageQueue(compositor),
+ mFeatures(features),
+ mVsyncModulator(std::move(modulatorPtr)),
+ mSchedulerCallback(callback) {}
Scheduler::~Scheduler() {
// MessageQueue depends on VsyncSchedule, so first destroy it.
@@ -186,17 +190,19 @@
};
}
-ConnectionHandle Scheduler::createConnection(const char* connectionName,
- frametimeline::TokenManager* tokenManager,
- std::chrono::nanoseconds workDuration,
- std::chrono::nanoseconds readyDuration) {
- auto throttleVsync = makeThrottleVsyncCallback();
- auto getVsyncPeriod = makeGetVsyncPeriodFunction();
- auto eventThread =
- std::make_unique<impl::EventThread>(connectionName, *mVsyncSchedule, tokenManager,
- std::move(throttleVsync), std::move(getVsyncPeriod),
- workDuration, readyDuration);
- return createConnection(std::move(eventThread));
+ConnectionHandle Scheduler::createEventThread(Cycle cycle,
+ frametimeline::TokenManager* tokenManager,
+ std::chrono::nanoseconds workDuration,
+ std::chrono::nanoseconds readyDuration) {
+ auto eventThread = std::make_unique<impl::EventThread>(cycle == Cycle::Render ? "app" : "appSf",
+ *mVsyncSchedule, tokenManager,
+ makeThrottleVsyncCallback(),
+ makeGetVsyncPeriodFunction(),
+ workDuration, readyDuration);
+
+ auto& handle = cycle == Cycle::Render ? mAppConnectionHandle : mSfConnectionHandle;
+ handle = createConnection(std::move(eventThread));
+ return handle;
}
ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
@@ -356,6 +362,20 @@
thread->setDuration(workDuration, readyDuration);
}
+void Scheduler::setVsyncConfigSet(const VsyncConfigSet& configs, Period vsyncPeriod) {
+ setVsyncConfig(mVsyncModulator->setVsyncConfigSet(configs), vsyncPeriod);
+}
+
+void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
+ setDuration(mAppConnectionHandle,
+ /* workDuration */ config.appWorkDuration,
+ /* readyDuration */ config.sfWorkDuration);
+ setDuration(mSfConnectionHandle,
+ /* workDuration */ vsyncPeriod,
+ /* readyDuration */ config.sfWorkDuration);
+ setDuration(config.sfWorkDuration);
+}
+
void Scheduler::enableHardwareVsync() {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index a3e28b6..ef7d0cf 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -36,6 +36,7 @@
#include <ftl/optional.h>
#include <scheduler/Features.h>
#include <scheduler/Time.h>
+#include <scheduler/VsyncConfig.h>
#include <ui/DisplayId.h>
#include "Display/DisplayMap.h"
@@ -47,6 +48,7 @@
#include "OneShotTimer.h"
#include "RefreshRateSelector.h"
#include "Utils/Dumper.h"
+#include "VsyncModulator.h"
#include "VsyncSchedule.h"
namespace android::scheduler {
@@ -104,7 +106,7 @@
using Impl = android::impl::MessageQueue;
public:
- Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags);
+ Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>);
virtual ~Scheduler();
void startTimers();
@@ -146,9 +148,14 @@
return std::move(future);
}
- ConnectionHandle createConnection(const char* connectionName, frametimeline::TokenManager*,
- std::chrono::nanoseconds workDuration,
- std::chrono::nanoseconds readyDuration);
+ enum class Cycle {
+ Render, // Surface rendering.
+ LastComposite // Ahead of display compositing by one refresh period.
+ };
+
+ ConnectionHandle createEventThread(Cycle, frametimeline::TokenManager*,
+ std::chrono::nanoseconds workDuration,
+ std::chrono::nanoseconds readyDuration);
sp<IDisplayEventConnection> createDisplayEventConnection(
ConnectionHandle, EventRegistrationFlags eventRegistration = {});
@@ -168,6 +175,18 @@
void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration);
+ const VsyncModulator& vsyncModulator() const { return *mVsyncModulator; }
+
+ template <typename... Args,
+ typename Handler = std::optional<VsyncConfig> (VsyncModulator::*)(Args...)>
+ void modulateVsync(Handler handler, Args... args) {
+ if (const auto config = (*mVsyncModulator.*handler)(args...)) {
+ setVsyncConfig(*config, getLeaderVsyncPeriod());
+ }
+ }
+
+ void setVsyncConfigSet(const VsyncConfigSet&, Period vsyncPeriod);
+
// Sets the render rate for the scheduler to run at.
void setRenderRate(Fps);
@@ -270,6 +289,7 @@
void displayPowerTimerCallback(TimerState);
void setVsyncPeriod(nsecs_t period);
+ void setVsyncConfig(const VsyncConfig&, Period vsyncPeriod);
// Chooses a leader among the registered displays, unless `leaderIdOpt` is specified. The new
// `mLeaderDisplayId` is never `std::nullopt`.
@@ -330,6 +350,9 @@
mutable std::mutex mConnectionsLock;
std::unordered_map<ConnectionHandle, Connection> mConnections GUARDED_BY(mConnectionsLock);
+ ConnectionHandle mAppConnectionHandle;
+ ConnectionHandle mSfConnectionHandle;
+
mutable std::mutex mHWVsyncLock;
bool mPrimaryHWVsyncEnabled GUARDED_BY(mHWVsyncLock) = false;
bool mHWVsyncAvailable GUARDED_BY(mHWVsyncLock) = false;
@@ -339,6 +362,9 @@
const FeatureFlags mFeatures;
std::optional<VsyncSchedule> mVsyncSchedule;
+ // Shifts the VSYNC phase during certain transactions and refresh rate changes.
+ const sp<VsyncModulator> mVsyncModulator;
+
// Used to choose refresh rate if content detection is enabled.
LayerHistory mLayerHistory;
diff --git a/services/surfaceflinger/Scheduler/VsyncModulator.h b/services/surfaceflinger/Scheduler/VsyncModulator.h
index 4b01ec3..dc4dafd 100644
--- a/services/surfaceflinger/Scheduler/VsyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VsyncModulator.h
@@ -25,21 +25,13 @@
#include <binder/IBinder.h>
#include <utils/Timers.h>
+#include <scheduler/TransactionSchedule.h>
#include <scheduler/VsyncConfig.h>
#include "../WpHash.h"
namespace android::scheduler {
-// State machine controlled by transaction flags. VsyncModulator switches to early phase offsets
-// when a transaction is flagged EarlyStart or Early, lasting until an EarlyEnd transaction or a
-// fixed number of frames, respectively.
-enum class TransactionSchedule {
- Late, // Default.
- EarlyStart,
- EarlyEnd
-};
-
// Modulates VSYNC phase depending on transaction schedule and refresh rate changes.
class VsyncModulator : public IBinder::DeathRecipient {
public:
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/TransactionSchedule.h b/services/surfaceflinger/Scheduler/include/scheduler/TransactionSchedule.h
new file mode 100644
index 0000000..6fc44dd
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/include/scheduler/TransactionSchedule.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 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
+
+namespace android::scheduler {
+
+// State machine controlled by transaction flags. VsyncModulator switches to early phase offsets
+// when a transaction is flagged EarlyStart or Early, lasting until an EarlyEnd transaction or a
+// fixed number of frames, respectively.
+enum class TransactionSchedule {
+ Late, // Default.
+ EarlyStart,
+ EarlyEnd
+};
+
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6a056d3..be055b2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -142,6 +142,7 @@
#include "Scheduler/LayerHistory.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VsyncConfiguration.h"
+#include "Scheduler/VsyncModulator.h"
#include "ScreenCaptureOutput.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlingerProperties.h"
@@ -189,6 +190,7 @@
using gui::LayerMetadata;
using gui::WindowInfo;
using gui::aidl_utils::binderStatusFromStatusT;
+using scheduler::VsyncModulator;
using ui::Dataspace;
using ui::DisplayPrimaries;
using ui::RenderIntent;
@@ -1163,7 +1165,7 @@
mScheduler->resyncToHardwareVsync(true, mode.modePtr->getFps());
// As we called to set period, we will call to onRefreshRateChangeCompleted once
// VsyncController model is locked.
- modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
+ mScheduler->modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
updatePhaseConfiguration(mode.fps);
mScheduler->setModeChangePending(true);
@@ -2039,7 +2041,7 @@
bool periodFlushed = false;
mScheduler->addResyncSample(timestamp, vsyncPeriod, &periodFlushed);
if (periodFlushed) {
- modulateVsync(&VsyncModulator::onRefreshRateChangeCompleted);
+ mScheduler->modulateVsync(&VsyncModulator::onRefreshRateChangeCompleted);
}
}
@@ -2117,7 +2119,7 @@
const auto& schedule = mScheduler->getVsyncSchedule();
const TimePoint vsyncDeadline = schedule.vsyncDeadlineAfter(frameTime);
- if (mVsyncModulator->getVsyncConfig().sfOffset > 0) {
+ if (mScheduler->vsyncModulator().getVsyncConfig().sfOffset > 0) {
return vsyncDeadline;
}
@@ -2231,17 +2233,19 @@
mPowerHintSessionEnabled = mPowerAdvisor->usePowerHintSession() && activeDisplay &&
activeDisplay->getPowerMode() == hal::PowerMode::ON;
if (mPowerHintSessionEnabled) {
- const auto& display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get();
- const Period vsyncPeriod = Period::fromNs(display->getActiveMode().fps.getPeriodNsecs());
mPowerAdvisor->setCommitStart(frameTime);
mPowerAdvisor->setExpectedPresentTime(mExpectedPresentTime);
// Frame delay is how long we should have minus how long we actually have.
- const Duration idealSfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration;
+ const Duration idealSfWorkDuration =
+ mScheduler->vsyncModulator().getVsyncConfig().sfWorkDuration;
const Duration frameDelay = idealSfWorkDuration - (mExpectedPresentTime - frameTime);
mPowerAdvisor->setFrameDelay(frameDelay);
mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration);
+
+ const auto& display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get();
+ const Period vsyncPeriod = display->getActiveMode().fps.getPeriod();
mPowerAdvisor->setTargetWorkDuration(vsyncPeriod);
// Send early hint here to make sure there's not another frame pending
@@ -2468,7 +2472,7 @@
// TODO: b/160583065 Enable skip validation when SF caches all client composition layers
const bool usedGpuComposition = mHadClientComposition || mReusedClientComposition;
- modulateVsync(&VsyncModulator::onDisplayRefresh, usedGpuComposition);
+ mScheduler->modulateVsync(&VsyncModulator::onDisplayRefresh, usedGpuComposition);
mLayersWithQueuedFrames.clear();
if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
@@ -2791,7 +2795,7 @@
// so we can call commitTransactionsLocked unconditionally.
// We clear the flags with mStateLock held to guarantee that
// mCurrentState won't change until the transaction is committed.
- modulateVsync(&VsyncModulator::onTransactionCommit);
+ mScheduler->modulateVsync(&VsyncModulator::onTransactionCommit);
commitTransactionsLocked(clearTransactionFlags(eTransactionMask));
mDebugInTransaction = 0;
@@ -3592,19 +3596,18 @@
}
void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
+ using namespace scheduler;
+
LOG_ALWAYS_FATAL_IF(mScheduler);
const auto activeMode = display->refreshRateSelector().getActiveMode();
const Fps activeRefreshRate = activeMode.fps;
mRefreshRateStats =
- std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, activeRefreshRate,
- hal::PowerMode::OFF);
+ std::make_unique<RefreshRateStats>(*mTimeStats, activeRefreshRate, hal::PowerMode::OFF);
mVsyncConfiguration = getFactory().createVsyncConfiguration(activeRefreshRate);
- mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
- using Feature = scheduler::Feature;
- scheduler::FeatureFlags features;
+ FeatureFlags features;
if (sysprop::use_content_detection_for_refresh_rate(false)) {
features |= Feature::kContentDetection;
@@ -3620,9 +3623,11 @@
features |= Feature::kKernelIdleTimer;
}
- mScheduler = std::make_unique<scheduler::Scheduler>(static_cast<ICompositor&>(*this),
- static_cast<ISchedulerCallback&>(*this),
- features);
+ auto modulatorPtr = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
+
+ mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
+ static_cast<ISchedulerCallback&>(*this), features,
+ std::move(modulatorPtr));
mScheduler->createVsyncSchedule(features);
mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector());
@@ -3630,15 +3635,17 @@
mScheduler->startTimers();
const auto configs = mVsyncConfiguration->getCurrentConfigs();
- const nsecs_t vsyncPeriod = activeRefreshRate.getPeriodNsecs();
+
mAppConnectionHandle =
- mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
- /*workDuration=*/configs.late.appWorkDuration,
- /*readyDuration=*/configs.late.sfWorkDuration);
+ mScheduler->createEventThread(Scheduler::Cycle::Render,
+ mFrameTimeline->getTokenManager(),
+ /* workDuration */ configs.late.appWorkDuration,
+ /* readyDuration */ configs.late.sfWorkDuration);
mSfConnectionHandle =
- mScheduler->createConnection("appSf", mFrameTimeline->getTokenManager(),
- /*workDuration=*/std::chrono::nanoseconds(vsyncPeriod),
- /*readyDuration=*/configs.late.sfWorkDuration);
+ mScheduler->createEventThread(Scheduler::Cycle::LastComposite,
+ mFrameTimeline->getTokenManager(),
+ /* workDuration */ activeRefreshRate.getPeriod(),
+ /* readyDuration */ configs.late.sfWorkDuration);
mScheduler->initVsync(mScheduler->getVsyncSchedule().getDispatch(),
*mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
@@ -3649,20 +3656,10 @@
mFpsReporter = sp<FpsReporter>::make(*mFrameTimeline, *this);
}
-void SurfaceFlinger::updatePhaseConfiguration(const Fps& refreshRate) {
+void SurfaceFlinger::updatePhaseConfiguration(Fps refreshRate) {
mVsyncConfiguration->setRefreshRateFps(refreshRate);
- setVsyncConfig(mVsyncModulator->setVsyncConfigSet(mVsyncConfiguration->getCurrentConfigs()),
- refreshRate.getPeriod());
-}
-
-void SurfaceFlinger::setVsyncConfig(const scheduler::VsyncConfig& config, Period vsyncPeriod) {
- mScheduler->setDuration(mAppConnectionHandle,
- /* workDuration */ config.appWorkDuration,
- /* readyDuration */ config.sfWorkDuration);
- mScheduler->setDuration(mSfConnectionHandle,
- /* workDuration */ vsyncPeriod,
- /* readyDuration */ config.sfWorkDuration);
- mScheduler->setDuration(config.sfWorkDuration);
+ mScheduler->setVsyncConfigSet(mVsyncConfiguration->getCurrentConfigs(),
+ refreshRate.getPeriod());
}
void SurfaceFlinger::doCommitTransactions() {
@@ -3861,7 +3858,7 @@
void SurfaceFlinger::setTransactionFlags(uint32_t mask, TransactionSchedule schedule,
const sp<IBinder>& applyToken, FrameHint frameHint) {
- modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken);
+ mScheduler->modulateVsync(&VsyncModulator::setTransactionSchedule, schedule, applyToken);
if (const bool scheduled = mTransactionFlags.fetch_or(mask) & mask; !scheduled) {
scheduleCommit(frameHint);
@@ -4066,7 +4063,7 @@
// We don't want to latch unsignaled if are in early / client composition
// as it leads to jank due to RenderEngine waiting for unsignaled buffer
// or window animations being slow.
- const auto isDefaultVsyncConfig = mVsyncModulator->isVsyncConfigDefault();
+ const auto isDefaultVsyncConfig = mScheduler->vsyncModulator().isVsyncConfigDefault();
if (!isDefaultVsyncConfig) {
ALOGV("%s: false (LatchUnsignaledConfig::AutoSingleLayer; !isDefaultVsyncConfig)",
__func__);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a49c623..3121a34 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -56,6 +56,7 @@
#include <scheduler/Fps.h>
#include <scheduler/PresentLatencyTracker.h>
#include <scheduler/Time.h>
+#include <scheduler/TransactionSchedule.h>
#include <ui/FenceResult.h>
#include "Display/DisplayMap.h"
@@ -73,7 +74,6 @@
#include "Scheduler/RefreshRateSelector.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/Scheduler.h"
-#include "Scheduler/VsyncModulator.h"
#include "SurfaceFlingerFactory.h"
#include "ThreadContext.h"
#include "Tracing/LayerTracing.h"
@@ -352,7 +352,6 @@
friend class TransactionApplicationTest;
friend class TunnelModeEnabledReporterTest;
- using VsyncModulator = scheduler::VsyncModulator;
using TransactionSchedule = scheduler::TransactionSchedule;
using TraverseLayersFunction = std::function<void(const LayerVector::Visitor&)>;
using RenderAreaFuture = ftl::Future<std::unique_ptr<RenderArea>>;
@@ -470,14 +469,6 @@
return std::bind(dump, this, _1, _2, _3);
}
- template <typename... Args,
- typename Handler = VsyncModulator::VsyncConfigOpt (VsyncModulator::*)(Args...)>
- void modulateVsync(Handler handler, Args... args) {
- if (const auto config = (*mVsyncModulator.*handler)(args...)) {
- setVsyncConfig(*config, mScheduler->getLeaderVsyncPeriod());
- }
- }
-
// Maximum allowed number of display frames that can be set through backdoor
static const int MAX_ALLOWED_DISPLAY_FRAMES = 2048;
@@ -710,8 +701,7 @@
void updateCursorAsync();
void initScheduler(const sp<const DisplayDevice>&) REQUIRES(kMainThreadContext, mStateLock);
- void updatePhaseConfiguration(const Fps&) REQUIRES(mStateLock);
- void setVsyncConfig(const scheduler::VsyncConfig&, Period vsyncPeriod);
+ void updatePhaseConfiguration(Fps) REQUIRES(mStateLock);
/*
* Transactions
@@ -1290,9 +1280,6 @@
// Stores phase offsets configured per refresh rate.
std::unique_ptr<scheduler::VsyncConfiguration> mVsyncConfiguration;
- // Optional to defer construction until PhaseConfiguration is created.
- sp<VsyncModulator> mVsyncModulator;
-
std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
scheduler::PresentLatencyTracker mPresentLatencyTracker GUARDED_BY(kMainThreadContext);
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 9773644..cdffbb4 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -224,16 +224,16 @@
class TestableScheduler : public Scheduler, private ICompositor {
public:
TestableScheduler(const std::shared_ptr<scheduler::RefreshRateSelector>& selectorPtr,
- ISchedulerCallback& callback)
+ sp<VsyncModulator> modulatorPtr, ISchedulerCallback& callback)
: TestableScheduler(std::make_unique<android::mock::VsyncController>(),
std::make_unique<android::mock::VSyncTracker>(), selectorPtr,
- callback) {}
+ std::move(modulatorPtr), callback) {}
TestableScheduler(std::unique_ptr<VsyncController> controller,
std::unique_ptr<VSyncTracker> tracker,
std::shared_ptr<RefreshRateSelector> selectorPtr,
- ISchedulerCallback& callback)
- : Scheduler(*this, callback, Feature::kContentDetection) {
+ sp<VsyncModulator> modulatorPtr, ISchedulerCallback& callback)
+ : Scheduler(*this, callback, Feature::kContentDetection, std::move(modulatorPtr)) {
mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
const auto displayId = selectorPtr->getActiveMode().modePtr->getPhysicalDisplayId();
@@ -281,6 +281,8 @@
return Scheduler::onNonPrimaryDisplayModeChanged(handle, mode);
}
+ using Scheduler::setVsyncConfig;
+
private:
// ICompositor overrides:
void configure() override {}
@@ -593,11 +595,11 @@
mFlinger->updateInputFlinger();
mFlinger->updateCursorAsync();
- mFlinger->setVsyncConfig({.sfOffset = mFdp.ConsumeIntegral<nsecs_t>(),
- .appOffset = mFdp.ConsumeIntegral<nsecs_t>(),
- .sfWorkDuration = getFuzzedDuration(mFdp),
- .appWorkDuration = getFuzzedDuration(mFdp)},
- getFuzzedDuration(mFdp));
+ mutableScheduler().setVsyncConfig({.sfOffset = mFdp.ConsumeIntegral<nsecs_t>(),
+ .appOffset = mFdp.ConsumeIntegral<nsecs_t>(),
+ .sfWorkDuration = getFuzzedDuration(mFdp),
+ .appWorkDuration = getFuzzedDuration(mFdp)},
+ getFuzzedDuration(mFdp));
{
ftl::FakeGuard guard(kMainThreadContext);
@@ -663,15 +665,17 @@
mRefreshRateSelector = std::make_shared<scheduler::RefreshRateSelector>(modes, kModeId60);
const auto fps = mRefreshRateSelector->getActiveMode().modePtr->getFps();
mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
- mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
- mFlinger->mVsyncConfiguration->getCurrentConfigs());
+
mFlinger->mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, fps,
hal::PowerMode::OFF);
+ auto modulatorPtr = sp<scheduler::VsyncModulator>::make(
+ mFlinger->mVsyncConfiguration->getCurrentConfigs());
+
mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
std::move(vsyncTracker), mRefreshRateSelector,
- *(callback ?: this));
+ std::move(modulatorPtr), *(callback ?: this));
mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 0f53eb6..0cbfa63 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -37,12 +37,12 @@
TestableScheduler(RefreshRateSelectorPtr selectorPtr, ISchedulerCallback& callback)
: TestableScheduler(std::make_unique<mock::VsyncController>(),
std::make_unique<mock::VSyncTracker>(), std::move(selectorPtr),
- callback) {}
+ /* modulatorPtr */ nullptr, callback) {}
TestableScheduler(std::unique_ptr<VsyncController> controller,
std::unique_ptr<VSyncTracker> tracker, RefreshRateSelectorPtr selectorPtr,
- ISchedulerCallback& callback)
- : Scheduler(*this, callback, Feature::kContentDetection) {
+ sp<VsyncModulator> modulatorPtr, ISchedulerCallback& callback)
+ : Scheduler(*this, callback, Feature::kContentDetection, std::move(modulatorPtr)) {
mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker),
std::make_unique<mock::VSyncDispatch>(),
std::move(controller)));
@@ -99,6 +99,7 @@
Scheduler::setLeaderDisplay(displayId);
}
+ auto& mutableVsyncModulator() { return *mVsyncModulator; }
auto& mutableLayerHistory() { return mLayerHistory; }
size_t layerHistorySize() NO_THREAD_SAFETY_ANALYSIS {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 72e0c7b..51d2012 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -224,8 +224,6 @@
const auto fps = selectorPtr->getActiveMode().fps;
mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(fps);
- mFlinger->mVsyncModulator = sp<scheduler::VsyncModulator>::make(
- mFlinger->mVsyncConfiguration->getCurrentConfigs());
mFlinger->mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, fps,
@@ -238,16 +236,21 @@
? static_cast<Callback&>(mNoOpSchedulerCallback)
: static_cast<Callback&>(mSchedulerCallback);
+ auto modulatorPtr = sp<scheduler::VsyncModulator>::make(
+ mFlinger->mVsyncConfiguration->getCurrentConfigs());
+
if (useNiceMock) {
mScheduler =
new testing::NiceMock<scheduler::TestableScheduler>(std::move(vsyncController),
std::move(vsyncTracker),
std::move(selectorPtr),
+ std::move(modulatorPtr),
callback);
} else {
mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
std::move(vsyncTracker),
- std::move(selectorPtr), callback);
+ std::move(selectorPtr),
+ std::move(modulatorPtr), callback);
}
mScheduler->initVsync(mScheduler->getVsyncSchedule().getDispatch(), *mTokenManager, 0ms);
@@ -262,8 +265,6 @@
scheduler::TestableScheduler& mutableScheduler() { return *mScheduler; }
scheduler::mock::SchedulerCallback& mockSchedulerCallback() { return mSchedulerCallback; }
- auto& mutableVsyncModulator() { return mFlinger->mVsyncModulator; }
-
using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
mFactory.mCreateBufferQueue = f;
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index a28d1cd..859f702 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -228,6 +228,11 @@
EXPECT_EQ(0u, transactionQueue.size());
}
+ void modulateVsync() {
+ static_cast<void>(
+ mFlinger.mutableScheduler().mutableVsyncModulator().onRefreshRateChangeInitiated());
+ }
+
bool mHasListenerCallbacks = false;
std::vector<ListenerCallbacks> mCallbacks;
int mTransactionNumber = 0;
@@ -623,9 +628,7 @@
layer_state_t::eBufferChanged),
});
- // Get VsyncModulator out of the default config
- static_cast<void>(mFlinger.mutableVsyncModulator()->onRefreshRateChangeInitiated());
-
+ modulateVsync();
setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
}
@@ -985,9 +988,7 @@
layer_state_t::eBufferChanged),
});
- // Get VsyncModulator out of the default config
- static_cast<void>(mFlinger.mutableVsyncModulator()->onRefreshRateChangeInitiated());
-
+ modulateVsync();
setTransactionStates({unsignaledTransaction}, kExpectedTransactionsPending);
}