SF: Add VsyncSchedule skeleton
Pull the Scheduler::VsyncSchedule struct and related code into its own
file, as it will be extended with more per-display state, e.g. reactor
registrations, resync state machine, etc.
Add <scheduler/Features.h> for feature flags. Move Scheduler into its
namespace.
Bug: 185535769
Test: libsurfaceflinger_unittest
Change-Id: I6e10893632c5abf40380df924791d1fcc27c3cc2
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 29636f8..c9fb7bc 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -194,9 +194,10 @@
"Scheduler/Timer.cpp",
"Scheduler/VSyncDispatchTimerQueue.cpp",
"Scheduler/VSyncPredictor.cpp",
- "Scheduler/VsyncModulator.cpp",
"Scheduler/VSyncReactor.cpp",
"Scheduler/VsyncConfiguration.cpp",
+ "Scheduler/VsyncModulator.cpp",
+ "Scheduler/VsyncSchedule.cpp",
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
"SurfaceFlingerDefaultFactory.cpp",
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index dec7cc0..926aa1d 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -372,8 +372,9 @@
// Add this buffer from our internal queue tracker
{ // Autolock scope
const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp;
- mFlinger->mScheduler->recordLayerHistory(this, presentTime,
- LayerHistory::LayerUpdateType::Buffer);
+
+ using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
+ mFlinger->mScheduler->recordLayerHistory(this, presentTime, LayerUpdateType::Buffer);
Mutex::Autolock lock(mQueueItemLock);
// Reset the frame number tracker when we receive the first buffer after
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index b4ccb80..7d40fc8 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -476,8 +476,9 @@
return static_cast<nsecs_t>(0);
}();
- mFlinger->mScheduler->recordLayerHistory(this, presentTime,
- LayerHistory::LayerUpdateType::Buffer);
+
+ using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
+ mFlinger->mScheduler->recordLayerHistory(this, presentTime, LayerUpdateType::Buffer);
addFrameEvent(mDrawingState.acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index fd09ae4..76bbe2c 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -483,7 +483,7 @@
std::scoped_lock lock(mActiveModeLock);
if (mDesiredActiveModeChanged) {
// If a mode change is pending, just cache the latest request in mDesiredActiveMode
- const Scheduler::ModeEvent prevConfig = mDesiredActiveMode.event;
+ const auto prevConfig = mDesiredActiveMode.event;
mDesiredActiveMode = info;
mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig;
return false;
@@ -508,7 +508,7 @@
void DisplayDevice::clearDesiredActiveModeState() {
std::scoped_lock lock(mActiveModeLock);
- mDesiredActiveMode.event = Scheduler::ModeEvent::None;
+ mDesiredActiveMode.event = scheduler::DisplayModeEvent::None;
mDesiredActiveModeChanged = false;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 4b9718f..324145e 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -190,7 +190,7 @@
struct ActiveModeInfo {
DisplayModePtr mode;
- scheduler::RefreshRateConfigEvent event = scheduler::RefreshRateConfigEvent::None;
+ scheduler::DisplayModeEvent event = scheduler::DisplayModeEvent::None;
bool operator!=(const ActiveModeInfo& other) const {
return mode != other.mode || event != other.event;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 968a49d..b3ea94f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1293,8 +1293,8 @@
mDrawingState.modified = true;
setTransactionFlags(eTransactionNeeded);
- mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
- LayerHistory::LayerUpdateType::SetFrameRate);
+ using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
+ mFlinger->mScheduler->recordLayerHistory(this, systemTime(), LayerUpdateType::SetFrameRate);
return true;
}
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 92236f5..8d56951 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -31,11 +31,9 @@
namespace android {
class Layer;
-class TestableScheduler;
namespace scheduler {
-class LayerHistoryTest;
class LayerInfo;
class LayerHistory {
@@ -75,8 +73,8 @@
std::string dump() const;
private:
- friend LayerHistoryTest;
- friend TestableScheduler;
+ friend class LayerHistoryTest;
+ friend class TestableScheduler;
using LayerPair = std::pair<Layer*, std::unique_ptr<LayerInfo>>;
using LayerInfos = std::vector<LayerPair>;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 8a1c206..492feb1 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -37,11 +37,11 @@
using namespace std::chrono_literals;
-enum class RefreshRateConfigEvent : unsigned { None = 0b0, Changed = 0b1 };
+enum class DisplayModeEvent : unsigned { None = 0b0, Changed = 0b1 };
-inline RefreshRateConfigEvent operator|(RefreshRateConfigEvent lhs, RefreshRateConfigEvent rhs) {
- using T = std::underlying_type_t<RefreshRateConfigEvent>;
- return static_cast<RefreshRateConfigEvent>(static_cast<T>(lhs) | static_cast<T>(rhs));
+inline DisplayModeEvent operator|(DisplayModeEvent lhs, DisplayModeEvent rhs) {
+ using T = std::underlying_type_t<DisplayModeEvent>;
+ return static_cast<DisplayModeEvent>(static_cast<T>(lhs) | static_cast<T>(rhs));
}
using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 4d72798..cbe4552 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -46,11 +46,8 @@
#include "OneShotTimer.h"
#include "SchedulerUtils.h"
#include "SurfaceFlingerProperties.h"
-#include "Timer.h"
-#include "VSyncDispatchTimerQueue.h"
#include "VSyncPredictor.h"
#include "VSyncReactor.h"
-#include "VsyncController.h"
#define RETURN_IF_INVALID_HANDLE(handle, ...) \
do { \
@@ -60,68 +57,14 @@
} \
} while (false)
-using namespace std::string_literals;
+namespace android::scheduler {
-namespace android {
-
-using gui::WindowInfo;
-
-namespace {
-
-std::unique_ptr<scheduler::VSyncTracker> createVSyncTracker() {
- // TODO(b/144707443): Tune constants.
- constexpr int kDefaultRate = 60;
- constexpr auto initialPeriod = std::chrono::duration<nsecs_t, std::ratio<1, kDefaultRate>>(1);
- constexpr nsecs_t idealPeriod =
- std::chrono::duration_cast<std::chrono::nanoseconds>(initialPeriod).count();
- constexpr size_t vsyncTimestampHistorySize = 20;
- constexpr size_t minimumSamplesForPrediction = 6;
- constexpr uint32_t discardOutlierPercent = 20;
- return std::make_unique<scheduler::VSyncPredictor>(idealPeriod, vsyncTimestampHistorySize,
- minimumSamplesForPrediction,
- discardOutlierPercent);
-}
-
-std::unique_ptr<scheduler::VSyncDispatch> createVSyncDispatch(scheduler::VSyncTracker& tracker) {
- // TODO(b/144707443): Tune constants.
- constexpr std::chrono::nanoseconds vsyncMoveThreshold = 3ms;
- constexpr std::chrono::nanoseconds timerSlack = 500us;
- return std::make_unique<
- scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), tracker,
- timerSlack.count(), vsyncMoveThreshold.count());
-}
-
-const char* toContentDetectionString(bool useContentDetection) {
- return useContentDetection ? "on" : "off";
-}
-
-} // namespace
-
-class PredictedVsyncTracer {
-public:
- PredictedVsyncTracer(scheduler::VSyncDispatch& dispatch)
- : mRegistration(dispatch, std::bind(&PredictedVsyncTracer::callback, this),
- "PredictedVsyncTracer") {
- scheduleRegistration();
- }
-
-private:
- TracedOrdinal<bool> mParity = {"VSYNC-predicted", 0};
- scheduler::VSyncCallbackRegistration mRegistration;
-
- void scheduleRegistration() { mRegistration.schedule({0, 0, 0}); }
-
- void callback() {
- mParity = !mParity;
- scheduleRegistration();
- }
-};
-
-Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, Options options)
- : impl::MessageQueue(compositor), mOptions(options), mSchedulerCallback(callback) {}
+Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features)
+ : impl::MessageQueue(compositor), mFeatures(features), mSchedulerCallback(callback) {}
void Scheduler::startTimers() {
using namespace sysprop;
+ using namespace std::string_literals;
if (const int64_t millis = set_touch_timer_ms(0); millis > 0) {
// Touch events are coming to SF every 100ms, so the timer needs to be higher than that
@@ -154,27 +97,14 @@
}
}
-void Scheduler::createVsyncSchedule(bool supportKernelTimer) {
- auto clock = std::make_unique<scheduler::SystemClock>();
- auto tracker = createVSyncTracker();
- auto dispatch = createVSyncDispatch(*tracker);
-
- // TODO(b/144707443): Tune constants.
- constexpr size_t pendingFenceLimit = 20;
- auto controller =
- std::make_unique<scheduler::VSyncReactor>(std::move(clock), *tracker, pendingFenceLimit,
- supportKernelTimer);
- mVsyncSchedule = {std::move(controller), std::move(tracker), std::move(dispatch)};
-
- if (base::GetBoolProperty("debug.sf.show_predicted_vsync", false)) {
- mPredictedVsyncTracer = std::make_unique<PredictedVsyncTracer>(*mVsyncSchedule.dispatch);
- }
+void Scheduler::createVsyncSchedule(FeatureFlags features) {
+ mVsyncSchedule.emplace(features);
}
std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
const char* name, std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration, bool traceVsync) {
- return std::make_unique<scheduler::DispSyncSource>(*mVsyncSchedule.dispatch, workDuration,
+ return std::make_unique<scheduler::DispSyncSource>(getVsyncDispatch(), workDuration,
readyDuration, traceVsync, name);
}
@@ -210,7 +140,7 @@
return true;
}
- return mVsyncSchedule.tracker->isVSyncInPhase(expectedVsyncTimestamp, *frameRate);
+ return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp, *frameRate);
}
impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
@@ -245,7 +175,7 @@
};
}
-Scheduler::ConnectionHandle Scheduler::createConnection(
+ConnectionHandle Scheduler::createConnection(
const char* connectionName, frametimeline::TokenManager* tokenManager,
std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
@@ -259,7 +189,7 @@
return createConnection(std::move(eventThread));
}
-Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
+ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
@@ -346,24 +276,24 @@
void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
{
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
+ std::lock_guard<std::mutex> lock(mPolicyLock);
// Cache the last reported modes for primary display.
- mFeatures.cachedModeChangedParams = {handle, mode};
+ mPolicy.cachedModeChangedParams = {handle, mode};
// Invalidate content based refresh rate selection so it could be calculated
// again for the new refresh rate.
- mFeatures.contentRequirements.clear();
+ mPolicy.contentRequirements.clear();
}
onNonPrimaryDisplayModeChanged(handle, mode);
}
void Scheduler::dispatchCachedReportedMode() {
// Check optional fields first.
- if (!mFeatures.mode) {
+ if (!mPolicy.mode) {
ALOGW("No mode ID found, not dispatching cached mode.");
return;
}
- if (!mFeatures.cachedModeChangedParams.has_value()) {
+ if (!mPolicy.cachedModeChangedParams) {
ALOGW("No mode changed params found, not dispatching cached mode.");
return;
}
@@ -372,18 +302,18 @@
// mode change is in progress. In that case we shouldn't dispatch an event
// as it will be dispatched when the current mode changes.
if (std::scoped_lock lock(mRefreshRateConfigsLock);
- mRefreshRateConfigs->getCurrentRefreshRate().getMode() != mFeatures.mode) {
+ mRefreshRateConfigs->getCurrentRefreshRate().getMode() != mPolicy.mode) {
return;
}
// If there is no change from cached mode, there is no need to dispatch an event
- if (mFeatures.mode == mFeatures.cachedModeChangedParams->mode) {
+ if (mPolicy.mode == mPolicy.cachedModeChangedParams->mode) {
return;
}
- mFeatures.cachedModeChangedParams->mode = mFeatures.mode;
- onNonPrimaryDisplayModeChanged(mFeatures.cachedModeChangedParams->handle,
- mFeatures.cachedModeChangedParams->mode);
+ mPolicy.cachedModeChangedParams->mode = mPolicy.mode;
+ onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->handle,
+ mPolicy.cachedModeChangedParams->mode);
}
void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
@@ -424,12 +354,12 @@
}
DisplayStatInfo Scheduler::getDisplayStatInfo(nsecs_t now) {
- const auto vsyncTime = mVsyncSchedule.tracker->nextAnticipatedVSyncTimeFrom(now);
- const auto vsyncPeriod = mVsyncSchedule.tracker->currentPeriod();
+ const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(now);
+ const auto vsyncPeriod = mVsyncSchedule->getTracker().currentPeriod();
return DisplayStatInfo{.vsyncTime = vsyncTime, .vsyncPeriod = vsyncPeriod};
}
-Scheduler::ConnectionHandle Scheduler::enableVSyncInjection(bool enable) {
+ConnectionHandle Scheduler::enableVSyncInjection(bool enable) {
if (mInjectVSyncs == enable) {
return {};
}
@@ -470,7 +400,7 @@
void Scheduler::enableHardwareVsync() {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
- mVsyncSchedule.tracker->resetModel();
+ mVsyncSchedule->getTracker().resetModel();
mSchedulerCallback.setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
@@ -523,10 +453,10 @@
void Scheduler::setVsyncPeriod(nsecs_t period) {
std::lock_guard<std::mutex> lock(mHWVsyncLock);
- mVsyncSchedule.controller->startPeriodTransition(period);
+ mVsyncSchedule->getController().startPeriodTransition(period);
if (!mPrimaryHWVsyncEnabled) {
- mVsyncSchedule.tracker->resetModel();
+ mVsyncSchedule->getTracker().resetModel();
mSchedulerCallback.setVsyncEnabled(true);
mPrimaryHWVsyncEnabled = true;
}
@@ -539,8 +469,9 @@
{ // Scope for the lock
std::lock_guard<std::mutex> lock(mHWVsyncLock);
if (mPrimaryHWVsyncEnabled) {
- needsHwVsync = mVsyncSchedule.controller->addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
- periodFlushed);
+ needsHwVsync =
+ mVsyncSchedule->getController().addHwVsyncTimestamp(timestamp, hwcVsyncPeriod,
+ periodFlushed);
}
}
@@ -551,24 +482,23 @@
}
}
-void Scheduler::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
- if (mVsyncSchedule.controller->addPresentFence(fenceTime)) {
+void Scheduler::addPresentFence(std::shared_ptr<FenceTime> fence) {
+ if (mVsyncSchedule->getController().addPresentFence(std::move(fence))) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}
}
-void Scheduler::setIgnorePresentFences(bool ignore) {
- mVsyncSchedule.controller->setIgnorePresentFences(ignore);
-}
-
void Scheduler::registerLayer(Layer* layer) {
+ using WindowType = gui::WindowInfo::Type;
+
scheduler::LayerHistory::LayerVoteType voteType;
- if (!mOptions.useContentDetection || layer->getWindowType() == WindowInfo::Type::STATUS_BAR) {
+ if (!mFeatures.test(Feature::kContentDetection) ||
+ layer->getWindowType() == WindowType::STATUS_BAR) {
voteType = scheduler::LayerHistory::LayerVoteType::NoVote;
- } else if (layer->getWindowType() == WindowInfo::Type::WALLPAPER) {
+ } else if (layer->getWindowType() == WindowType::WALLPAPER) {
// Running Wallpaper at Min is considered as part of content detection.
voteType = scheduler::LayerHistory::LayerVoteType::Min;
} else {
@@ -615,13 +545,13 @@
bool frameRateChanged;
bool frameRateOverridesChanged;
{
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
- mFeatures.contentRequirements = summary;
+ std::lock_guard<std::mutex> lock(mPolicyLock);
+ mPolicy.contentRequirements = summary;
newMode = calculateRefreshRateModeId(&consideredSignals);
frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps());
- if (mFeatures.mode == newMode) {
+ if (mPolicy.mode == newMode) {
// We don't need to change the display mode, but we might need to send an event
// about a mode change, since it was suppressed due to a previous idleConsidered
if (!consideredSignals.idle) {
@@ -629,15 +559,16 @@
}
frameRateChanged = false;
} else {
- mFeatures.mode = newMode;
+ mPolicy.mode = newMode;
frameRateChanged = true;
}
}
if (frameRateChanged) {
- auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId());
+ const auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId());
+
mSchedulerCallback.changeRefreshRate(newRefreshRate,
- consideredSignals.idle ? ModeEvent::None
- : ModeEvent::Changed);
+ consideredSignals.idle ? DisplayModeEvent::None
+ : DisplayModeEvent::Changed);
}
if (frameRateOverridesChanged) {
mSchedulerCallback.triggerOnFrameRateOverridesChanged();
@@ -660,8 +591,8 @@
void Scheduler::setDisplayPowerState(bool normal) {
{
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
- mFeatures.isDisplayPowerStateNormal = normal;
+ std::lock_guard<std::mutex> lock(mPolicyLock);
+ mPolicy.isDisplayPowerStateNormal = normal;
}
if (mDisplayPowerTimer) {
@@ -703,7 +634,7 @@
}
void Scheduler::idleTimerCallback(TimerState state) {
- handleTimerStateChanged(&mFeatures.idleTimer, state);
+ handleTimerStateChanged(&mPolicy.idleTimer, state);
ATRACE_INT("ExpiredIdleTimer", static_cast<int>(state));
}
@@ -713,14 +644,14 @@
// Clear layer history to get fresh FPS detection.
// NOTE: Instead of checking all the layers, we should be checking the layer
// that is currently on top. b/142507166 will give us this capability.
- if (handleTimerStateChanged(&mFeatures.touch, touch)) {
+ if (handleTimerStateChanged(&mPolicy.touch, touch)) {
mLayerHistory.clear();
}
ATRACE_INT("TouchState", static_cast<int>(touch));
}
void Scheduler::displayPowerTimerCallback(TimerState state) {
- handleTimerStateChanged(&mFeatures.displayPowerTimer, state);
+ handleTimerStateChanged(&mPolicy.displayPowerTimer, state);
ATRACE_INT("ExpiredDisplayPowerTimer", static_cast<int>(state));
}
@@ -730,7 +661,7 @@
StringAppendF(&result, "+ Touch timer: %s\n",
mTouchTimer ? mTouchTimer->dump().c_str() : "off");
StringAppendF(&result, "+ Content detection: %s %s\n\n",
- toContentDetectionString(mOptions.useContentDetection),
+ mFeatures.test(Feature::kContentDetection) ? "on" : "off",
mLayerHistory.dump().c_str());
{
@@ -756,13 +687,8 @@
}
}
-void Scheduler::dumpVsync(std::string& s) const {
- using base::StringAppendF;
-
- StringAppendF(&s, "VSyncReactor:\n");
- mVsyncSchedule.controller->dump(s);
- StringAppendF(&s, "VSyncDispatch:\n");
- mVsyncSchedule.dispatch->dump(s);
+void Scheduler::dumpVsync(std::string& out) const {
+ mVsyncSchedule->dump(out);
}
bool Scheduler::updateFrameRateOverrides(
@@ -774,7 +700,7 @@
if (!consideredSignals.idle) {
const auto frameRateOverrides =
- refreshRateConfigs->getFrameRateOverrides(mFeatures.contentRequirements,
+ refreshRateConfigs->getFrameRateOverrides(mPolicy.contentRequirements,
displayRefreshRate, consideredSignals);
std::lock_guard lock(mFrameRateOverridesLock);
if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),
@@ -797,31 +723,30 @@
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
const auto refreshRateConfigs = holdRefreshRateConfigs();
{
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
+ std::lock_guard<std::mutex> lock(mPolicyLock);
if (*currentState == newState) {
return false;
}
*currentState = newState;
newMode = calculateRefreshRateModeId(&consideredSignals);
frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps());
- if (mFeatures.mode == newMode) {
+ if (mPolicy.mode == newMode) {
// We don't need to change the display mode, but we might need to send an event
// about a mode change, since it was suppressed due to a previous idleConsidered
if (!consideredSignals.idle) {
dispatchCachedReportedMode();
}
} else {
- mFeatures.mode = newMode;
+ mPolicy.mode = newMode;
refreshRateChanged = true;
}
}
if (refreshRateChanged) {
- const RefreshRate& newRefreshRate =
- refreshRateConfigs->getRefreshRateFromModeId(newMode->getId());
+ const auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newMode->getId());
mSchedulerCallback.changeRefreshRate(newRefreshRate,
- consideredSignals.idle ? ModeEvent::None
- : ModeEvent::Changed);
+ consideredSignals.idle ? DisplayModeEvent::None
+ : DisplayModeEvent::Changed);
}
if (frameRateOverridesChanged) {
mSchedulerCallback.triggerOnFrameRateOverridesChanged();
@@ -838,27 +763,26 @@
// If Display Power is not in normal operation we want to be in performance mode. When coming
// back to normal mode, a grace period is given with DisplayPowerTimer.
if (mDisplayPowerTimer &&
- (!mFeatures.isDisplayPowerStateNormal ||
- mFeatures.displayPowerTimer == TimerState::Reset)) {
+ (!mPolicy.isDisplayPowerStateNormal || mPolicy.displayPowerTimer == TimerState::Reset)) {
return refreshRateConfigs->getMaxRefreshRateByPolicy().getMode();
}
- const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
- const bool idle = mFeatures.idleTimer == TimerState::Expired;
+ const bool touchActive = mTouchTimer && mPolicy.touch == TouchState::Active;
+ const bool idle = mPolicy.idleTimer == TimerState::Expired;
return refreshRateConfigs
- ->getBestRefreshRate(mFeatures.contentRequirements,
- {.touch = touchActive, .idle = idle}, consideredSignals)
+ ->getBestRefreshRate(mPolicy.contentRequirements, {.touch = touchActive, .idle = idle},
+ consideredSignals)
.getMode();
}
DisplayModePtr Scheduler::getPreferredDisplayMode() {
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
+ std::lock_guard<std::mutex> lock(mPolicyLock);
// Make sure that the default mode ID is first updated, before returned.
- if (mFeatures.mode) {
- mFeatures.mode = calculateRefreshRateModeId();
+ if (mPolicy.mode) {
+ mPolicy.mode = calculateRefreshRateModeId();
}
- return mFeatures.mode;
+ return mPolicy.mode;
}
void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
@@ -915,8 +839,8 @@
std::chrono::steady_clock::time_point Scheduler::getPreviousVsyncFrom(
nsecs_t expectedPresentTime) const {
const auto presentTime = std::chrono::nanoseconds(expectedPresentTime);
- const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncSchedule.tracker->currentPeriod());
+ const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncSchedule->getTracker().currentPeriod());
return std::chrono::steady_clock::time_point(presentTime - vsyncPeriod);
}
-} // namespace android
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 2a6de54..e127ff7 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -31,40 +31,37 @@
#include <ui/GraphicTypes.h>
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
+#include <scheduler/Features.h>
+
#include "EventThread.h"
#include "LayerHistory.h"
#include "MessageQueue.h"
#include "OneShotTimer.h"
#include "RefreshRateConfigs.h"
#include "SchedulerUtils.h"
+#include "VsyncSchedule.h"
namespace android {
-using namespace std::chrono_literals;
-using scheduler::LayerHistory;
-
class FenceTime;
class InjectVSyncSource;
-class PredictedVsyncTracer;
-
-namespace scheduler {
-class VsyncController;
-class VSyncDispatch;
-class VSyncTracker;
-} // namespace scheduler
namespace frametimeline {
class TokenManager;
} // namespace frametimeline
+namespace scheduler {
+
struct ISchedulerCallback {
// Indicates frame activity, i.e. whether commit and/or composite is taking place.
enum class FrameHint { kNone, kActive };
+ using RefreshRate = RefreshRateConfigs::RefreshRate;
+ using DisplayModeEvent = scheduler::DisplayModeEvent;
+
virtual void scheduleComposite(FrameHint) = 0;
virtual void setVsyncEnabled(bool) = 0;
- virtual void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
- scheduler::RefreshRateConfigEvent) = 0;
+ virtual void changeRefreshRate(const RefreshRate&, DisplayModeEvent) = 0;
virtual void kernelTimerChanged(bool expired) = 0;
virtual void triggerOnFrameRateOverridesChanged() = 0;
@@ -76,18 +73,10 @@
using Impl = impl::MessageQueue;
public:
- using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
- using ModeEvent = scheduler::RefreshRateConfigEvent;
-
- struct Options {
- // Whether to use content detection at all.
- bool useContentDetection;
- };
-
- Scheduler(ICompositor&, ISchedulerCallback&, Options);
+ Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags);
~Scheduler();
- void createVsyncSchedule(bool supportKernelIdleTimer);
+ void createVsyncSchedule(FeatureFlags);
void startTimers();
void run();
@@ -107,7 +96,6 @@
return std::move(future);
}
- using ConnectionHandle = scheduler::ConnectionHandle;
ConnectionHandle createConnection(const char* connectionName, frametimeline::TokenManager*,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration,
@@ -119,7 +107,7 @@
sp<EventThreadConnection> getEventConnection(ConnectionHandle);
void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected);
- void onPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr) EXCLUDES(mFeatureStateLock);
+ void onPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr) EXCLUDES(mPolicyLock);
void onNonPrimaryDisplayModeChanged(ConnectionHandle, DisplayModePtr);
void onScreenAcquired(ConnectionHandle);
void onScreenReleased(ConnectionHandle);
@@ -152,8 +140,7 @@
// VsyncController detected that the vsync period changed, and false otherwise.
void addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwcVsyncPeriod,
bool* periodFlushed);
- void addPresentFence(const std::shared_ptr<FenceTime>&);
- void setIgnorePresentFences(bool ignore);
+ void addPresentFence(std::shared_ptr<FenceTime>);
// Layers are registered on creation, and unregistered when the weak reference expires.
void registerLayer(Layer*);
@@ -172,7 +159,7 @@
void setDisplayPowerState(bool normal);
- scheduler::VSyncDispatch& getVsyncDispatch() { return *mVsyncSchedule.dispatch; }
+ VSyncDispatch& getVsyncDispatch() { return mVsyncSchedule->getDispatch(); }
// Returns true if a given vsync timestamp is considered valid vsync
// for a given uid
@@ -211,7 +198,7 @@
std::optional<Fps> getFrameRateOverride(uid_t uid) const
EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock);
- void setRefreshRateConfigs(std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs)
+ void setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs> refreshRateConfigs)
EXCLUDES(mRefreshRateConfigsLock) {
// We need to stop the idle timer on the previous RefreshRateConfigs instance
// and cleanup the scheduler's state before we switch to the other RefreshRateConfigs.
@@ -220,8 +207,8 @@
if (mRefreshRateConfigs) mRefreshRateConfigs->stopIdleTimer();
}
{
- std::scoped_lock lock(mFeatureStateLock);
- mFeatures = {};
+ std::scoped_lock lock(mPolicyLock);
+ mPolicy = {};
}
{
std::scoped_lock lock(mRefreshRateConfigsLock);
@@ -251,18 +238,10 @@
using FrameHint = ISchedulerCallback::FrameHint;
- // In order to make sure that the features don't override themselves, we need a state machine
- // to keep track which feature requested the config change.
enum class ContentDetectionState { Off, On };
enum class TimerState { Reset, Expired };
enum class TouchState { Inactive, Active };
- struct VsyncSchedule {
- std::unique_ptr<scheduler::VsyncController> controller;
- std::unique_ptr<scheduler::VSyncTracker> tracker;
- std::unique_ptr<scheduler::VSyncDispatch> dispatch;
- };
-
// Create a connection on the given EventThread.
ConnectionHandle createConnection(std::unique_ptr<EventThread>);
sp<EventThreadConnection> createConnectionInternal(
@@ -284,19 +263,17 @@
// selection were initialized, prioritizes them, and calculates the DisplayModeId
// for the suggested refresh rate.
DisplayModePtr calculateRefreshRateModeId(
- scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr)
- REQUIRES(mFeatureStateLock);
+ RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr) REQUIRES(mPolicyLock);
- void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock) EXCLUDES(mRefreshRateConfigsLock);
- bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals,
- Fps displayRefreshRate) REQUIRES(mFeatureStateLock)
- EXCLUDES(mFrameRateOverridesLock);
+ void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mRefreshRateConfigsLock);
+ bool updateFrameRateOverrides(RefreshRateConfigs::GlobalSignals, Fps displayRefreshRate)
+ REQUIRES(mPolicyLock) EXCLUDES(mFrameRateOverridesLock);
impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const
EXCLUDES(mRefreshRateConfigsLock);
impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
- std::shared_ptr<scheduler::RefreshRateConfigs> holdRefreshRateConfigs() const
+ std::shared_ptr<RefreshRateConfigs> holdRefreshRateConfigs() const
EXCLUDES(mRefreshRateConfigsLock) {
std::scoped_lock lock(mRefreshRateConfigsLock);
return mRefreshRateConfigs;
@@ -322,66 +299,63 @@
std::atomic<nsecs_t> mLastResyncTime = 0;
- const Options mOptions;
- VsyncSchedule mVsyncSchedule;
+ const FeatureFlags mFeatures;
+ std::optional<VsyncSchedule> mVsyncSchedule;
// Used to choose refresh rate if content detection is enabled.
LayerHistory mLayerHistory;
// Timer used to monitor touch events.
- std::optional<scheduler::OneShotTimer> mTouchTimer;
+ std::optional<OneShotTimer> mTouchTimer;
// Timer used to monitor display power mode.
- std::optional<scheduler::OneShotTimer> mDisplayPowerTimer;
+ std::optional<OneShotTimer> mDisplayPowerTimer;
ISchedulerCallback& mSchedulerCallback;
- // In order to make sure that the features don't override themselves, we need a state machine
- // to keep track which feature requested the config change.
- mutable std::mutex mFeatureStateLock;
+ mutable std::mutex mPolicyLock;
struct {
+ // Policy for choosing the display mode.
+ LayerHistory::Summary contentRequirements;
TimerState idleTimer = TimerState::Reset;
TouchState touch = TouchState::Inactive;
TimerState displayPowerTimer = TimerState::Expired;
-
- DisplayModePtr mode;
- LayerHistory::Summary contentRequirements;
-
bool isDisplayPowerStateNormal = true;
- // Used to cache the last parameters of onPrimaryDisplayModeChanged
+ // Chosen display mode.
+ DisplayModePtr mode;
+
struct ModeChangedParams {
ConnectionHandle handle;
DisplayModePtr mode;
};
+ // Parameters for latest dispatch of mode change event.
std::optional<ModeChangedParams> cachedModeChangedParams;
- } mFeatures GUARDED_BY(mFeatureStateLock);
+ } mPolicy GUARDED_BY(mPolicyLock);
mutable std::mutex mRefreshRateConfigsLock;
- std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs
- GUARDED_BY(mRefreshRateConfigsLock);
+ std::shared_ptr<RefreshRateConfigs> mRefreshRateConfigs GUARDED_BY(mRefreshRateConfigsLock);
std::mutex mVsyncTimelineLock;
std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
GUARDED_BY(mVsyncTimelineLock);
static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
- std::unique_ptr<PredictedVsyncTracer> mPredictedVsyncTracer;
-
// The frame rate override lists need their own mutex as they are being read
// by SurfaceFlinger, Scheduler and EventThread (as a callback) to prevent deadlocks
mutable std::mutex mFrameRateOverridesLock;
// mappings between a UID and a preferred refresh rate that this app would
// run at.
- scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent
+ RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent
GUARDED_BY(mFrameRateOverridesLock);
- scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor
+ RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor
GUARDED_BY(mFrameRateOverridesLock);
// Keeps track of whether the screen is acquired for debug
std::atomic<bool> mScreenAcquired = false;
};
+} // namespace scheduler
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index ee973f7..1c9de1c 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -47,7 +47,7 @@
VSyncReactor::~VSyncReactor() = default;
-bool VSyncReactor::addPresentFence(const std::shared_ptr<android::FenceTime>& fence) {
+bool VSyncReactor::addPresentFence(std::shared_ptr<FenceTime> fence) {
if (!fence) {
return false;
}
@@ -80,7 +80,7 @@
if (mPendingLimit == mUnfiredFences.size()) {
mUnfiredFences.erase(mUnfiredFences.begin());
}
- mUnfiredFences.push_back(fence);
+ mUnfiredFences.push_back(std::move(fence));
} else {
timestampAccepted &= mTracker.addVsyncTimestamp(signalTime);
}
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.h b/services/surfaceflinger/Scheduler/VSyncReactor.h
index 449d4c3..a9d536b 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.h
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.h
@@ -37,7 +37,7 @@
bool supportKernelIdleTimer);
~VSyncReactor();
- bool addPresentFence(const std::shared_ptr<android::FenceTime>& fence) final;
+ bool addPresentFence(std::shared_ptr<FenceTime>) final;
void setIgnorePresentFences(bool ignore) final;
void startPeriodTransition(nsecs_t period) final;
diff --git a/services/surfaceflinger/Scheduler/VsyncController.h b/services/surfaceflinger/Scheduler/VsyncController.h
index 0f0df22..59f6537 100644
--- a/services/surfaceflinger/Scheduler/VsyncController.h
+++ b/services/surfaceflinger/Scheduler/VsyncController.h
@@ -17,19 +17,15 @@
#pragma once
#include <cstddef>
+#include <memory>
+#include <ui/FenceTime.h>
#include <utils/Mutex.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
-#include <ui/FenceTime.h>
-
-#include <memory>
-
namespace android::scheduler {
-class FenceTime;
-
class VsyncController {
public:
virtual ~VsyncController();
@@ -43,7 +39,7 @@
* an accurate prediction,
* False otherwise
*/
- virtual bool addPresentFence(const std::shared_ptr<android::FenceTime>&) = 0;
+ virtual bool addPresentFence(std::shared_ptr<FenceTime>) = 0;
/*
* Adds a hw sync timestamp to the model. The controller will use the timestamp
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
new file mode 100644
index 0000000..77d1223
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#include <scheduler/Fps.h>
+
+#include "VsyncSchedule.h"
+
+#include "Timer.h"
+#include "VSyncDispatchTimerQueue.h"
+#include "VSyncPredictor.h"
+#include "VSyncReactor.h"
+
+#include "../TracedOrdinal.h"
+
+namespace android::scheduler {
+
+class VsyncSchedule::PredictedVsyncTracer {
+ // Invoked from the thread of the VsyncDispatch owned by this VsyncSchedule.
+ constexpr auto makeVsyncCallback() {
+ return [this](nsecs_t, nsecs_t, nsecs_t) {
+ mParity = !mParity;
+ schedule();
+ };
+ }
+
+public:
+ explicit PredictedVsyncTracer(VsyncDispatch& dispatch)
+ : mRegistration(dispatch, makeVsyncCallback(), __func__) {
+ schedule();
+ }
+
+private:
+ void schedule() { mRegistration.schedule({0, 0, 0}); }
+
+ TracedOrdinal<bool> mParity = {"VSYNC-predicted", 0};
+ VSyncCallbackRegistration mRegistration;
+};
+
+VsyncSchedule::VsyncSchedule(FeatureFlags features)
+ : mTracker(createTracker()),
+ mDispatch(createDispatch(*mTracker)),
+ mController(createController(*mTracker, features)) {
+ if (features.test(Feature::kTracePredictedVsync)) {
+ mTracer = std::make_unique<PredictedVsyncTracer>(*mDispatch);
+ }
+}
+
+VsyncSchedule::VsyncSchedule(TrackerPtr tracker, DispatchPtr dispatch, ControllerPtr controller)
+ : mTracker(std::move(tracker)),
+ mDispatch(std::move(dispatch)),
+ mController(std::move(controller)) {}
+
+VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default;
+VsyncSchedule::~VsyncSchedule() = default;
+
+void VsyncSchedule::dump(std::string& out) const {
+ out.append("VsyncController:\n");
+ mController->dump(out);
+
+ out.append("VsyncDispatch:\n");
+ mDispatch->dump(out);
+}
+
+VsyncSchedule::TrackerPtr VsyncSchedule::createTracker() {
+ // TODO(b/144707443): Tune constants.
+ constexpr nsecs_t kInitialPeriod = (60_Hz).getPeriodNsecs();
+ constexpr size_t kHistorySize = 20;
+ constexpr size_t kMinSamplesForPrediction = 6;
+ constexpr uint32_t kDiscardOutlierPercent = 20;
+
+ return std::make_unique<VSyncPredictor>(kInitialPeriod, kHistorySize, kMinSamplesForPrediction,
+ kDiscardOutlierPercent);
+}
+
+VsyncSchedule::DispatchPtr VsyncSchedule::createDispatch(VsyncTracker& tracker) {
+ using namespace std::chrono_literals;
+
+ // TODO(b/144707443): Tune constants.
+ constexpr std::chrono::nanoseconds kGroupDispatchWithin = 500us;
+ constexpr std::chrono::nanoseconds kSnapToSameVsyncWithin = 3ms;
+
+ return std::make_unique<VSyncDispatchTimerQueue>(std::make_unique<Timer>(), tracker,
+ kGroupDispatchWithin.count(),
+ kSnapToSameVsyncWithin.count());
+}
+
+VsyncSchedule::ControllerPtr VsyncSchedule::createController(VsyncTracker& tracker,
+ FeatureFlags features) {
+ // TODO(b/144707443): Tune constants.
+ constexpr size_t kMaxPendingFences = 20;
+ const bool hasKernelIdleTimer = features.test(Feature::kKernelIdleTimer);
+
+ auto reactor = std::make_unique<VSyncReactor>(std::make_unique<SystemClock>(), tracker,
+ kMaxPendingFences, hasKernelIdleTimer);
+
+ reactor->setIgnorePresentFences(!features.test(Feature::kPresentFences));
+ return reactor;
+}
+
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
new file mode 100644
index 0000000..0d9b114
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2021 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
+
+#include <memory>
+#include <string>
+
+#include <scheduler/Features.h>
+
+namespace android::scheduler {
+
+// TODO(b/185535769): Rename classes, and remove aliases.
+class VSyncDispatch;
+class VSyncTracker;
+
+class VsyncController;
+using VsyncDispatch = VSyncDispatch;
+using VsyncTracker = VSyncTracker;
+
+// Schedule that synchronizes to hardware VSYNC of a physical display.
+class VsyncSchedule {
+public:
+ explicit VsyncSchedule(FeatureFlags);
+ VsyncSchedule(VsyncSchedule&&);
+ ~VsyncSchedule();
+
+ // TODO(b/185535769): Hide behind API.
+ const VsyncTracker& getTracker() const { return *mTracker; }
+ VsyncTracker& getTracker() { return *mTracker; }
+ VsyncController& getController() { return *mController; }
+
+ // TODO(b/185535769): Remove once VsyncSchedule owns all registrations.
+ VsyncDispatch& getDispatch() { return *mDispatch; }
+
+ void dump(std::string&) const;
+
+private:
+ friend class TestableScheduler;
+
+ using TrackerPtr = std::unique_ptr<VsyncTracker>;
+ using DispatchPtr = std::unique_ptr<VsyncDispatch>;
+ using ControllerPtr = std::unique_ptr<VsyncController>;
+
+ // For tests.
+ VsyncSchedule(TrackerPtr, DispatchPtr, ControllerPtr);
+
+ static TrackerPtr createTracker();
+ static DispatchPtr createDispatch(VsyncTracker&);
+ static ControllerPtr createController(VsyncTracker&, FeatureFlags);
+
+ class PredictedVsyncTracer;
+ using TracerPtr = std::unique_ptr<PredictedVsyncTracer>;
+
+ // Effectively const except in move constructor.
+ TrackerPtr mTracker;
+ DispatchPtr mDispatch;
+ ControllerPtr mController;
+ TracerPtr mTracer;
+};
+
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Features.h b/services/surfaceflinger/Scheduler/include/scheduler/Features.h
new file mode 100644
index 0000000..0e96678
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Features.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 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
+
+#include <ftl/Flags.h>
+
+#include <cstdint>
+
+namespace android::scheduler {
+
+enum class Feature : std::uint8_t {
+ kPresentFences = 0b1,
+ kKernelIdleTimer = 0b10,
+ kContentDetection = 0b100,
+ kTracePredictedVsync = 0b1000,
+};
+
+using FeatureFlags = Flags<Feature>;
+
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e497d95..3860901 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1200,7 +1200,7 @@
mRefreshRateStats->setRefreshRate(refreshRate);
updatePhaseConfiguration(refreshRate);
- if (upcomingModeInfo.event != Scheduler::ModeEvent::None) {
+ if (upcomingModeInfo.event != DisplayModeEvent::None) {
mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, upcomingModeInfo.mode);
}
}
@@ -3099,7 +3099,7 @@
mCompositionEngine->updateCursorAsync(refreshArgs);
}
-void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, Scheduler::ModeEvent event) {
+void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, DisplayModeEvent event) {
// If this is called from the main thread mStateLock must be locked before
// Currently the only way to call this function from the main thread is from
// Scheduler::chooseRefreshRateForContent
@@ -3147,17 +3147,32 @@
mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
- const Scheduler::Options options = {
- .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)};
+ using Feature = scheduler::Feature;
+ scheduler::FeatureFlags features;
- mScheduler = std::make_unique<Scheduler>(static_cast<ICompositor&>(*this),
- static_cast<ISchedulerCallback&>(*this), options);
- {
- auto configs = display->holdRefreshRateConfigs();
- mScheduler->createVsyncSchedule(configs->supportsKernelIdleTimer());
- mScheduler->setRefreshRateConfigs(std::move(configs));
+ if (sysprop::use_content_detection_for_refresh_rate(false)) {
+ features |= Feature::kContentDetection;
+ }
+ if (base::GetBoolProperty("debug.sf.show_predicted_vsync"s, false)) {
+ features |= Feature::kTracePredictedVsync;
+ }
+ if (!base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false) &&
+ !getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
+ features |= Feature::kPresentFences;
}
+ mScheduler = std::make_unique<scheduler::Scheduler>(static_cast<ICompositor&>(*this),
+ static_cast<ISchedulerCallback&>(*this),
+ features);
+ {
+ auto configs = display->holdRefreshRateConfigs();
+ if (configs->supportsKernelIdleTimer()) {
+ features |= Feature::kKernelIdleTimer;
+ }
+
+ mScheduler->createVsyncSchedule(features);
+ mScheduler->setRefreshRateConfigs(std::move(configs));
+ }
setVsyncEnabled(false);
mScheduler->startTimers();
@@ -3190,11 +3205,6 @@
// classes from EventThread, and there should be no run-time binder cost
// anyway since there are no connected apps at this point.
mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, display->getActiveMode());
- static auto ignorePresentFences =
- base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
- mScheduler->setIgnorePresentFences(
- ignorePresentFences ||
- getHwComposer().hasCapability(hal::Capability::PRESENT_FENCE_IS_NOT_RELIABLE));
}
void SurfaceFlinger::updatePhaseConfiguration(const Fps& refreshRate) {
@@ -3818,10 +3828,11 @@
clientStateFlags |= setClientStateLocked(frameTimelineInfo, state, desiredPresentTime,
isAutoTimestamp, postTime, permissions);
if ((flags & eAnimation) && state.state.surface) {
- if (const auto layer = fromHandle(state.state.surface).promote(); layer) {
+ if (const auto layer = fromHandle(state.state.surface).promote()) {
+ using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
mScheduler->recordLayerHistory(layer.get(),
isAutoTimestamp ? 0 : desiredPresentTime,
- LayerHistory::LayerUpdateType::AnimationTX);
+ LayerUpdateType::AnimationTX);
}
}
}
@@ -6478,7 +6489,7 @@
if (display->refreshRateConfigs().isModeAllowed(preferredDisplayMode->getId())) {
ALOGV("switching to Scheduler preferred display mode %d",
preferredDisplayMode->getId().value());
- setDesiredActiveMode({preferredDisplayMode, Scheduler::ModeEvent::Changed});
+ setDesiredActiveMode({preferredDisplayMode, DisplayModeEvent::Changed});
} else {
LOG_ALWAYS_FATAL("Desired display mode not allowed: %d",
preferredDisplayMode->getId().value());
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 05c058b..eb934b6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -165,7 +165,7 @@
private IBinder::DeathRecipient,
private HWC2::ComposerCallback,
private ICompositor,
- private ISchedulerCallback {
+ private scheduler::ISchedulerCallback {
public:
struct SkipInitializationTag {};
@@ -356,7 +356,6 @@
friend class TransactionApplicationTest;
friend class TunnelModeEnabledReporterTest;
- using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
using VsyncModulator = scheduler::VsyncModulator;
using TransactionSchedule = scheduler::TransactionSchedule;
using TraverseLayersFunction = std::function<void(const LayerVector::Visitor&)>;
@@ -643,7 +642,7 @@
// Toggles hardware VSYNC by calling into HWC.
void setVsyncEnabled(bool) override;
// Initiates a refresh rate change to be applied on commit.
- void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override;
+ void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override;
// Called when kernel idle timer has expired. Used to update the refresh rate overlay.
void kernelTimerChanged(bool expired) override;
// Called when the frame rate override list changed to trigger an event.
@@ -1261,7 +1260,7 @@
/*
* Scheduler
*/
- std::unique_ptr<Scheduler> mScheduler;
+ std::unique_ptr<scheduler::Scheduler> mScheduler;
scheduler::ConnectionHandle mAppConnectionHandle;
scheduler::ConnectionHandle mSfConnectionHandle;
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index e509cc9..6153e8e 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -42,16 +42,12 @@
class IGraphicBufferConsumer;
class IGraphicBufferProducer;
class Layer;
-class MessageQueue;
-class Scheduler;
class StartPropertySetThread;
class SurfaceFlinger;
class SurfaceInterceptor;
class TimeStats;
struct DisplayDeviceCreationArgs;
-struct ICompositor;
-struct ISchedulerCallback;
struct LayerCreationArgs;
namespace compositionengine {
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 8d2c078..eb5f31e 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -138,7 +138,7 @@
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
- constexpr ISchedulerCallback* kCallback = nullptr;
+ constexpr scheduler::ISchedulerCallback* kCallback = nullptr;
constexpr bool kHasMultipleConfigs = true;
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
std::move(eventThread), std::move(sfEventThread), kCallback,
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
index d4cfbbb..5a0033e 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
@@ -29,7 +29,7 @@
class InitiateModeChangeTest : public DisplayTransactionTest {
public:
- using Event = scheduler::RefreshRateConfigEvent;
+ using Event = scheduler::DisplayModeEvent;
void SetUp() override {
injectFakeBufferQueueFactory();
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index de5e9df..0a3437a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -121,7 +121,7 @@
mock::VsyncController* mVsyncController = new mock::VsyncController;
mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker;
- mock::SchedulerCallback mSchedulerCallback;
+ scheduler::mock::SchedulerCallback mSchedulerCallback;
mock::EventThread* mEventThread = new mock::EventThread;
mock::EventThread* mSFEventThread = new mock::EventThread;
diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
index cd2fc74..bb1f432 100644
--- a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
@@ -17,6 +17,8 @@
#undef LOG_TAG
#define LOG_TAG "FpsReporterTest"
+#include <chrono>
+
#include <android/gui/BnFpsListener.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -36,6 +38,8 @@
namespace android {
+using namespace std::chrono_literals;
+
using testing::_;
using testing::DoAll;
using testing::Mock;
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 4993a2d..00687ad 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -38,9 +38,9 @@
using testing::Return;
using testing::ReturnRef;
-namespace android {
+namespace android::scheduler {
-namespace scheduler {
+using MockLayer = android::mock::MockLayer;
class LayerHistoryTest : public testing::Test {
protected:
@@ -93,12 +93,12 @@
}
}
- auto createLayer() { return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger())); }
+ auto createLayer() { return sp<MockLayer>::make(mFlinger.flinger()); }
auto createLayer(std::string name) {
- return sp<mock::MockLayer>(new mock::MockLayer(mFlinger.flinger(), std::move(name)));
+ return sp<MockLayer>::make(mFlinger.flinger(), std::move(name));
}
- void recordFramesAndExpect(const sp<mock::MockLayer>& layer, nsecs_t& time, Fps frameRate,
+ void recordFramesAndExpect(const sp<MockLayer>& layer, nsecs_t& time, Fps frameRate,
Fps desiredRefreshRate, int numFrames) {
LayerHistory::Summary summary;
for (int i = 0; i < numFrames; i++) {
@@ -768,8 +768,7 @@
::testing::Values(1s, 2s, 3s, 4s, 5s));
} // namespace
-} // namespace scheduler
-} // namespace android
+} // namespace android::scheduler
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wextra"
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index e558f3b..a6fd378 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -28,12 +28,16 @@
#include "mock/MockLayer.h"
#include "mock/MockSchedulerCallback.h"
+namespace android::scheduler {
+
using testing::_;
using testing::Return;
-namespace android {
namespace {
+using MockEventThread = android::mock::EventThread;
+using MockLayer = android::mock::MockLayer;
+
constexpr PhysicalDisplayId PHYSICAL_DISPLAY_ID = PhysicalDisplayId::fromPort(255u);
class SchedulerTest : public testing::Test {
@@ -64,21 +68,21 @@
.setGroup(0)
.build();
- std::shared_ptr<scheduler::RefreshRateConfigs> mConfigs =
- std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60}, mode60->getId());
+ std::shared_ptr<RefreshRateConfigs> mConfigs =
+ std::make_shared<RefreshRateConfigs>(DisplayModes{mode60}, mode60->getId());
mock::SchedulerCallback mSchedulerCallback;
TestableScheduler* mScheduler = new TestableScheduler{mConfigs, mSchedulerCallback};
- Scheduler::ConnectionHandle mConnectionHandle;
- mock::EventThread* mEventThread;
+ ConnectionHandle mConnectionHandle;
+ MockEventThread* mEventThread;
sp<MockEventThreadConnection> mEventThreadConnection;
TestableSurfaceFlinger mFlinger;
};
SchedulerTest::SchedulerTest() {
- auto eventThread = std::make_unique<mock::EventThread>();
+ auto eventThread = std::make_unique<MockEventThread>();
mEventThread = eventThread.get();
EXPECT_CALL(*mEventThread, registerDisplayEventConnection(_)).WillOnce(Return(0));
@@ -98,7 +102,7 @@
} // namespace
TEST_F(SchedulerTest, invalidConnectionHandle) {
- Scheduler::ConnectionHandle handle;
+ ConnectionHandle handle;
const sp<IDisplayEventConnection> connection = mScheduler->createDisplayEventConnection(handle);
@@ -155,7 +159,7 @@
TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSupported) {
// The layer is registered at creation time and deregistered at destruction time.
- sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger());
+ sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
// recordLayerHistory should be a noop
ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
@@ -174,24 +178,22 @@
TEST_F(SchedulerTest, updateDisplayModes) {
ASSERT_EQ(0u, mScheduler->layerHistorySize());
- sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger());
+ sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
ASSERT_EQ(1u, mScheduler->layerHistorySize());
mScheduler->setRefreshRateConfigs(
- std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60, mode120},
- mode60->getId()));
+ std::make_shared<RefreshRateConfigs>(DisplayModes{mode60, mode120}, mode60->getId()));
ASSERT_EQ(0u, mScheduler->getNumActiveLayers());
mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer);
ASSERT_EQ(1u, mScheduler->getNumActiveLayers());
}
-TEST_F(SchedulerTest, testDispatchCachedReportedMode) {
- // If the optional fields are cleared, the function should return before
- // onModeChange is called.
- mScheduler->clearOptionalFieldsInFeatures();
- EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
+TEST_F(SchedulerTest, dispatchCachedReportedMode) {
+ mScheduler->clearCachedReportedMode();
+
EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
+ EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
}
TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) {
@@ -203,7 +205,7 @@
// If the handle is incorrect, the function should return before
// onModeChange is called.
- Scheduler::ConnectionHandle invalidHandle = {.id = 123};
+ ConnectionHandle invalidHandle = {.id = 123};
EXPECT_NO_FATAL_FAILURE(mScheduler->onNonPrimaryDisplayModeChanged(invalidHandle, mode));
EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
}
@@ -224,10 +226,9 @@
TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
mScheduler->setRefreshRateConfigs(
- std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60, mode120},
- mode60->getId()));
+ std::make_shared<RefreshRateConfigs>(DisplayModes{mode60, mode120}, mode60->getId()));
- sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger());
+ sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger());
mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer);
@@ -241,4 +242,4 @@
mScheduler->chooseRefreshRateForContent();
}
-} // namespace android
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index eed62a7..fe5f9e0 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -48,6 +48,8 @@
using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
+using scheduler::LayerHistory;
+
using FrameRate = Layer::FrameRate;
using FrameRateCompatibility = Layer::FrameRateCompatibility;
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp
index 69e0501..ec7e8a7 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_NotifyPowerBoostTest.cpp
@@ -17,6 +17,9 @@
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
+#include <chrono>
+#include <thread>
+
#include "DisplayTransactionTestHelpers.h"
#include <android/hardware/power/Boost.h>
@@ -27,6 +30,8 @@
using android::hardware::power::Boost;
TEST_F(DisplayTransactionTest, notifyPowerBoostNotifiesTouchEvent) {
+ using namespace std::chrono_literals;
+
mFlinger.scheduler()->replaceTouchTimer(100);
std::this_thread::sleep_for(10ms); // wait for callback to be triggered
EXPECT_TRUE(mFlinger.scheduler()->isTouchActive()); // Starting timer activates touch
@@ -47,4 +52,4 @@
}
} // namespace
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 9d1fc98..dabd2d2 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -28,22 +28,20 @@
#include "mock/MockVSyncTracker.h"
#include "mock/MockVsyncController.h"
-namespace android {
+namespace android::scheduler {
class TestableScheduler : public Scheduler, private ICompositor {
public:
- TestableScheduler(std::shared_ptr<scheduler::RefreshRateConfigs> configs,
- ISchedulerCallback& callback)
+ TestableScheduler(std::shared_ptr<RefreshRateConfigs> configs, ISchedulerCallback& callback)
: TestableScheduler(std::make_unique<mock::VsyncController>(),
std::make_unique<mock::VSyncTracker>(), std::move(configs),
callback) {}
- TestableScheduler(std::unique_ptr<scheduler::VsyncController> vsyncController,
- std::unique_ptr<scheduler::VSyncTracker> vsyncTracker,
- std::shared_ptr<scheduler::RefreshRateConfigs> configs,
- ISchedulerCallback& callback)
- : Scheduler(*this, callback, {.useContentDetection = true}) {
- mVsyncSchedule = {std::move(vsyncController), std::move(vsyncTracker), nullptr};
+ TestableScheduler(std::unique_ptr<VsyncController> controller,
+ std::unique_ptr<VSyncTracker> tracker,
+ std::shared_ptr<RefreshRateConfigs> configs, ISchedulerCallback& callback)
+ : Scheduler(*this, callback, Feature::kContentDetection) {
+ mVsyncSchedule.emplace(VsyncSchedule(std::move(tracker), nullptr, std::move(controller)));
setRefreshRateConfigs(std::move(configs));
ON_CALL(*this, postMessage).WillByDefault([](sp<MessageHandler>&& handler) {
@@ -86,33 +84,24 @@
}
bool isTouchActive() {
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
- return mFeatures.touch == Scheduler::TouchState::Active;
+ std::lock_guard<std::mutex> lock(mPolicyLock);
+ return mPolicy.touch == Scheduler::TouchState::Active;
}
void dispatchCachedReportedMode() {
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
+ std::lock_guard<std::mutex> lock(mPolicyLock);
return Scheduler::dispatchCachedReportedMode();
}
- void clearOptionalFieldsInFeatures() {
- std::lock_guard<std::mutex> lock(mFeatureStateLock);
- mFeatures.cachedModeChangedParams.reset();
+ void clearCachedReportedMode() {
+ std::lock_guard<std::mutex> lock(mPolicyLock);
+ mPolicy.cachedModeChangedParams.reset();
}
void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, DisplayModePtr mode) {
return Scheduler::onNonPrimaryDisplayModeChanged(handle, mode);
}
- ~TestableScheduler() {
- // All these pointer and container clears help ensure that GMock does
- // not report a leaked object, since the Scheduler instance may
- // still be referenced by something despite our best efforts to destroy
- // it after each test is done.
- mVsyncSchedule.controller.reset();
- mConnections.clear();
- }
-
private:
// ICompositor overrides:
bool commit(nsecs_t, int64_t, nsecs_t) override { return false; }
@@ -120,4 +109,4 @@
void sample() override {}
};
-} // namespace android
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 4c5789e..4473e01 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -169,12 +169,12 @@
} // namespace surfaceflinger::test
-class TestableSurfaceFlinger final : private ISchedulerCallback {
+class TestableSurfaceFlinger final : private scheduler::ISchedulerCallback {
public:
using HotplugEvent = SurfaceFlinger::HotplugEvent;
SurfaceFlinger* flinger() { return mFlinger.get(); }
- TestableScheduler* scheduler() { return mScheduler; }
+ scheduler::TestableScheduler* scheduler() { return mScheduler; }
// Extend this as needed for accessing SurfaceFlinger private (and public)
// functions.
@@ -197,7 +197,8 @@
std::unique_ptr<scheduler::VSyncTracker> vsyncTracker,
std::unique_ptr<EventThread> appEventThread,
std::unique_ptr<EventThread> sfEventThread,
- ISchedulerCallback* callback = nullptr, bool hasMultipleModes = false) {
+ scheduler::ISchedulerCallback* callback = nullptr,
+ bool hasMultipleModes = false) {
DisplayModes modes{DisplayMode::Builder(0)
.setId(DisplayModeId(0))
.setPhysicalDisplayId(PhysicalDisplayId::fromPort(0))
@@ -224,17 +225,18 @@
std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
/*powerMode=*/hal::PowerMode::OFF);
- mScheduler = new TestableScheduler(std::move(vsyncController), std::move(vsyncTracker),
- mRefreshRateConfigs, *(callback ?: this));
+ mScheduler = new scheduler::TestableScheduler(std::move(vsyncController),
+ std::move(vsyncTracker), mRefreshRateConfigs,
+ *(callback ?: this));
mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
resetScheduler(mScheduler);
}
- void resetScheduler(Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); }
+ void resetScheduler(scheduler::Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); }
- TestableScheduler& mutableScheduler() const { return *mScheduler; }
+ scheduler::TestableScheduler& mutableScheduler() const { return *mScheduler; }
using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction;
void setCreateBufferQueueFunction(CreateBufferQueueFunction f) {
@@ -759,13 +761,13 @@
private:
void scheduleComposite(FrameHint) override {}
void setVsyncEnabled(bool) override {}
- void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override {}
+ void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {}
void kernelTimerChanged(bool) override {}
void triggerOnFrameRateOverridesChanged() {}
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
- TestableScheduler* mScheduler = nullptr;
+ scheduler::TestableScheduler* mScheduler = nullptr;
std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
};
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index ec19100..16d4b59 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -26,7 +26,7 @@
#include <log/log.h>
#include <ui/MockFence.h>
#include <utils/String8.h>
-#include "TestableScheduler.h"
+
#include "TestableSurfaceFlinger.h"
#include "mock/MockEventThread.h"
#include "mock/MockVsyncController.h"
@@ -85,11 +85,8 @@
std::move(eventThread), std::move(sfEventThread));
}
- TestableScheduler* mScheduler;
TestableSurfaceFlinger mFlinger;
- std::unique_ptr<mock::EventThread> mEventThread = std::make_unique<mock::EventThread>();
-
mock::VsyncController* mVsyncController = new mock::VsyncController();
mock::VSyncTracker* mVSyncTracker = new mock::VSyncTracker();
mock::MockFence* mFenceUnsignaled = new mock::MockFence();
diff --git a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
index e241dc9..849e308 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockSchedulerCallback.h
@@ -20,25 +20,22 @@
#include "Scheduler/Scheduler.h"
-namespace android::mock {
+namespace android::scheduler::mock {
struct SchedulerCallback final : ISchedulerCallback {
MOCK_METHOD(void, scheduleComposite, (FrameHint), (override));
- MOCK_METHOD1(setVsyncEnabled, void(bool));
- MOCK_METHOD2(changeRefreshRate,
- void(const scheduler::RefreshRateConfigs::RefreshRate&,
- scheduler::RefreshRateConfigEvent));
- MOCK_METHOD1(kernelTimerChanged, void(bool));
- MOCK_METHOD0(triggerOnFrameRateOverridesChanged, void());
+ MOCK_METHOD(void, setVsyncEnabled, (bool), (override));
+ MOCK_METHOD(void, changeRefreshRate, (const RefreshRate&, DisplayModeEvent), (override));
+ MOCK_METHOD(void, kernelTimerChanged, (bool), (override));
+ MOCK_METHOD(void, triggerOnFrameRateOverridesChanged, (), (override));
};
struct NoOpSchedulerCallback final : ISchedulerCallback {
void scheduleComposite(FrameHint) override {}
void setVsyncEnabled(bool) override {}
- void changeRefreshRate(const scheduler::RefreshRateConfigs::RefreshRate&,
- scheduler::RefreshRateConfigEvent) override {}
+ void changeRefreshRate(const RefreshRate&, DisplayModeEvent) override {}
void kernelTimerChanged(bool) override {}
void triggerOnFrameRateOverridesChanged() {}
};
-} // namespace android::mock
+} // namespace android::scheduler::mock
diff --git a/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h b/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h
index 94d9966..314f681 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockVsyncController.h
@@ -27,7 +27,7 @@
VsyncController();
~VsyncController() override;
- MOCK_METHOD1(addPresentFence, bool(const std::shared_ptr<FenceTime>&));
+ MOCK_METHOD(bool, addPresentFence, (std::shared_ptr<FenceTime>), (override));
MOCK_METHOD3(addHwVsyncTimestamp, bool(nsecs_t, std::optional<nsecs_t>, bool*));
MOCK_METHOD1(startPeriodTransition, void(nsecs_t));
MOCK_METHOD1(setIgnorePresentFences, void(bool));