SF: move RefreshRateConfigs to DisplayDevice
Move RefreshRateConfigs to DisplayDevice to be able to maintain
a per-display refresh rate switching policy.
Test: SF unit tests
Test: refresh rate switching is working on device with
more than one display
Bug: 187539899
Change-Id: Ica6a955e8ad0e563a0740f6579b61fc592eb982c
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 3cb7e9c..6a78b53 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -421,7 +421,7 @@
mFrameTracker.setFrameReadyTime(desiredPresentTime);
}
- const Fps refreshRate = mFlinger->mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+ const Fps refreshRate = display->refreshRateConfigs().getCurrentRefreshRate().getFps();
const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
if (presentFence->isValid()) {
mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 517f848..5c33428 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -67,7 +67,8 @@
mCompositionDisplay{args.compositionDisplay},
mPhysicalOrientation(args.physicalOrientation),
mSupportedModes(std::move(args.supportedModes)),
- mIsPrimary(args.isPrimary) {
+ mIsPrimary(args.isPrimary),
+ mRefreshRateConfigs(std::move(args.refreshRateConfigs)) {
mCompositionDisplay->editState().isSecure = args.isSecure;
mCompositionDisplay->createRenderSurface(
compositionengine::RenderSurfaceCreationArgsBuilder()
@@ -155,6 +156,9 @@
const auto mode = getMode(id);
LOG_FATAL_IF(!mode, "Cannot set active mode which is not supported.");
mActiveMode = mode;
+ if (mRefreshRateConfigs) {
+ mRefreshRateConfigs->setCurrentModeId(mActiveMode->getId());
+ }
}
status_t DisplayDevice::initiateModeChange(DisplayModeId modeId,
@@ -296,6 +300,10 @@
}
result.append("\n");
getCompositionDisplay()->dump(result);
+
+ if (mRefreshRateConfigs) {
+ mRefreshRateConfigs->dump(result);
+ }
}
bool DisplayDevice::hasRenderIntent(ui::RenderIntent intent) const {
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e5fe067..5a20a43 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -44,6 +44,8 @@
#include "DisplayHardware/Hal.h"
#include "DisplayHardware/PowerAdvisor.h"
+#include "Scheduler/RefreshRateConfigs.h"
+
namespace android {
class Fence;
@@ -193,6 +195,16 @@
// set-top boxes after a hotplug reconnect.
DisplayModePtr getMode(DisplayModeId) const;
+ // Returns the refresh rate configs for this display.
+ scheduler::RefreshRateConfigs& refreshRateConfigs() const { return *mRefreshRateConfigs; }
+
+ // Returns a shared pointer to the refresh rate configs for this display.
+ // Clients can store this refresh rate configs and use it even if the DisplayDevice
+ // is destroyed.
+ std::shared_ptr<scheduler::RefreshRateConfigs> holdRefreshRateConfigs() const {
+ return mRefreshRateConfigs;
+ }
+
void onVsync(nsecs_t timestamp);
nsecs_t getVsyncPeriodFromHWC() const;
nsecs_t getRefreshTimestamp() const;
@@ -238,6 +250,8 @@
std::optional<DeviceProductInfo> mDeviceProductInfo;
std::vector<ui::Hdr> mOverrideHdrTypes;
+
+ std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
};
struct DisplayDeviceState {
@@ -283,6 +297,7 @@
HWComposer& hwComposer;
const wp<IBinder> displayToken;
const std::shared_ptr<compositionengine::Display> compositionDisplay;
+ std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs;
int32_t sequenceId{0};
std::optional<ui::DisplayConnectionType> connectionType;
@@ -298,6 +313,7 @@
hardware::graphics::composer::hal::PowerMode::ON};
bool isPrimary{false};
DisplayModes supportedModes;
+ DisplayModeId activeModeId;
};
// Predicates for display lookup.
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 9cfc37d..9657a9f 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -283,7 +283,16 @@
void RefreshRateOverlay::reset() {
mBufferCache.clear();
- const auto range = mFlinger.mRefreshRateConfigs->getSupportedRefreshRateRange();
+ // TODO: this is a temp hack that would be removed in the next CL
+ const auto range = [&]() NO_THREAD_SAFETY_ANALYSIS {
+ constexpr auto defaultFps = Fps(60);
+ const auto display = mFlinger.getDefaultDisplayDeviceLocked();
+ if (display) {
+ return display->refreshRateConfigs().getSupportedRefreshRateRange();
+ }
+ ALOGW("%s: default display is null", __func__);
+ return scheduler::RefreshRateConfigs::FpsRange{defaultFps, defaultFps};
+ }();
mLowFps = range.min.getIntValue();
mHighFps = range.max.getIntValue();
}
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 0563795..84e3548 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -75,10 +75,9 @@
}
} // namespace
-LayerHistory::LayerHistory(const RefreshRateConfigs& refreshRateConfigs)
+LayerHistory::LayerHistory()
: mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {
LayerInfo::setTraceEnabled(mTraceEnabled);
- LayerInfo::setRefreshRateConfigs(refreshRateConfigs);
}
LayerHistory::~LayerHistory() = default;
@@ -138,7 +137,8 @@
}
}
-LayerHistory::Summary LayerHistory::summarize(nsecs_t now) {
+LayerHistory::Summary LayerHistory::summarize(const RefreshRateConfigs& refreshRateConfigs,
+ nsecs_t now) {
LayerHistory::Summary summary;
std::lock_guard lock(mLock);
@@ -151,7 +151,7 @@
ALOGV("%s has priority: %d %s focused", info->getName().c_str(), frameRateSelectionPriority,
layerFocused ? "" : "not");
- const auto vote = info->getRefreshRateVote(now);
+ const auto vote = info->getRefreshRateVote(refreshRateConfigs, now);
// Skip NoVote layer as those don't have any requirements
if (vote.type == LayerHistory::LayerVoteType::NoVote) {
continue;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 82f6c39..92236f5 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -42,7 +42,7 @@
public:
using LayerVoteType = RefreshRateConfigs::LayerVoteType;
- LayerHistory(const RefreshRateConfigs&);
+ LayerHistory();
~LayerHistory();
// Layers are unregistered when the weak reference expires.
@@ -67,7 +67,7 @@
using Summary = std::vector<RefreshRateConfigs::LayerRequirement>;
// Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
- Summary summarize(nsecs_t now);
+ Summary summarize(const RefreshRateConfigs&, nsecs_t now);
void clear();
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 989bf4e..8a45b66 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -34,7 +34,6 @@
namespace android::scheduler {
-const RefreshRateConfigs* LayerInfo::sRefreshRateConfigs = nullptr;
bool LayerInfo::sTraceEnabled = false;
LayerInfo::LayerInfo(const std::string& name, uid_t ownerUid,
@@ -184,7 +183,8 @@
return static_cast<nsecs_t>(averageFrameTime);
}
-std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(nsecs_t now) {
+std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(
+ const RefreshRateConfigs& refreshRateConfigs, nsecs_t now) {
static constexpr float MARGIN = 1.0f; // 1Hz
if (!hasEnoughDataForHeuristic()) {
ALOGV("Not enough data");
@@ -196,9 +196,7 @@
const auto refreshRate = Fps::fromPeriodNsecs(*averageFrameTime);
const bool refreshRateConsistent = mRefreshRateHistory.add(refreshRate, now);
if (refreshRateConsistent) {
- const auto knownRefreshRate =
- sRefreshRateConfigs->findClosestKnownFrameRate(refreshRate);
-
+ const auto knownRefreshRate = refreshRateConfigs.findClosestKnownFrameRate(refreshRate);
// To avoid oscillation, use the last calculated refresh rate if it is
// close enough
if (std::abs(mLastRefreshRate.calculated.getValue() - refreshRate.getValue()) >
@@ -220,7 +218,8 @@
: std::nullopt;
}
-LayerInfo::LayerVote LayerInfo::getRefreshRateVote(nsecs_t now) {
+LayerInfo::LayerVote LayerInfo::getRefreshRateVote(const RefreshRateConfigs& refreshRateConfigs,
+ nsecs_t now) {
if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) {
ALOGV("%s voted %d ", mName.c_str(), static_cast<int>(mLayerVote.type));
return mLayerVote;
@@ -247,7 +246,7 @@
clearHistory(now);
}
- auto refreshRate = calculateRefreshRateIfPossible(now);
+ auto refreshRate = calculateRefreshRateIfPossible(refreshRateConfigs, now);
if (refreshRate.has_value()) {
ALOGV("%s calculated refresh rate: %s", mName.c_str(), to_string(*refreshRate).c_str());
return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()};
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 34cc389..ce9783c 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -122,10 +122,6 @@
static void setTraceEnabled(bool enabled) { sTraceEnabled = enabled; }
- static void setRefreshRateConfigs(const RefreshRateConfigs& refreshRateConfigs) {
- sRefreshRateConfigs = &refreshRateConfigs;
- }
-
LayerInfo(const std::string& name, uid_t ownerUid, LayerHistory::LayerVoteType defaultVote);
LayerInfo(const LayerInfo&) = delete;
@@ -161,7 +157,7 @@
uid_t getOwnerUid() const { return mOwnerUid; }
- LayerVote getRefreshRateVote(nsecs_t now);
+ LayerVote getRefreshRateVote(const RefreshRateConfigs&, nsecs_t now);
// Return the last updated time. If the present time is farther in the future than the
// updated time, the updated time is the present time.
@@ -263,7 +259,7 @@
bool isFrequent(nsecs_t now) const;
bool isAnimating(nsecs_t now) const;
bool hasEnoughDataForHeuristic() const;
- std::optional<Fps> calculateRefreshRateIfPossible(nsecs_t now);
+ std::optional<Fps> calculateRefreshRateIfPossible(const RefreshRateConfigs&, nsecs_t now);
std::optional<nsecs_t> calculateAverageFrameTime() const;
bool isFrameTimeValid(const FrameTimeData&) const;
@@ -300,7 +296,6 @@
mutable std::unordered_map<LayerHistory::LayerVoteType, std::string> mTraceTags;
// Shared for all LayerInfo instances
- static const RefreshRateConfigs* sRefreshRateConfigs;
static bool sTraceEnabled;
};
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index dfd1395..884862d 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -316,8 +316,6 @@
Config config = {.enableFrameRateOverride = false,
.frameRateMultipleThreshold = 0});
- void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
-
// Returns whether switching modes (refresh rate or resolution) is possible.
// TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only
// differ in resolution.
@@ -354,6 +352,9 @@
void dump(std::string& result) const EXCLUDES(mLock);
+ RefreshRateConfigs(const RefreshRateConfigs&) = delete;
+ void operator=(const RefreshRateConfigs&) = delete;
+
private:
friend class RefreshRateConfigsTest;
@@ -405,6 +406,8 @@
float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&,
bool isSeamlessSwitch) const REQUIRES(mLock);
+ void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
+
// The list of refresh rates, indexed by display modes ID. This may change after this
// object is initialized.
AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 384e4e9..861f3ac 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -117,16 +117,17 @@
}
};
-Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
+Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
+ ISchedulerCallback& callback)
: Scheduler(configs, callback,
{.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
.useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
}
-Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
- Options options)
+Scheduler::Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
+ ISchedulerCallback& callback, Options options)
: Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,
- createLayerHistory(configs), options) {
+ createLayerHistory(), options) {
using namespace sysprop;
const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);
@@ -159,7 +160,8 @@
}
}
-Scheduler::Scheduler(VsyncSchedule schedule, const scheduler::RefreshRateConfigs& configs,
+Scheduler::Scheduler(VsyncSchedule schedule,
+ const std::shared_ptr<scheduler::RefreshRateConfigs>& configs,
ISchedulerCallback& schedulerCallback,
std::unique_ptr<LayerHistory> layerHistory, Options options)
: mOptions(options),
@@ -194,9 +196,8 @@
return {std::move(controller), std::move(tracker), std::move(dispatch)};
}
-std::unique_ptr<LayerHistory> Scheduler::createLayerHistory(
- const scheduler::RefreshRateConfigs& configs) {
- return std::make_unique<scheduler::LayerHistory>(configs);
+std::unique_ptr<LayerHistory> Scheduler::createLayerHistory() {
+ return std::make_unique<scheduler::LayerHistory>();
}
std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
@@ -207,11 +208,14 @@
}
std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
- if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
- return std::nullopt;
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->supportsFrameRateOverride()) {
+ return std::nullopt;
+ }
}
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
{
const auto iter = mFrameRateOverridesFromBackdoor.find(uid);
if (iter != mFrameRateOverridesFromBackdoor.end()) {
@@ -239,7 +243,8 @@
}
impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
- if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->supportsFrameRateOverride()) {
return {};
}
@@ -250,14 +255,18 @@
impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
return [this](uid_t uid) {
- nsecs_t basePeriod = mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod();
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
+ nsecs_t basePeriod = refreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
return basePeriod;
}
- const auto divider = scheduler::RefreshRateConfigs::getFrameRateDivider(
- mRefreshRateConfigs.getCurrentRefreshRate().getFps(), *frameRate);
+ const auto divider =
+ scheduler::RefreshRateConfigs::getFrameRateDivider(refreshRateConfigs
+ ->getCurrentRefreshRate()
+ .getFps(),
+ *frameRate);
if (divider <= 1) {
return basePeriod;
}
@@ -343,7 +352,7 @@
void Scheduler::onFrameRateOverridesChanged(ConnectionHandle handle, PhysicalDisplayId displayId) {
std::vector<FrameRateOverride> overrides;
{
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {
overrides.emplace_back(FrameRateOverride{uid, frameRate.getValue()});
}
@@ -388,7 +397,10 @@
}
const auto modeId = *mFeatures.modeId;
- const auto vsyncPeriod = mRefreshRateConfigs.getRefreshRateFromModeId(modeId).getVsyncPeriod();
+ const auto vsyncPeriod = [&] {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getRefreshRateFromModeId(modeId).getVsyncPeriod();
+ }();
// If there is no change from cached mode, there is no need to dispatch an event
if (modeId == mFeatures.cachedModeChangedParams->modeId &&
@@ -532,7 +544,11 @@
const nsecs_t last = mLastResyncTime.exchange(now);
if (now - last > kIgnoreDelay) {
- resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().getVsyncPeriod());
+ const auto vsyncPeriod = [&] {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ }();
+ resyncToHardwareVsync(false, vsyncPeriod);
}
}
@@ -602,9 +618,12 @@
void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime,
LayerHistory::LayerUpdateType updateType) {
- if (mRefreshRateConfigs.canSwitch()) {
- mLayerHistory->record(layer, presentTime, systemTime(), updateType);
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->canSwitch()) return;
}
+
+ mLayerHistory->record(layer, presentTime, systemTime(), updateType);
}
void Scheduler::setModeChangePending(bool pending) {
@@ -612,11 +631,16 @@
}
void Scheduler::chooseRefreshRateForContent() {
- if (!mRefreshRateConfigs.canSwitch()) return;
+ {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ if (!mRefreshRateConfigs->canSwitch()) return;
+ }
ATRACE_CALL();
- scheduler::LayerHistory::Summary summary = mLayerHistory->summarize(systemTime());
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
+ scheduler::LayerHistory::Summary summary =
+ mLayerHistory->summarize(*refreshRateConfigs, systemTime());
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
DisplayModeId newModeId;
bool frameRateChanged;
@@ -626,7 +650,7 @@
mFeatures.contentRequirements = summary;
newModeId = calculateRefreshRateModeId(&consideredSignals);
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
frameRateOverridesChanged =
updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps());
@@ -643,7 +667,7 @@
}
}
if (frameRateChanged) {
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ auto newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
mSchedulerCallback.changeRefreshRate(newRefreshRate,
consideredSignals.idle ? ModeEvent::None
: ModeEvent::Changed);
@@ -689,7 +713,11 @@
// TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate
// magic number
- const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+ const auto refreshRate = [&] {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getCurrentRefreshRate();
+ }();
+
constexpr Fps FPS_THRESHOLD_FOR_KERNEL_TIMER{65.0f};
if (state == TimerState::Reset &&
refreshRate.getFps().greaterThanWithMargin(FPS_THRESHOLD_FOR_KERNEL_TIMER)) {
@@ -741,7 +769,7 @@
mLayerHistory ? mLayerHistory->dump().c_str() : "(no layer history)");
{
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
StringAppendF(&result, "Frame Rate Overrides (backdoor): {");
for (const auto& [uid, frameRate] : mFrameRateOverridesFromBackdoor) {
StringAppendF(&result, "[uid: %d frameRate: %s], ", uid, to_string(frameRate).c_str());
@@ -767,16 +795,17 @@
bool Scheduler::updateFrameRateOverrides(
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals, Fps displayRefreshRate) {
- if (!mRefreshRateConfigs.supportsFrameRateOverride()) {
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
+ if (!refreshRateConfigs->supportsFrameRateOverride()) {
return false;
}
if (!consideredSignals.idle) {
const auto frameRateOverrides =
- mRefreshRateConfigs.getFrameRateOverrides(mFeatures.contentRequirements,
+ refreshRateConfigs->getFrameRateOverrides(mFeatures.contentRequirements,
displayRefreshRate,
consideredSignals.touch);
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),
frameRateOverrides.begin(), frameRateOverrides.end(),
[](const std::pair<uid_t, Fps>& a, const std::pair<uid_t, Fps>& b) {
@@ -795,6 +824,7 @@
bool refreshRateChanged = false;
bool frameRateOverridesChanged;
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
{
std::lock_guard<std::mutex> lock(mFeatureStateLock);
if (*currentState == newState) {
@@ -802,7 +832,7 @@
}
*currentState = newState;
newModeId = calculateRefreshRateModeId(&consideredSignals);
- const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ const RefreshRate& newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
frameRateOverridesChanged =
updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps());
if (mFeatures.modeId == newModeId) {
@@ -817,7 +847,7 @@
}
}
if (refreshRateChanged) {
- const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
+ const RefreshRate& newRefreshRate = refreshRateConfigs->getRefreshRateFromModeId(newModeId);
mSchedulerCallback.changeRefreshRate(newRefreshRate,
consideredSignals.idle ? ModeEvent::None
@@ -834,20 +864,21 @@
ATRACE_CALL();
if (consideredSignals) *consideredSignals = {};
+ const auto refreshRateConfigs = holdRefreshRateConfigs();
// 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)) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getModeId();
+ return refreshRateConfigs->getMaxRefreshRateByPolicy().getModeId();
}
const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired;
- return mRefreshRateConfigs
- .getBestRefreshRate(mFeatures.contentRequirements, {.touch = touchActive, .idle = idle},
- consideredSignals)
+ return refreshRateConfigs
+ ->getBestRefreshRate(mFeatures.contentRequirements,
+ {.touch = touchActive, .idle = idle}, consideredSignals)
.getModeId();
}
@@ -902,7 +933,7 @@
return;
}
- std::lock_guard lock(mFrameRateOverridesMutex);
+ std::lock_guard lock(mFrameRateOverridesLock);
if (frameRateOverride.frameRateHz != 0.f) {
mFrameRateOverridesFromBackdoor[frameRateOverride.uid] = Fps(frameRateOverride.frameRateHz);
} else {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 7a2fdb5..dc17f90 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -72,7 +72,7 @@
using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
using ModeEvent = scheduler::RefreshRateConfigEvent;
- Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&);
+ Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&);
~Scheduler();
using ConnectionHandle = scheduler::ConnectionHandle;
@@ -95,7 +95,7 @@
void onScreenReleased(ConnectionHandle);
void onFrameRateOverridesChanged(ConnectionHandle, PhysicalDisplayId)
- EXCLUDES(mFrameRateOverridesMutex) EXCLUDES(mConnectionsLock);
+ EXCLUDES(mFrameRateOverridesLock) EXCLUDES(mConnectionsLock);
// Modifies work duration in the event thread.
void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
@@ -116,7 +116,7 @@
// no-op.
// The period is the vsync period from the current display configuration.
void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
- void resync();
+ void resync() EXCLUDES(mRefreshRateConfigsLock);
// Passes a vsync sample to VsyncController. periodFlushed will be true if
// VsyncController detected that the vsync period changed, and false otherwise.
@@ -127,12 +127,13 @@
// Layers are registered on creation, and unregistered when the weak reference expires.
void registerLayer(Layer*);
- void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType);
+ void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType)
+ EXCLUDES(mRefreshRateConfigsLock);
void setModeChangePending(bool pending);
void deregisterLayer(Layer*);
// Detects content using layer history, and selects a matching refresh rate.
- void chooseRefreshRateForContent();
+ void chooseRefreshRateForContent() EXCLUDES(mRefreshRateConfigsLock);
bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); }
void resetIdleTimer();
@@ -147,7 +148,7 @@
// Returns true if a given vsync timestamp is considered valid vsync
// for a given uid
bool isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const
- EXCLUDES(mFrameRateOverridesMutex);
+ EXCLUDES(mFrameRateOverridesLock);
std::chrono::steady_clock::time_point getPreviousVsyncFrom(nsecs_t expectedPresentTime) const;
@@ -176,9 +177,21 @@
// Stores the preferred refresh rate that an app should run at.
// FrameRateOverride.refreshRateHz == 0 means no preference.
- void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesMutex);
+ void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesLock);
// Retrieves the overridden refresh rate for a given uid.
- std::optional<Fps> getFrameRateOverride(uid_t uid) const EXCLUDES(mFrameRateOverridesMutex);
+ std::optional<Fps> getFrameRateOverride(uid_t uid) const
+ EXCLUDES(mRefreshRateConfigsLock, mFrameRateOverridesLock);
+
+ void setRefreshRateConfigs(std::shared_ptr<scheduler::RefreshRateConfigs> refreshRateConfigs)
+ EXCLUDES(mRefreshRateConfigsLock) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ mRefreshRateConfigs = std::move(refreshRateConfigs);
+ }
+
+ nsecs_t getVsyncPeriodFromRefreshRateConfigs() const EXCLUDES(mRefreshRateConfigsLock) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ }
private:
friend class TestableScheduler;
@@ -203,14 +216,14 @@
};
// Unlike the testing constructor, this creates the VsyncSchedule, LayerHistory, and timers.
- Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&, Options);
+ Scheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&, Options);
// Used by tests to inject mocks.
- Scheduler(VsyncSchedule, const scheduler::RefreshRateConfigs&, ISchedulerCallback&,
- std::unique_ptr<LayerHistory>, Options);
+ Scheduler(VsyncSchedule, const std::shared_ptr<scheduler::RefreshRateConfigs>&,
+ ISchedulerCallback&, std::unique_ptr<LayerHistory>, Options);
static VsyncSchedule createVsyncSchedule(bool supportKernelIdleTimer);
- static std::unique_ptr<LayerHistory> createLayerHistory(const scheduler::RefreshRateConfigs&);
+ static std::unique_ptr<LayerHistory> createLayerHistory();
// Create a connection on the given EventThread.
ConnectionHandle createConnection(std::unique_ptr<EventThread>);
@@ -218,7 +231,7 @@
EventThread*, ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
// Update feature state machine to given state when corresponding timer resets or expires.
- void kernelIdleTimerCallback(TimerState);
+ void kernelIdleTimerCallback(TimerState) EXCLUDES(mRefreshRateConfigsLock);
void idleTimerCallback(TimerState);
void touchTimerCallback(TimerState);
void displayPowerTimerCallback(TimerState);
@@ -236,14 +249,21 @@
scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr)
REQUIRES(mFeatureStateLock);
- void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock);
+ void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock) EXCLUDES(mRefreshRateConfigsLock);
bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals,
Fps displayRefreshRate) REQUIRES(mFeatureStateLock)
- EXCLUDES(mFrameRateOverridesMutex);
+ EXCLUDES(mFrameRateOverridesLock);
- impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const;
+ impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const
+ EXCLUDES(mRefreshRateConfigsLock);
impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
+ std::shared_ptr<scheduler::RefreshRateConfigs> holdRefreshRateConfigs() const
+ EXCLUDES(mRefreshRateConfigsLock) {
+ std::scoped_lock lock(mRefreshRateConfigsLock);
+ return mRefreshRateConfigs;
+ }
+
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
struct Connection {
sp<EventThreadConnection> connection;
@@ -304,7 +324,9 @@
std::optional<ModeChangedParams> cachedModeChangedParams;
} mFeatures GUARDED_BY(mFeatureStateLock);
- const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
+ mutable std::mutex mRefreshRateConfigsLock;
+ std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs
+ GUARDED_BY(mRefreshRateConfigsLock);
std::mutex mVsyncTimelineLock;
std::optional<hal::VsyncPeriodChangeTimeline> mLastVsyncPeriodChangeTimeline
@@ -315,14 +337,14 @@
// 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 mFrameRateOverridesMutex;
+ mutable std::mutex mFrameRateOverridesLock;
// mappings between a UID and a preferred refresh rate that this app would
// run at.
scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesByContent
- GUARDED_BY(mFrameRateOverridesMutex);
+ GUARDED_BY(mFrameRateOverridesLock);
scheduler::RefreshRateConfigs::UidToFrameRateOverride mFrameRateOverridesFromBackdoor
- GUARDED_BY(mFrameRateOverridesMutex);
+ GUARDED_BY(mFrameRateOverridesLock);
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 18cb0c2..40e0ed6 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1073,7 +1073,13 @@
void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) {
ATRACE_CALL();
- auto refreshRate = mRefreshRateConfigs->getRefreshRateFromModeId(info.modeId);
+ const auto display = getDefaultDisplayDeviceLocked();
+ if (!display) {
+ ALOGW("%s: default display is null", __func__);
+ return;
+ }
+
+ auto refreshRate = display->refreshRateConfigs().getRefreshRateFromModeId(info.modeId);
ALOGV("%s(%s)", __func__, refreshRate.getName().c_str());
std::lock_guard<std::mutex> lock(mActiveModeLock);
@@ -1084,8 +1090,7 @@
mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig;
} else {
// Check if we are already at the desired mode
- const auto display = getDefaultDisplayDeviceLocked();
- if (!display || display->getActiveMode()->getId() == refreshRate.getModeId()) {
+ if (display->getActiveMode()->getId() == refreshRate.getModeId()) {
return;
}
@@ -1136,7 +1141,7 @@
const auto fps = mode->getFps();
// Keep the old switching type.
const auto allowGroupSwitching =
- mRefreshRateConfigs->getCurrentPolicy().allowGroupSwitching;
+ display->refreshRateConfigs().getCurrentPolicy().allowGroupSwitching;
const scheduler::RefreshRateConfigs::Policy policy{mode->getId(),
allowGroupSwitching,
{fps, fps}};
@@ -1178,7 +1183,6 @@
}
std::lock_guard<std::mutex> lock(mActiveModeLock);
- mRefreshRateConfigs->setCurrentModeId(mUpcomingActiveMode.modeId);
display->setActiveMode(mUpcomingActiveMode.modeId);
const Fps refreshRate = upcomingMode->getFps();
@@ -1744,7 +1748,12 @@
}
bool SurfaceFlinger::isDisplayModeAllowed(DisplayModeId modeId) const {
- return mRefreshRateConfigs->isModeAllowed(modeId);
+ const auto display = getDefaultDisplayDeviceLocked();
+ if (display) {
+ return display->refreshRateConfigs().isModeAllowed(modeId);
+ }
+ ALOGW("%s: default display is null", __func__);
+ return false;
}
void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate,
@@ -2470,7 +2479,6 @@
// We call getTransactionFlags(), which will also clear the flags,
// with mStateLock held to guarantee that mCurrentState won't change
// until the transaction is committed.
-
modulateVsync(&VsyncModulator::onTransactionCommit);
transactionFlags = getTransactionFlags(eTransactionMask);
handleTransactionLocked(transactionFlags);
@@ -2583,11 +2591,6 @@
sp<IBinder> token = new BBinder();
mCurrentState.displays.add(token, state);
mPhysicalDisplayTokens.emplace(displayId, std::move(token));
-
- if (event.hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
- initScheduler(state);
- }
-
mInterceptor->saveDisplayCreation(state);
} else {
ALOGV("Recreating display %s", to_string(displayId).c_str());
@@ -2642,6 +2645,14 @@
if (const auto& physical = state.physical) {
creationArgs.connectionType = physical->type;
creationArgs.supportedModes = physical->supportedModes;
+ creationArgs.activeModeId = physical->activeMode->getId();
+ scheduler::RefreshRateConfigs::Config config =
+ {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
+ .frameRateMultipleThreshold =
+ base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
+ creationArgs.refreshRateConfigs =
+ std::make_shared<scheduler::RefreshRateConfigs>(creationArgs.supportedModes,
+ creationArgs.activeModeId, config);
}
if (const auto id = PhysicalDisplayId::tryCast(compositionDisplay->getId())) {
@@ -2780,6 +2791,9 @@
const auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay),
state, displaySurface, producer);
mDisplays.emplace(displayToken, display);
+ if (display->isPrimary()) {
+ initScheduler(display);
+ }
if (!state.isVirtual()) {
dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
}
@@ -2847,8 +2861,7 @@
// TODO(b/175678251) Call a listener instead.
if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
- updateInternalDisplayVsyncLocked(currentState.physical->supportedModes,
- currentState.physical->activeMode->getId());
+ updateInternalDisplayVsyncLocked(display);
}
}
return;
@@ -2884,11 +2897,9 @@
}
}
}
-void SurfaceFlinger::updateInternalDisplayVsyncLocked(const DisplayModes& modes,
- DisplayModeId currentModeId) {
- mRefreshRateConfigs->updateDisplayModes(modes, currentModeId);
+void SurfaceFlinger::updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) {
mVsyncConfiguration->reset();
- const Fps refreshRate = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+ const Fps refreshRate = activeDisplay->refreshRateConfigs().getCurrentRefreshRate().getFps();
updatePhaseConfiguration(refreshRate);
mRefreshRateStats->setRefreshRate(refreshRate);
if (mRefreshRateOverlay) {
@@ -3122,24 +3133,15 @@
mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
}
-void SurfaceFlinger::initScheduler(const DisplayDeviceState& displayState) {
+void SurfaceFlinger::initScheduler(const sp<DisplayDevice>& display) {
if (mScheduler) {
// In practice it's not allowed to hotplug in/out the primary display once it's been
// connected during startup, but some tests do it, so just warn and return.
ALOGW("Can't re-init scheduler");
return;
}
- const auto displayId = displayState.physical->id;
- scheduler::RefreshRateConfigs::Config config =
- {.enableFrameRateOverride = android::sysprop::enable_frame_rate_override(false),
- .frameRateMultipleThreshold =
- base::GetIntProperty("debug.sf.frame_rate_multiple_threshold", 0)};
- mRefreshRateConfigs =
- std::make_unique<scheduler::RefreshRateConfigs>(displayState.physical->supportedModes,
- displayState.physical->activeMode
- ->getId(),
- config);
- const auto currRefreshRate = displayState.physical->activeMode->getFps();
+ const auto displayId = display->getId();
+ const auto currRefreshRate = display->getActiveMode()->getFps();
mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
hal::PowerMode::OFF);
@@ -3147,7 +3149,7 @@
mVsyncModulator.emplace(mVsyncConfiguration->getCurrentConfigs());
// start the EventThread
- mScheduler = getFactory().createScheduler(*mRefreshRateConfigs, *this);
+ mScheduler = getFactory().createScheduler(display->holdRefreshRateConfigs(), *this);
const auto configs = mVsyncConfiguration->getCurrentConfigs();
const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
mAppConnectionHandle =
@@ -3176,9 +3178,9 @@
// This is a bit hacky, but this avoids a back-pointer into the main SF
// 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, displayId,
- displayState.physical->activeMode->getId(),
- vsyncPeriod);
+ mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle,
+ *PhysicalDisplayId::tryCast(displayId),
+ display->getActiveMode()->getId(), vsyncPeriod);
static auto ignorePresentFences =
base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
mScheduler->setIgnorePresentFences(
@@ -4496,7 +4498,8 @@
{}, getpid(), getuid(), 0 /* Undefined transactionId */);
setPowerModeInternal(display, hal::PowerMode::ON);
- const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ const nsecs_t vsyncPeriod =
+ display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
mDefaultDisplayTransformHint = display->getTransformHint();
// Use phase of 0 since phase is not known.
@@ -4549,7 +4552,7 @@
if (mInterceptor->isEnabled()) {
mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
}
- const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ const auto vsyncPeriod = display->refreshRateConfigs().getCurrentRefreshRate().getVsyncPeriod();
if (currentMode == hal::PowerMode::OFF) {
const auto activeDisplay = getDisplayDeviceLocked(mActiveDisplayToken);
if (display->isInternal() && (!activeDisplay || !activeDisplay->isPoweredOn())) {
@@ -4781,8 +4784,6 @@
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
- mRefreshRateConfigs->dump(result);
-
StringAppendF(&result, "(mode override by backdoor: %s)\n\n",
mDebugDisplayModeSetByBackdoor ? "yes" : "no");
@@ -5823,8 +5824,13 @@
desiredActiveMode ? std::make_optional(desiredActiveMode->modeId) : std::nullopt;
const bool timerExpired = mKernelIdleTimerEnabled && expired;
+ const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+ if (!display) {
+ ALOGW("%s: default display is null", __func__);
+ return;
+ }
const auto newRefreshRate =
- mRefreshRateConfigs->onKernelTimerChanged(desiredModeId, timerExpired);
+ display->refreshRateConfigs().onKernelTimerChanged(desiredModeId, timerExpired);
if (newRefreshRate) {
if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
mRefreshRateOverlay->changeRefreshRate(*newRefreshRate);
@@ -5841,8 +5847,13 @@
if (!mSupportKernelIdleTimer) {
return;
}
- const KernelIdleTimerAction action = mRefreshRateConfigs->getIdleTimerAction();
+ const auto display = getDefaultDisplayDeviceLocked();
+ if (!display) {
+ ALOGW("%s: default display is null", __func__);
+ return;
+ }
+ const KernelIdleTimerAction action = display->refreshRateConfigs().getIdleTimerAction();
switch (action) {
case KernelIdleTimerAction::TurnOff:
if (mKernelIdleTimerEnabled) {
@@ -6471,6 +6482,16 @@
return NO_ERROR;
}
+ status_t setPolicyResult = overridePolicy
+ ? display->refreshRateConfigs().setOverridePolicy(policy)
+ : display->refreshRateConfigs().setDisplayManagerPolicy(*policy);
+ if (setPolicyResult < 0) {
+ return BAD_VALUE;
+ }
+ if (setPolicyResult == scheduler::RefreshRateConfigs::CURRENT_POLICY_UNCHANGED) {
+ return NO_ERROR;
+ }
+
if (!isDefaultDisplay) {
// TODO(b/144711714): For non-default displays we should be able to set an active mode
// as well. For now, just call directly to initiateModeChange but ideally
@@ -6497,16 +6518,8 @@
return NO_ERROR;
}
- status_t setPolicyResult = overridePolicy
- ? mRefreshRateConfigs->setOverridePolicy(policy)
- : mRefreshRateConfigs->setDisplayManagerPolicy(*policy);
- if (setPolicyResult < 0) {
- return BAD_VALUE;
- }
- if (setPolicyResult == scheduler::RefreshRateConfigs::CURRENT_POLICY_UNCHANGED) {
- return NO_ERROR;
- }
- scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy();
+ scheduler::RefreshRateConfigs::Policy currentPolicy =
+ display->refreshRateConfigs().getCurrentPolicy();
ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());
@@ -6519,11 +6532,9 @@
vsyncPeriod);
toggleKernelIdleTimer();
- auto modeId = mScheduler->getPreferredModeId();
- auto preferredRefreshRate = modeId
- ? mRefreshRateConfigs->getRefreshRateFromModeId(*modeId)
- // NOTE: Choose the default mode ID, if Scheduler doesn't have one in mind.
- : mRefreshRateConfigs->getRefreshRateFromModeId(currentPolicy.defaultMode);
+ auto modeId = mScheduler->getPreferredModeId() ? *mScheduler->getPreferredModeId()
+ : currentPolicy.defaultMode;
+ auto preferredRefreshRate = display->refreshRateConfigs().getRefreshRateFromModeId(modeId);
ALOGV("trying to switch to Scheduler preferred mode %d (%s)",
preferredRefreshRate.getModeId().value(), preferredRefreshRate.getName().c_str());
@@ -6593,29 +6604,19 @@
return NAME_NOT_FOUND;
}
- if (display == getDefaultDisplayDeviceLocked()) {
- scheduler::RefreshRateConfigs::Policy policy =
- mRefreshRateConfigs->getDisplayManagerPolicy();
- *outDefaultMode = policy.defaultMode.value();
- *outAllowGroupSwitching = policy.allowGroupSwitching;
- *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue();
- *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue();
- *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue();
- *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue();
- return NO_ERROR;
- } else if (display->isVirtual()) {
+ if (display->isVirtual()) {
return INVALID_OPERATION;
- } else {
- const auto activeMode = display->getActiveMode();
- *outDefaultMode = activeMode->getId().value();
- *outAllowGroupSwitching = false;
- auto vsyncPeriod = activeMode->getVsyncPeriod();
- *outPrimaryRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
- *outPrimaryRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
- *outAppRequestRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
- *outAppRequestRefreshRateMax = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
- return NO_ERROR;
}
+
+ scheduler::RefreshRateConfigs::Policy policy =
+ display->refreshRateConfigs().getDisplayManagerPolicy();
+ *outDefaultMode = policy.defaultMode.value();
+ *outAllowGroupSwitching = policy.allowGroupSwitching;
+ *outPrimaryRefreshRateMin = policy.primaryRange.min.getValue();
+ *outPrimaryRefreshRateMax = policy.primaryRange.max.getValue();
+ *outAppRequestRefreshRateMin = policy.appRequestRange.min.getValue();
+ *outAppRequestRefreshRateMax = policy.appRequestRange.max.getValue();
+ return NO_ERROR;
}
wp<Layer> SurfaceFlinger::fromHandle(const sp<IBinder>& handle) {
@@ -6746,7 +6747,8 @@
// matter for the override policy though, since we set allowGroupSwitching to
// true, so it's not a problem.
scheduler::RefreshRateConfigs::Policy overridePolicy;
- overridePolicy.defaultMode = mRefreshRateConfigs->getDisplayManagerPolicy().defaultMode;
+ overridePolicy.defaultMode =
+ display->refreshRateConfigs().getDisplayManagerPolicy().defaultMode;
overridePolicy.allowGroupSwitching = true;
constexpr bool kOverridePolicy = true;
result = setDesiredDisplayModeSpecsInternal(display, overridePolicy, kOverridePolicy);
@@ -6860,7 +6862,14 @@
}
status_t SurfaceFlinger::getMaxAcquiredBufferCount(int* buffers) const {
- const auto maxSupportedRefreshRate = mRefreshRateConfigs->getSupportedRefreshRateRange().max;
+ const auto maxSupportedRefreshRate = [&] {
+ const auto display = getDefaultDisplayDevice();
+ if (display) {
+ return display->refreshRateConfigs().getSupportedRefreshRateRange().max;
+ }
+ ALOGW("%s: default display is null", __func__);
+ return Fps(60);
+ }();
*buffers = getMaxAcquiredBufferCountForRefreshRate(maxSupportedRefreshRate);
return NO_ERROR;
}
@@ -6871,7 +6880,14 @@
if (frameRateOverride.has_value()) {
return frameRateOverride.value();
}
- return mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+
+ const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
+ if (display) {
+ return display->refreshRateConfigs().getCurrentRefreshRate().getFps();
+ }
+
+ ALOGW("%s: default display is null", __func__);
+ return Fps(60);
}();
return getMaxAcquiredBufferCountForRefreshRate(refreshRate);
}
@@ -6999,8 +7015,8 @@
ALOGE("%s: activeDisplay is null", __func__);
return;
}
- updateInternalDisplayVsyncLocked(activeDisplay->getSupportedModes(),
- activeDisplay->getActiveMode()->getId());
+ updateInternalDisplayVsyncLocked(activeDisplay);
+ mScheduler->setRefreshRateConfigs(activeDisplay->holdRefreshRateConfigs());
onActiveDisplaySizeChanged(activeDisplay);
if (mRefreshRateOverlay) {
mRefreshRateOverlay->setViewport(activeDisplay->getSize());
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 338aa18..1271596 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -590,7 +590,7 @@
typename Handler = VsyncModulator::VsyncConfigOpt (VsyncModulator::*)(Args...)>
void modulateVsync(Handler handler, Args... args) {
if (const auto config = (*mVsyncModulator.*handler)(args...)) {
- const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
+ const auto vsyncPeriod = mScheduler->getVsyncPeriodFromRefreshRateConfigs();
setVsyncConfig(*config, vsyncPeriod);
}
}
@@ -750,7 +750,7 @@
// Called when the frame rate override list changed to trigger an event.
void triggerOnFrameRateOverridesChanged() override;
// Toggles the kernel idle timer on or off depending the policy decisions around refresh rates.
- void toggleKernelIdleTimer();
+ void toggleKernelIdleTimer() REQUIRES(mStateLock);
// Keeps track of whether the kernel idle timer is currently enabled, so we don't have to
// make calls to sys prop each time.
bool mKernelIdleTimerEnabled = false;
@@ -814,7 +814,7 @@
void commitInputWindowCommands() REQUIRES(mStateLock);
void updateCursorAsync();
- void initScheduler(const DisplayDeviceState&) REQUIRES(mStateLock);
+ void initScheduler(const sp<DisplayDevice>& display) REQUIRES(mStateLock);
void updatePhaseConfiguration(const Fps&) REQUIRES(mStateLock);
void setVsyncConfig(const VsyncModulator::VsyncConfig&, nsecs_t vsyncPeriod);
@@ -975,7 +975,7 @@
return nullptr;
}
- sp<const DisplayDevice> getDefaultDisplayDevice() EXCLUDES(mStateLock) {
+ sp<const DisplayDevice> getDefaultDisplayDevice() const EXCLUDES(mStateLock) {
Mutex::Autolock lock(mStateLock);
return getDefaultDisplayDeviceLocked();
}
@@ -1211,7 +1211,7 @@
std::chrono::nanoseconds presentLatency);
int getMaxAcquiredBufferCountForRefreshRate(Fps refreshRate) const;
- void updateInternalDisplayVsyncLocked(const DisplayModes& modes, DisplayModeId currentModeId)
+ void updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay)
REQUIRES(mStateLock);
sp<StartPropertySetThread> mStartPropertySetThread;
@@ -1410,7 +1410,6 @@
// Optional to defer construction until PhaseConfiguration is created.
std::optional<scheduler::VsyncModulator> mVsyncModulator;
- std::unique_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
std::atomic<nsecs_t> mExpectedPresentTime = 0;
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index 4a75180..89d1c4d 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -65,8 +65,9 @@
}
std::unique_ptr<Scheduler> DefaultFactory::createScheduler(
- const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback) {
- return std::make_unique<Scheduler>(configs, callback);
+ const std::shared_ptr<scheduler::RefreshRateConfigs>& refreshRateConfigs,
+ ISchedulerCallback& callback) {
+ return std::make_unique<Scheduler>(std::move(refreshRateConfigs), callback);
}
sp<SurfaceInterceptor> DefaultFactory::createSurfaceInterceptor() {
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
index 24148dd..b8bf2ba 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
@@ -30,8 +30,8 @@
std::unique_ptr<MessageQueue> createMessageQueue() override;
std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(
Fps currentRefreshRate) override;
- std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&,
- ISchedulerCallback&) override;
+ std::unique_ptr<Scheduler> createScheduler(
+ const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&) override;
sp<SurfaceInterceptor> createSurfaceInterceptor() override;
sp<StartPropertySetThread> createStartPropertySetThread(bool timestampPropertyValue) override;
sp<DisplayDevice> createDisplayDevice(DisplayDeviceCreationArgs&) override;
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 885297f..13c95dd 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -79,8 +79,8 @@
virtual std::unique_ptr<MessageQueue> createMessageQueue() = 0;
virtual std::unique_ptr<scheduler::VsyncConfiguration> createVsyncConfiguration(
Fps currentRefreshRate) = 0;
- virtual std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&,
- ISchedulerCallback&) = 0;
+ virtual std::unique_ptr<Scheduler> createScheduler(
+ const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&) = 0;
virtual sp<SurfaceInterceptor> createSurfaceInterceptor() = 0;
virtual sp<StartPropertySetThread> createStartPropertySetThread(
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index b67ebca..d0d5ca4 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -35,6 +35,7 @@
using testing::_;
using testing::Return;
+using testing::ReturnRef;
namespace android {
@@ -62,6 +63,10 @@
LayerHistory& history() { return *mScheduler->mutableLayerHistory(); }
const LayerHistory& history() const { return *mScheduler->mutableLayerHistory(); }
+ LayerHistory::Summary summarizeLayerHistory(nsecs_t now) {
+ return history().summarize(*mScheduler->refreshRateConfigs(), now);
+ }
+
size_t layerCount() const { return mScheduler->layerHistorySize(); }
size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; }
@@ -101,7 +106,7 @@
history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += frameRate.getPeriodNsecs();
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
}
ASSERT_EQ(1, summary.size());
@@ -110,21 +115,24 @@
<< "Frame rate is " << frameRate;
}
- RefreshRateConfigs mConfigs{{DisplayMode::Builder(0)
- .setId(DisplayModeId(0))
- .setVsyncPeriod(int32_t(LO_FPS_PERIOD))
- .setGroup(0)
- .build(),
- DisplayMode::Builder(1)
- .setId(DisplayModeId(1))
- .setVsyncPeriod(int32_t(HI_FPS_PERIOD))
- .setGroup(0)
- .build()},
- DisplayModeId(0)};
+ std::shared_ptr<RefreshRateConfigs> mConfigs =
+ std::make_shared<RefreshRateConfigs>(DisplayModes{DisplayMode::Builder(0)
+ .setId(DisplayModeId(0))
+ .setVsyncPeriod(int32_t(
+ LO_FPS_PERIOD))
+ .setGroup(0)
+ .build(),
+ DisplayMode::Builder(1)
+ .setId(DisplayModeId(1))
+ .setVsyncPeriod(int32_t(
+ HI_FPS_PERIOD))
+ .setGroup(0)
+ .build()},
+ DisplayModeId(0));
- mock::NoOpSchedulerCallback mSchedulerCallback;
+ mock::SchedulerCallback mSchedulerCallback;
- TestableScheduler* const mScheduler = new TestableScheduler(mConfigs, mSchedulerCallback);
+ TestableScheduler* mScheduler = new TestableScheduler(mConfigs, mSchedulerCallback);
TestableSurfaceFlinger mFlinger;
};
@@ -142,22 +150,22 @@
const nsecs_t time = systemTime();
// No layers returned if no layers are active.
- EXPECT_TRUE(history().summarize(time).empty());
+ EXPECT_TRUE(summarizeLayerHistory(time).empty());
EXPECT_EQ(0, activeLayerCount());
// Max returned if active layers have insufficient history.
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) {
history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer);
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
}
// Max is returned since we have enough history but there is no timestamp votes.
for (int i = 0; i < 10; i++) {
history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer);
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
}
}
@@ -173,17 +181,17 @@
nsecs_t time = systemTime();
history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer);
- auto summary = history().summarize(time);
- ASSERT_EQ(1, history().summarize(time).size());
+ auto summary = summarizeLayerHistory(time);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
// Layer is still considered inactive so we expect to get Min
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote);
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false));
history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer);
- summary = history().summarize(time);
- EXPECT_TRUE(history().summarize(time).empty());
+ summary = summarizeLayerHistory(time);
+ EXPECT_TRUE(summarizeLayerHistory(time).empty());
EXPECT_EQ(0, activeLayerCount());
}
@@ -201,9 +209,9 @@
time += LO_FPS_PERIOD;
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote);
- EXPECT_TRUE(LO_FPS.equalsWithMargin(history().summarize(time)[0].desiredRefreshRate));
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote);
+ EXPECT_TRUE(LO_FPS.equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
}
@@ -224,13 +232,13 @@
time += HI_FPS_PERIOD;
}
- ASSERT_TRUE(history().summarize(time).empty());
+ ASSERT_TRUE(summarizeLayerHistory(time).empty());
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer became inactive
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
- ASSERT_TRUE(history().summarize(time).empty());
+ ASSERT_TRUE(summarizeLayerHistory(time).empty());
EXPECT_EQ(0, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -251,14 +259,14 @@
time += HI_FPS_PERIOD;
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer became inactive
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
- ASSERT_TRUE(history().summarize(time).empty());
+ ASSERT_TRUE(summarizeLayerHistory(time).empty());
EXPECT_EQ(0, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -279,14 +287,14 @@
time += LO_FPS_PERIOD;
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer became inactive
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
- ASSERT_TRUE(history().summarize(time).empty());
+ ASSERT_TRUE(summarizeLayerHistory(time).empty());
EXPECT_EQ(0, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -307,18 +315,18 @@
time += HI_FPS_PERIOD;
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote);
- EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate));
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote);
+ EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer became inactive, but the vote stays
setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, history().summarize(time)[0].vote);
- EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate));
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote);
+ EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -339,20 +347,20 @@
time += HI_FPS_PERIOD;
}
- ASSERT_EQ(1, history().summarize(time).size());
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
- history().summarize(time)[0].vote);
- EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate));
+ summarizeLayerHistory(time)[0].vote);
+ EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
// layer became inactive, but the vote stays
setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic);
time += MAX_ACTIVE_LAYER_PERIOD_NS.count();
- ASSERT_EQ(1, history().summarize(time).size());
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
- history().summarize(time)[0].vote);
- EXPECT_TRUE(Fps(73.4f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate));
+ summarizeLayerHistory(time)[0].vote);
+ EXPECT_TRUE(Fps(73.4f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -383,7 +391,7 @@
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer1.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
}
ASSERT_EQ(1, summary.size());
@@ -395,7 +403,7 @@
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += HI_FPS_PERIOD;
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
}
// layer1 is still active but infrequent.
@@ -404,7 +412,7 @@
ASSERT_EQ(2, summary.size());
EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote);
ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote);
- EXPECT_TRUE(HI_FPS.equalsWithMargin(history().summarize(time)[1].desiredRefreshRate));
+ EXPECT_TRUE(HI_FPS.equalsWithMargin(summarizeLayerHistory(time)[1].desiredRefreshRate));
EXPECT_EQ(2, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
@@ -414,7 +422,7 @@
for (int i = 0; i < 2 * PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += LO_FPS_PERIOD;
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
}
ASSERT_EQ(1, summary.size());
@@ -433,7 +441,7 @@
history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += HI_FPS_PERIOD;
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
}
ASSERT_EQ(2, summary.size());
@@ -445,7 +453,7 @@
// layer3 becomes recently active.
history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
ASSERT_EQ(2, summary.size());
EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
EXPECT_TRUE(LO_FPS.equalsWithMargin(summary[0].desiredRefreshRate));
@@ -456,7 +464,7 @@
// layer1 expires.
layer1.clear();
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
ASSERT_EQ(2, summary.size());
EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote);
@@ -472,7 +480,7 @@
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) {
history().record(layer2.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += LO_FPS_PERIOD;
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
}
ASSERT_EQ(1, summary.size());
@@ -483,7 +491,7 @@
// layer2 expires.
layer2.clear();
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
EXPECT_TRUE(summary.empty());
EXPECT_EQ(1, layerCount());
EXPECT_EQ(0, activeLayerCount());
@@ -493,7 +501,7 @@
for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) {
history().record(layer3.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += HI_FPS_PERIOD;
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
}
ASSERT_EQ(1, summary.size());
@@ -505,7 +513,7 @@
// layer3 expires.
layer3.clear();
- summary = history().summarize(time);
+ summary = summarizeLayerHistory(time);
EXPECT_TRUE(summary.empty());
EXPECT_EQ(0, layerCount());
EXPECT_EQ(0, activeLayerCount());
@@ -526,8 +534,8 @@
time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
EXPECT_EQ(1, layerCount());
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
}
@@ -537,8 +545,8 @@
time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
EXPECT_EQ(1, layerCount());
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
@@ -551,8 +559,8 @@
time += HI_FPS_PERIOD;
EXPECT_EQ(1, layerCount());
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
}
@@ -562,8 +570,8 @@
time += HI_FPS_PERIOD;
EXPECT_EQ(1, layerCount());
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(1, frequentLayerCount(time));
}
@@ -590,10 +598,10 @@
LayerHistory::LayerUpdateType::Buffer);
EXPECT_EQ(2, layerCount());
- ASSERT_EQ(1, history().summarize(time).size());
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple,
- history().summarize(time)[0].vote);
- EXPECT_TRUE(Fps(60.0f).equalsWithMargin(history().summarize(time)[0].desiredRefreshRate));
+ summarizeLayerHistory(time)[0].vote);
+ EXPECT_TRUE(Fps(60.0f).equalsWithMargin(summarizeLayerHistory(time)[0].desiredRefreshRate));
EXPECT_EQ(2, activeLayerCount());
EXPECT_EQ(2, frequentLayerCount(time));
}
@@ -617,8 +625,8 @@
time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
}
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
EXPECT_EQ(0, animatingLayerCount(time));
@@ -627,8 +635,8 @@
history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::Buffer);
time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
EXPECT_EQ(0, animatingLayerCount(time));
@@ -637,8 +645,8 @@
history().record(layer.get(), time, time, LayerHistory::LayerUpdateType::AnimationTX);
time += MAX_FREQUENT_LAYER_PERIOD_NS.count();
- ASSERT_EQ(1, history().summarize(time).size());
- EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+ EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote);
EXPECT_EQ(1, activeLayerCount());
EXPECT_EQ(0, frequentLayerCount(time));
EXPECT_EQ(1, animatingLayerCount(time));
@@ -727,13 +735,13 @@
}
if (time - startTime > PRESENT_TIME_HISTORY_DURATION.count()) {
- ASSERT_NE(0, history().summarize(time).size());
- ASSERT_GE(2, history().summarize(time).size());
+ ASSERT_NE(0, summarizeLayerHistory(time).size());
+ ASSERT_GE(2, summarizeLayerHistory(time).size());
bool max = false;
bool min = false;
Fps heuristic{0.0};
- for (const auto& layer : history().summarize(time)) {
+ for (const auto& layer : summarizeLayerHistory(time)) {
if (layer.vote == LayerHistory::LayerVoteType::Heuristic) {
heuristic = layer.desiredRefreshRate;
} else if (layer.vote == LayerHistory::LayerVoteType::Max) {
@@ -746,7 +754,7 @@
if (infrequentLayerUpdates > FREQUENT_LAYER_WINDOW_SIZE) {
EXPECT_TRUE(Fps(24.0f).equalsWithMargin(heuristic));
EXPECT_FALSE(max);
- if (history().summarize(time).size() == 2) {
+ if (summarizeLayerHistory(time).size() == 2) {
EXPECT_TRUE(min);
}
}
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 3423bd5..e0b0a87 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -2272,26 +2272,6 @@
ASSERT_TRUE(frameRateOverrides.empty());
}
-TEST_F(RefreshRateConfigsTest, updateDisplayModes) {
- auto refreshRateConfigs =
- std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
- /*currentConfigId=*/HWC_CONFIG_ID_30);
- refreshRateConfigs->setDisplayManagerPolicy({DisplayModeId(HWC_CONFIG_ID_30),
- /* allowGroupSwitching */ false,
- /* range */ {Fps(30.0f), Fps(30.0f)}});
-
- refreshRateConfigs->updateDisplayModes(m60_90Device, HWC_CONFIG_ID_60);
-
- const auto currentRefreshRate = refreshRateConfigs->getCurrentRefreshRate();
- EXPECT_TRUE(currentRefreshRate.getFps().equalsWithMargin(Fps(60.0)));
- EXPECT_EQ(currentRefreshRate.getModeId(), HWC_CONFIG_ID_60);
-
- EXPECT_TRUE(
- getMaxSupportedRefreshRate(*refreshRateConfigs).getFps().equalsWithMargin(Fps(90.0)));
- EXPECT_TRUE(
- getMinSupportedRefreshRate(*refreshRateConfigs).getFps().equalsWithMargin(Fps(60.0)));
-}
-
} // namespace
} // namespace scheduler
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index e51db84..1f5fec0 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -62,7 +62,8 @@
.setGroup(0)
.build();
- scheduler::RefreshRateConfigs mConfigs{{mode60}, mode60->getId()};
+ std::shared_ptr<scheduler::RefreshRateConfigs> mConfigs =
+ std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60}, mode60->getId());
mock::SchedulerCallback mSchedulerCallback;
@@ -182,7 +183,9 @@
sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger());
ASSERT_EQ(static_cast<size_t>(1), mScheduler->layerHistorySize());
- mConfigs.updateDisplayModes({mode60, mode120}, /* activeMode */ mode60->getId());
+ mScheduler->setRefreshRateConfigs(
+ std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60, mode120},
+ mode60->getId()));
ASSERT_EQ(static_cast<size_t>(0), mScheduler->getNumActiveLayers());
mScheduler->recordLayerHistory(layer.get(), 0, LayerHistory::LayerUpdateType::Buffer);
@@ -225,7 +228,9 @@
}
TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
- mConfigs.updateDisplayModes({mode60, mode120}, /* activeMode */ mode60->getId());
+ mScheduler->setRefreshRateConfigs(
+ std::make_shared<scheduler::RefreshRateConfigs>(DisplayModes{mode60, mode120},
+ mode60->getId()));
sp<mock::MockLayer> layer = sp<mock::MockLayer>::make(mFlinger.flinger());
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 1ed52ea..8e7554b 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -479,7 +479,9 @@
->record(child.get(), 0, 0, LayerHistory::LayerUpdateType::Buffer);
const auto layerHistorySummary =
- mFlinger.mutableScheduler().mutableLayerHistory()->summarize(0);
+ mFlinger.mutableScheduler()
+ .mutableLayerHistory()
+ ->summarize(*mFlinger.mutableScheduler().refreshRateConfigs(), 0);
ASSERT_EQ(2u, layerHistorySummary.size());
EXPECT_TRUE(FRAME_RATE_VOTE1.rate.equalsWithMargin(layerHistorySummary[0].desiredRefreshRate));
EXPECT_TRUE(FRAME_RATE_VOTE1.rate.equalsWithMargin(layerHistorySummary[1].desiredRefreshRate));
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 41fd6e3..3b129d5 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -32,15 +32,18 @@
class TestableScheduler : public Scheduler {
public:
- TestableScheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
+ TestableScheduler(const std::shared_ptr<scheduler::RefreshRateConfigs>& refreshRateConfigs,
+ ISchedulerCallback& callback)
: TestableScheduler(std::make_unique<mock::VsyncController>(),
- std::make_unique<mock::VSyncTracker>(), configs, callback) {}
+ std::make_unique<mock::VSyncTracker>(), refreshRateConfigs,
+ callback) {}
TestableScheduler(std::unique_ptr<scheduler::VsyncController> vsyncController,
std::unique_ptr<scheduler::VSyncTracker> vsyncTracker,
- const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
- : Scheduler({std::move(vsyncController), std::move(vsyncTracker), nullptr}, configs,
- callback, createLayerHistory(configs),
+ const std::shared_ptr<scheduler::RefreshRateConfigs>& refreshRateConfigs,
+ ISchedulerCallback& callback)
+ : Scheduler({std::move(vsyncController), std::move(vsyncTracker), nullptr},
+ refreshRateConfigs, callback, createLayerHistory(),
{.supportKernelTimer = false, .useContentDetection = true}) {}
// Used to inject mock event thread.
@@ -64,6 +67,8 @@
return mutableLayerHistory()->mLayerInfos.size();
}
+ auto refreshRateConfigs() { return holdRefreshRateConfigs(); }
+
size_t getNumActiveLayers() NO_THREAD_SAFETY_ANALYSIS {
if (!mLayerHistory) return 0;
return mutableLayerHistory()->mActiveLayersEnd;
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 7f6e05e..0dc5b4f 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -82,8 +82,8 @@
return std::make_unique<scheduler::FakePhaseOffsets>();
}
- std::unique_ptr<Scheduler> createScheduler(const scheduler::RefreshRateConfigs&,
- ISchedulerCallback&) override {
+ std::unique_ptr<Scheduler> createScheduler(
+ const std::shared_ptr<scheduler::RefreshRateConfigs>&, ISchedulerCallback&) override {
return nullptr;
}
@@ -222,18 +222,16 @@
}
const auto currMode = DisplayModeId(0);
- mFlinger->mRefreshRateConfigs =
- std::make_unique<scheduler::RefreshRateConfigs>(modes, currMode);
- const auto currFps =
- mFlinger->mRefreshRateConfigs->getRefreshRateFromModeId(currMode).getFps();
+ mRefreshRateConfigs = std::make_shared<scheduler::RefreshRateConfigs>(modes, currMode);
+ const auto currFps = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+ mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);
+ mFlinger->mVsyncModulator.emplace(mFlinger->mVsyncConfiguration->getCurrentConfigs());
mFlinger->mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
/*powerMode=*/hal::PowerMode::OFF);
- mFlinger->mVsyncConfiguration = mFactory.createVsyncConfiguration(currFps);
- mFlinger->mVsyncModulator.emplace(mFlinger->mVsyncConfiguration->getCurrentConfigs());
mScheduler = new TestableScheduler(std::move(vsyncController), std::move(vsyncTracker),
- *mFlinger->mRefreshRateConfigs, *(callback ?: this));
+ mRefreshRateConfigs, *(callback ?: this));
mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread));
mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread));
@@ -653,6 +651,7 @@
DisplayModes modes{activeMode};
mCreationArgs.supportedModes = modes;
+ mCreationArgs.refreshRateConfigs = flinger.mRefreshRateConfigs;
}
sp<IBinder> token() const { return mDisplayToken; }
@@ -769,6 +768,7 @@
surfaceflinger::test::Factory mFactory;
sp<SurfaceFlinger> mFlinger = new SurfaceFlinger(mFactory, SurfaceFlinger::SkipInitialization);
TestableScheduler* mScheduler = nullptr;
+ std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs;
};
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 7c431a0..1a50427 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -74,6 +74,7 @@
EXPECT_CALL(*mVSyncTracker, currentPeriod())
.WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
+ mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>());
mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),
std::move(eventThread), std::move(sfEventThread));