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/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