Merge "SF: keep a reference vsync point before clearing timestamps" into main
diff --git a/libs/binder/IBatteryStats.cpp b/libs/binder/IBatteryStats.cpp
index 69b11c0..7b58046 100644
--- a/libs/binder/IBatteryStats.cpp
+++ b/libs/binder/IBatteryStats.cpp
@@ -66,14 +66,14 @@
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
- remote()->transact(NOTE_START_AUDIO_TRANSACTION, data, &reply);
+ remote()->transact(NOTE_START_AUDIO_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual void noteStopAudio(int uid) {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
- remote()->transact(NOTE_STOP_AUDIO_TRANSACTION, data, &reply);
+ remote()->transact(NOTE_STOP_AUDIO_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual void noteResetVideo() {
@@ -85,7 +85,7 @@
virtual void noteResetAudio() {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
- remote()->transact(NOTE_RESET_AUDIO_TRANSACTION, data, &reply);
+ remote()->transact(NOTE_RESET_AUDIO_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
}
virtual void noteFlashlightOn(int uid) {
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.cpp b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
index e76a4c3..aa18713 100644
--- a/libs/renderengine/skia/GaneshVkRenderEngine.cpp
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.cpp
@@ -23,6 +23,7 @@
#include <log/log_main.h>
#include <sync/sync.h>
+#include <utils/Trace.h>
namespace android::renderengine::skia {
@@ -33,6 +34,12 @@
info->unref();
}
+std::unique_ptr<SkiaGpuContext> GaneshVkRenderEngine::createContext(
+ VulkanInterface& vulkanInterface) {
+ return SkiaGpuContext::MakeVulkan_Ganesh(vulkanInterface.getGaneshBackendContext(),
+ mSkSLCacheMonitor);
+}
+
void GaneshVkRenderEngine::waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) {
if (fenceFd.get() < 0) return;
@@ -51,11 +58,18 @@
context->grDirectContext()->wait(1, &beSemaphore, kDeleteAfterWait);
}
-base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context) {
+base::unique_fd GaneshVkRenderEngine::flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) {
sk_sp<GrDirectContext> grContext = context->grDirectContext();
+ {
+ ATRACE_NAME("flush surface");
+ // TODO: Investigate feasibility of combining this "surface flush" into the "context flush"
+ // below.
+ context->grDirectContext()->flush(dstSurface.get());
+ }
+
VulkanInterface& vi = getVulkanInterface(isProtected());
VkSemaphore semaphore = vi.createExportableSemaphore();
-
GrBackendSemaphore backendSemaphore = GrBackendSemaphores::MakeVk(semaphore);
GrFlushInfo flushInfo;
diff --git a/libs/renderengine/skia/GaneshVkRenderEngine.h b/libs/renderengine/skia/GaneshVkRenderEngine.h
index 90e2487..5940d04 100644
--- a/libs/renderengine/skia/GaneshVkRenderEngine.h
+++ b/libs/renderengine/skia/GaneshVkRenderEngine.h
@@ -27,8 +27,9 @@
protected:
GaneshVkRenderEngine(const RenderEngineCreationArgs& args) : SkiaVkRenderEngine(args) {}
+ std::unique_ptr<SkiaGpuContext> createContext(VulkanInterface& vulkanInterface) override;
void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
- base::unique_fd flushAndSubmit(SkiaGpuContext* context) override;
+ base::unique_fd flushAndSubmit(SkiaGpuContext* context, sk_sp<SkSurface> dstSurface) override;
};
} // namespace android::renderengine::skia
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index f10c98d..61369ae 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -337,8 +337,14 @@
}
}
-base::unique_fd SkiaGLRenderEngine::flushAndSubmit(SkiaGpuContext* context) {
- base::unique_fd drawFence = flush();
+base::unique_fd SkiaGLRenderEngine::flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) {
+ sk_sp<GrDirectContext> grContext = context->grDirectContext();
+ {
+ ATRACE_NAME("flush surface");
+ grContext->flush(dstSurface.get());
+ }
+ base::unique_fd drawFence = flushGL();
bool requireSync = drawFence.get() < 0;
if (requireSync) {
@@ -346,8 +352,7 @@
} else {
ATRACE_BEGIN("Submit(sync=false)");
}
- bool success =
- context->grDirectContext()->submit(requireSync ? GrSyncCpu::kYes : GrSyncCpu::kNo);
+ bool success = grContext->submit(requireSync ? GrSyncCpu::kYes : GrSyncCpu::kNo);
ATRACE_END();
if (!success) {
ALOGE("Failed to flush RenderEngine commands");
@@ -394,7 +399,7 @@
return true;
}
-base::unique_fd SkiaGLRenderEngine::flush() {
+base::unique_fd SkiaGLRenderEngine::flushGL() {
ATRACE_CALL();
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 2e22478..bd177e6 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -63,7 +63,7 @@
bool supportsProtectedContentImpl() const override;
bool useProtectedContextImpl(GrProtected isProtected) override;
void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override;
- base::unique_fd flushAndSubmit(SkiaGpuContext* context) override;
+ base::unique_fd flushAndSubmit(SkiaGpuContext* context, sk_sp<SkSurface> dstSurface) override;
void appendBackendSpecificInfoToDump(std::string& result) override;
private:
@@ -71,7 +71,7 @@
EGLSurface placeholder, EGLContext protectedContext,
EGLSurface protectedPlaceholder);
bool waitGpuFence(base::borrowed_fd fenceFd);
- base::unique_fd flush();
+ base::unique_fd flushGL();
static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
EGLContext shareContext,
diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp
index c12c119..f548a52 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaRenderEngine.cpp
@@ -90,7 +90,7 @@
// Debugging settings
static const bool kPrintLayerSettings = false;
-static const bool kFlushAfterEveryLayer = kPrintLayerSettings;
+static const bool kGaneshFlushAfterEveryLayer = kPrintLayerSettings;
static constexpr bool kEnableLayerBrightening = true;
} // namespace
@@ -1122,21 +1122,21 @@
} else {
canvas->drawRect(bounds.rect(), paint);
}
- if (kFlushAfterEveryLayer) {
+ if (kGaneshFlushAfterEveryLayer) {
ATRACE_NAME("flush surface");
+ // No-op in Graphite. If "flushing" Skia's drawing commands after each layer is desired
+ // in Graphite, then a graphite::Recording would need to be snapped and tracked for each
+ // layer, which is likely possible but adds non-trivial complexity (in both bookkeeping
+ // and refactoring).
skgpu::ganesh::Flush(activeSurface);
}
}
surfaceAutoSaveRestore.restore();
mCapture->endCapture();
- {
- ATRACE_NAME("flush surface");
- LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface);
- skgpu::ganesh::Flush(activeSurface);
- }
- auto drawFence = sp<Fence>::make(flushAndSubmit(context));
+ LOG_ALWAYS_FATAL_IF(activeSurface != dstSurface);
+ auto drawFence = sp<Fence>::make(flushAndSubmit(context, dstSurface));
if (ATRACE_ENABLED()) {
static gui::FenceMonitor sMonitor("RE Completion");
diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h
index a39adbe..d7b4910 100644
--- a/libs/renderengine/skia/SkiaRenderEngine.h
+++ b/libs/renderengine/skia/SkiaRenderEngine.h
@@ -89,7 +89,8 @@
virtual bool supportsProtectedContentImpl() const = 0;
virtual bool useProtectedContextImpl(GrProtected isProtected) = 0;
virtual void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) = 0;
- virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context) = 0;
+ virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) = 0;
virtual void appendBackendSpecificInfoToDump(std::string& result) = 0;
size_t getMaxTextureSize() const override final;
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index 473fa0a..3715859 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -112,12 +112,9 @@
sSetupVulkanInterface();
SkiaRenderEngine::Contexts contexts;
- contexts.first = SkiaGpuContext::MakeVulkan_Ganesh(sVulkanInterface.getGaneshBackendContext(),
- mSkSLCacheMonitor);
+ contexts.first = createContext(sVulkanInterface);
if (supportsProtectedContentImpl()) {
- contexts.second = SkiaGpuContext::MakeVulkan_Ganesh(sProtectedContentVulkanInterface
- .getGaneshBackendContext(),
- mSkSLCacheMonitor);
+ contexts.second = createContext(sProtectedContentVulkanInterface);
}
return contexts;
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.h b/libs/renderengine/skia/SkiaVkRenderEngine.h
index 5fd911f..371b812 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.h
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.h
@@ -71,9 +71,11 @@
};
protected:
+ virtual std::unique_ptr<SkiaGpuContext> createContext(VulkanInterface& vulkanInterface) = 0;
// Redeclare parent functions that Ganesh vs. Graphite subclasses must implement.
virtual void waitFence(SkiaGpuContext* context, base::borrowed_fd fenceFd) override = 0;
- virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context) override = 0;
+ virtual base::unique_fd flushAndSubmit(SkiaGpuContext* context,
+ sk_sp<SkSurface> dstSurface) override = 0;
SkiaVkRenderEngine(const RenderEngineCreationArgs& args);
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 4d8ffb6..782c84a 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -507,10 +507,7 @@
}
// Touchscreens and touchpad devices.
- static const bool ENABLE_TOUCHPAD_GESTURES_LIBRARY =
- sysprop::InputProperties::enable_touchpad_gestures_library().value_or(true);
- if (ENABLE_TOUCHPAD_GESTURES_LIBRARY && classes.test(InputDeviceClass::TOUCHPAD) &&
- classes.test(InputDeviceClass::TOUCH_MT)) {
+ if (classes.test(InputDeviceClass::TOUCHPAD) && classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(createInputMapper<TouchpadInputMapper>(contextPtr, readerConfig));
} else if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(createInputMapper<MultiTouchInputMapper>(contextPtr, readerConfig));
diff --git a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
index 99f9e24..721cdfd 100644
--- a/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchpadInputMapper.cpp
@@ -198,6 +198,7 @@
}
void produceAtomsLocked(AStatsEventList& outEventList) const REQUIRES(mLock) {
+ ALOGI("Producing touchpad usage atoms for %zu counters", mCounters.size());
for (auto& [id, counters] : mCounters) {
auto [busId, vendorId, productId, versionId] = id;
addAStatsEvent(&outEventList, android::util::TOUCHPAD_USAGE, vendorId, productId,
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index b4789f1..6be245e 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3010,7 +3010,6 @@
EXPECT_CALL(mOutput, getCompositionEngine()).WillRepeatedly(ReturnRef(mCompositionEngine));
EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
EXPECT_CALL(mOutput, isPowerHintSessionEnabled()).WillRepeatedly(Return(true));
- SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, false);
}
StrictMock<OutputPartialMock> mOutput;
@@ -3028,6 +3027,7 @@
}
TEST_F(OutputFinishFrameTest, takesEarlyOutifComposeSurfacesReturnsNoFence) {
+ SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, true);
mOutput.mState.isEnabled = true;
EXPECT_CALL(mOutput, updateProtectedContentState());
EXPECT_CALL(mOutput, dequeueRenderBuffer(_, _)).WillOnce(Return(true));
@@ -3037,7 +3037,8 @@
mOutput.finishFrame(std::move(result));
}
-TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
+TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFenceWithAdpfGpuOff) {
+ SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, false);
mOutput.mState.isEnabled = true;
InSequence seq;
@@ -3052,7 +3053,7 @@
mOutput.finishFrame(std::move(result));
}
-TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFenceWithAdpfGpuOn) {
+TEST_F(OutputFinishFrameTest, queuesBufferIfComposeSurfacesReturnsAFence) {
SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, true);
mOutput.mState.isEnabled = true;
@@ -3070,6 +3071,7 @@
TEST_F(OutputFinishFrameTest, queuesBufferWithHdrSdrRatio) {
SET_FLAG_FOR_TEST(flags::fp16_client_target, true);
+ SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, true);
mOutput.mState.isEnabled = true;
InSequence seq;
@@ -3089,7 +3091,7 @@
.WillOnce(DoAll(SetArgPointee<1>(texture), Return(true)));
EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _, _))
.WillOnce(Return(ByMove(base::unique_fd())));
- EXPECT_CALL(mOutput, setHintSessionGpuFence(_));
+ EXPECT_CALL(mOutput, setHintSessionGpuFence(_)).Times(0);
EXPECT_CALL(*mRenderSurface, queueBuffer(_, 2.f));
impl::GpuCompositionResult result;
@@ -3097,10 +3099,11 @@
}
TEST_F(OutputFinishFrameTest, predictionSucceeded) {
+ SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, true);
mOutput.mState.isEnabled = true;
mOutput.mState.strategyPrediction = CompositionStrategyPredictionState::SUCCESS;
InSequence seq;
- EXPECT_CALL(mOutput, setHintSessionGpuFence(_));
+ EXPECT_CALL(mOutput, setHintSessionGpuFence(_)).Times(0);
EXPECT_CALL(*mRenderSurface, queueBuffer(_, 1.f));
impl::GpuCompositionResult result;
@@ -3108,6 +3111,7 @@
}
TEST_F(OutputFinishFrameTest, predictionFailedAndBufferIsReused) {
+ SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, true);
mOutput.mState.isEnabled = true;
mOutput.mState.strategyPrediction = CompositionStrategyPredictionState::FAIL;
@@ -3123,7 +3127,7 @@
composeSurfaces(RegionEq(Region::INVALID_REGION), result.buffer,
Eq(ByRef(result.fence))))
.WillOnce(Return(ByMove(base::unique_fd())));
- EXPECT_CALL(mOutput, setHintSessionGpuFence(_));
+ EXPECT_CALL(mOutput, setHintSessionGpuFence(_)).Times(0);
EXPECT_CALL(*mRenderSurface, queueBuffer(_, 1.f));
mOutput.finishFrame(std::move(result));
}
@@ -3484,7 +3488,6 @@
EXPECT_CALL(*mDisplayColorProfile, getHdrCapabilities())
.WillRepeatedly(ReturnRef(kHdrCapabilities));
EXPECT_CALL(mOutput, isPowerHintSessionEnabled()).WillRepeatedly(Return(true));
- SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, false);
}
struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
@@ -3757,7 +3760,8 @@
EXPECT_TRUE(mOutput.mState.reusedClientComposition);
}
-TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) {
+TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChangesWithAdpfGpuOff) {
+ SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, false);
LayerFE::LayerSettings r1;
LayerFE::LayerSettings r2;
@@ -3800,7 +3804,7 @@
EXPECT_FALSE(mOutput.mState.reusedClientComposition);
}
-TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChangesWithAdpfGpuOn) {
+TEST_F(OutputComposeSurfacesTest, clientCompositionIfBufferChanges) {
SET_FLAG_FOR_TEST(flags::adpf_gpu_sf, true);
LayerFE::LayerSettings r1;
LayerFE::LayerSettings r2;
diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
index cd45bfd..7e61dc0 100644
--- a/services/surfaceflinger/Scheduler/OneShotTimer.cpp
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
@@ -115,9 +115,24 @@
break;
}
- auto triggerTime = mClock->now() + mInterval;
+ auto triggerTime = mClock->now() + mInterval.load();
state = TimerState::WAITING;
while (true) {
+ if (mPaused) {
+ mWaiting = true;
+ int result = sem_wait(&mSemaphore);
+ if (result && errno != EINTR) {
+ std::stringstream ss;
+ ss << "sem_wait failed (" << errno << ")";
+ LOG_ALWAYS_FATAL("%s", ss.str().c_str());
+ }
+
+ mWaiting = false;
+ state = checkForResetAndStop(state);
+ if (state == TimerState::STOPPED) {
+ break;
+ }
+ }
// Wait until triggerTime time to check if we need to reset or drop into the idle state.
if (const auto triggerInterval = triggerTime - mClock->now(); triggerInterval > 0ns) {
mWaiting = true;
@@ -137,14 +152,14 @@
break;
}
- if (state == TimerState::WAITING && (triggerTime - mClock->now()) <= 0ns) {
+ if (!mPaused && state == TimerState::WAITING && (triggerTime - mClock->now()) <= 0ns) {
triggerTimeout = true;
state = TimerState::IDLE;
break;
}
if (state == TimerState::RESET) {
- triggerTime = mLastResetTime.load() + mInterval;
+ triggerTime = mLastResetTime.load() + mInterval.load();
state = TimerState::WAITING;
}
}
@@ -179,5 +194,15 @@
}
}
+void OneShotTimer::pause() {
+ mPaused = true;
+}
+
+void OneShotTimer::resume() {
+ if (mPaused.exchange(false)) {
+ LOG_ALWAYS_FATAL_IF(sem_post(&mSemaphore), "sem_post failed");
+ }
+}
+
} // namespace scheduler
} // namespace android
diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h
index 02e8719..4e1e2ee 100644
--- a/services/surfaceflinger/Scheduler/OneShotTimer.h
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.h
@@ -43,7 +43,8 @@
std::unique_ptr<android::Clock> clock = std::make_unique<SteadyClock>());
~OneShotTimer();
- Duration interval() const { return mInterval; }
+ Duration interval() const { return mInterval.load(); }
+ void setInterval(Interval value) { mInterval = value; }
// Initializes and turns on the idle timer.
void start();
@@ -51,6 +52,10 @@
void stop();
// Resets the wakeup time and fires the reset callback.
void reset();
+ // Pauses the timer. reset calls will get ignored.
+ void pause();
+ // Resumes the timer.
+ void resume();
private:
// Enum to track in what state is the timer.
@@ -91,7 +96,7 @@
std::string mName;
// Interval after which timer expires.
- const Interval mInterval;
+ std::atomic<Interval> mInterval;
// Callback that happens when timer resets.
const ResetCallback mResetCallback;
@@ -105,6 +110,7 @@
std::atomic<bool> mResetTriggered = false;
std::atomic<bool> mStopTriggered = false;
std::atomic<bool> mWaiting = false;
+ std::atomic<bool> mPaused = false;
std::atomic<std::chrono::steady_clock::time_point> mLastResetTime;
};
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
index eac527b..a37fb96 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.cpp
@@ -285,11 +285,12 @@
std::string RefreshRateSelector::Policy::toString() const {
return base::StringPrintf("{defaultModeId=%d, allowGroupSwitching=%s"
- ", primaryRanges=%s, appRequestRanges=%s}",
+ ", primaryRanges=%s, appRequestRanges=%s idleScreenConfig=%s}",
ftl::to_underlying(defaultMode),
allowGroupSwitching ? "true" : "false",
- to_string(primaryRanges).c_str(),
- to_string(appRequestRanges).c_str());
+ to_string(primaryRanges).c_str(), to_string(appRequestRanges).c_str(),
+ idleScreenConfigOpt ? idleScreenConfigOpt->toString().c_str()
+ : "nullptr");
}
std::pair<nsecs_t, nsecs_t> RefreshRateSelector::getDisplayFrames(nsecs_t layerPeriod,
@@ -1255,14 +1256,14 @@
RefreshRateSelector::RefreshRateSelector(DisplayModes modes, DisplayModeId activeModeId,
Config config)
: mKnownFrameRates(constructKnownFrameRates(modes)), mConfig(config) {
- initializeIdleTimer();
+ initializeIdleTimer(mConfig.legacyIdleTimerTimeout);
FTL_FAKE_GUARD(kMainThreadContext, updateDisplayModes(std::move(modes), activeModeId));
}
-void RefreshRateSelector::initializeIdleTimer() {
- if (mConfig.idleTimerTimeout > 0ms) {
+void RefreshRateSelector::initializeIdleTimer(std::chrono::milliseconds timeout) {
+ if (timeout > 0ms) {
mIdleTimer.emplace(
- "IdleTimer", mConfig.idleTimerTimeout,
+ "IdleTimer", timeout,
[this] {
std::scoped_lock lock(mIdleTimerCallbacksMutex);
if (const auto callbacks = getIdleTimerCallbacks()) {
@@ -1385,9 +1386,40 @@
mGetRankedFrameRatesCache.reset();
- if (*getCurrentPolicyLocked() == oldPolicy) {
+ const auto& idleScreenConfigOpt = getCurrentPolicyLocked()->idleScreenConfigOpt;
+ if (idleScreenConfigOpt != oldPolicy.idleScreenConfigOpt) {
+ if (!idleScreenConfigOpt.has_value()) {
+ // fallback to legacy timer if existed, otherwise pause the old timer
+ LOG_ALWAYS_FATAL_IF(!mIdleTimer);
+ if (mConfig.legacyIdleTimerTimeout > 0ms) {
+ mIdleTimer->setInterval(mConfig.legacyIdleTimerTimeout);
+ mIdleTimer->resume();
+ } else {
+ mIdleTimer->pause();
+ }
+ } else if (idleScreenConfigOpt->timeoutMillis > 0) {
+ // create a new timer or reconfigure
+ const auto timeout = std::chrono::milliseconds{idleScreenConfigOpt->timeoutMillis};
+ if (!mIdleTimer) {
+ initializeIdleTimer(timeout);
+ if (mIdleTimerStarted) {
+ mIdleTimer->start();
+ }
+ } else {
+ mIdleTimer->setInterval(timeout);
+ mIdleTimer->resume();
+ }
+ } else {
+ if (mIdleTimer) {
+ mIdleTimer->pause();
+ }
+ }
+ }
+
+ if (getCurrentPolicyLocked()->similarExceptIdleConfig(oldPolicy)) {
return SetPolicyResult::Unchanged;
}
+
constructAvailableRefreshRates();
displayId = getActiveModeLocked().modePtr->getPhysicalDisplayId();
@@ -1589,7 +1621,10 @@
}
std::chrono::milliseconds RefreshRateSelector::getIdleTimerTimeout() {
- return mConfig.idleTimerTimeout;
+ if (FlagManager::getInstance().idle_screen_refresh_rate_timeout() && mIdleTimer) {
+ return std::chrono::duration_cast<std::chrono::milliseconds>(mIdleTimer->interval());
+ }
+ return mConfig.legacyIdleTimerTimeout;
}
// TODO(b/293651105): Extract category FpsRange mapping to OEM-configurable config.
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
index a0e2785..4f491d9 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
@@ -67,26 +67,32 @@
FpsRanges primaryRanges;
// The app request refresh rate ranges. @see DisplayModeSpecs.aidl for details.
FpsRanges appRequestRanges;
+ // The idle timer configuration, if provided.
+ std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig> idleScreenConfigOpt;
Policy() = default;
Policy(DisplayModeId defaultMode, FpsRange range,
- bool allowGroupSwitching = kAllowGroupSwitchingDefault)
+ bool allowGroupSwitching = kAllowGroupSwitchingDefault,
+ const std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig>&
+ idleScreenConfigOpt = std::nullopt)
: Policy(defaultMode, FpsRanges{range, range}, FpsRanges{range, range},
- allowGroupSwitching) {}
+ allowGroupSwitching, idleScreenConfigOpt) {}
Policy(DisplayModeId defaultMode, FpsRanges primaryRanges, FpsRanges appRequestRanges,
- bool allowGroupSwitching = kAllowGroupSwitchingDefault)
+ bool allowGroupSwitching = kAllowGroupSwitchingDefault,
+ const std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig>&
+ idleScreenConfigOpt = std::nullopt)
: defaultMode(defaultMode),
allowGroupSwitching(allowGroupSwitching),
primaryRanges(primaryRanges),
- appRequestRanges(appRequestRanges) {}
+ appRequestRanges(appRequestRanges),
+ idleScreenConfigOpt(idleScreenConfigOpt) {}
bool operator==(const Policy& other) const {
using namespace fps_approx_ops;
- return defaultMode == other.defaultMode && primaryRanges == other.primaryRanges &&
- appRequestRanges == other.appRequestRanges &&
- allowGroupSwitching == other.allowGroupSwitching;
+ return similarExceptIdleConfig(other) &&
+ idleScreenConfigOpt == other.idleScreenConfigOpt;
}
bool operator!=(const Policy& other) const { return !(*this == other); }
@@ -95,6 +101,13 @@
return isApproxEqual(primaryRanges.physical.min, primaryRanges.physical.max);
}
+ bool similarExceptIdleConfig(const Policy& updated) const {
+ using namespace fps_approx_ops;
+ return defaultMode == updated.defaultMode && primaryRanges == updated.primaryRanges &&
+ appRequestRanges == updated.appRequestRanges &&
+ allowGroupSwitching == updated.allowGroupSwitching;
+ }
+
std::string toString() const;
};
@@ -291,7 +304,7 @@
int frameRateMultipleThreshold = 0;
// The Idle Timer timeout. 0 timeout means no idle timer.
- std::chrono::milliseconds idleTimerTimeout = 0ms;
+ std::chrono::milliseconds legacyIdleTimerTimeout = 0ms;
// The controller representing how the kernel idle timer will be configured
// either on the HWC api or sysprop.
@@ -302,7 +315,7 @@
DisplayModes, DisplayModeId activeModeId,
Config config = {.enableFrameRateOverride = Config::FrameRateOverride::Disabled,
.frameRateMultipleThreshold = 0,
- .idleTimerTimeout = 0ms,
+ .legacyIdleTimerTimeout = 0ms,
.kernelIdleTimerController = {}});
RefreshRateSelector(const RefreshRateSelector&) = delete;
@@ -383,12 +396,14 @@
}
void startIdleTimer() {
+ mIdleTimerStarted = true;
if (mIdleTimer) {
mIdleTimer->start();
}
}
void stopIdleTimer() {
+ mIdleTimerStarted = false;
if (mIdleTimer) {
mIdleTimer->stop();
}
@@ -481,7 +496,7 @@
void updateDisplayModes(DisplayModes, DisplayModeId activeModeId) EXCLUDES(mLock)
REQUIRES(kMainThreadContext);
- void initializeIdleTimer();
+ void initializeIdleTimer(std::chrono::milliseconds timeout);
std::optional<IdleTimerCallbacks::Callbacks> getIdleTimerCallbacks() const
REQUIRES(mIdleTimerCallbacksMutex) {
@@ -562,6 +577,7 @@
std::optional<IdleTimerCallbacks> mIdleTimerCallbacks GUARDED_BY(mIdleTimerCallbacksMutex);
// Used to detect (lack of) frame activity.
ftl::Optional<scheduler::OneShotTimer> mIdleTimer;
+ std::atomic<bool> mIdleTimerStarted = false;
};
} // namespace android::scheduler
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1265540..734058a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3588,7 +3588,7 @@
{.enableFrameRateOverride = enableFrameRateOverride,
.frameRateMultipleThreshold =
base::GetIntProperty("debug.sf.frame_rate_multiple_threshold"s, 0),
- .idleTimerTimeout = idleTimerTimeoutMs,
+ .legacyIdleTimerTimeout = idleTimerTimeoutMs,
.kernelIdleTimerController = kernelIdleTimerController};
creationArgs.refreshRateSelector =
@@ -8639,8 +8639,13 @@
return INVALID_OPERATION;
} else {
using Policy = scheduler::RefreshRateSelector::DisplayManagerPolicy;
+ const auto idleScreenConfigOpt =
+ FlagManager::getInstance().idle_screen_refresh_rate_timeout()
+ ? specs.idleScreenRefreshRateConfig
+ : std::nullopt;
const Policy policy{DisplayModeId(specs.defaultMode), translate(specs.primaryRanges),
- translate(specs.appRequestRanges), specs.allowGroupSwitching};
+ translate(specs.appRequestRanges), specs.allowGroupSwitching,
+ idleScreenConfigOpt};
return setDesiredDisplayModeSpecsInternal(display, policy);
}
diff --git a/services/surfaceflinger/common/Android.bp b/services/surfaceflinger/common/Android.bp
index 4a89dd0..6b971a7 100644
--- a/services/surfaceflinger/common/Android.bp
+++ b/services/surfaceflinger/common/Android.bp
@@ -36,6 +36,7 @@
static_libs: [
"libsurfaceflingerflags",
"android.os.flags-aconfig-cc",
+ "android.server.display.flags-aconfig-cc",
],
}
@@ -47,6 +48,7 @@
static_libs: [
"libsurfaceflingerflags_test",
"android.os.flags-aconfig-cc-test",
+ "android.server.display.flags-aconfig-cc",
],
}
@@ -59,6 +61,7 @@
"libsurfaceflinger_common",
"libsurfaceflingerflags",
"android.os.flags-aconfig-cc",
+ "android.server.display.flags-aconfig-cc",
],
}
@@ -71,5 +74,6 @@
"libsurfaceflinger_common_test",
"libsurfaceflingerflags_test",
"android.os.flags-aconfig-cc-test",
+ "android.server.display.flags-aconfig-cc",
],
}
diff --git a/services/surfaceflinger/common/FlagManager.cpp b/services/surfaceflinger/common/FlagManager.cpp
index 4b34a55..6507aba 100644
--- a/services/surfaceflinger/common/FlagManager.cpp
+++ b/services/surfaceflinger/common/FlagManager.cpp
@@ -28,6 +28,7 @@
#include <android_os.h>
#include <com_android_graphics_surfaceflinger_flags.h>
+#include <com_android_server_display_feature_flags.h>
namespace android {
using namespace com::android::graphics::surfaceflinger;
@@ -137,6 +138,7 @@
DUMP_READ_ONLY_FLAG(dont_skip_on_early_ro);
DUMP_READ_ONLY_FLAG(protected_if_client);
DUMP_READ_ONLY_FLAG(ce_fence_promise);
+ DUMP_READ_ONLY_FLAG(idle_screen_refresh_rate_timeout);
#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
#undef DUMP_FLAG_INTERVAL
@@ -190,6 +192,9 @@
#define FLAG_MANAGER_SERVER_FLAG_IMPORTED(name, syspropOverride, owner) \
FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, true, owner)
+#define FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(name, syspropOverride, owner) \
+ FLAG_MANAGER_FLAG_INTERNAL(name, syspropOverride, false, owner)
+
/// Legacy server flags ///
FLAG_MANAGER_LEGACY_SERVER_FLAG(test_flag, "", "")
FLAG_MANAGER_LEGACY_SERVER_FLAG(use_adpf_cpu_hint, "debug.sf.enable_adpf_cpu_hint",
@@ -230,4 +235,8 @@
/// Trunk stable server flags from outside SurfaceFlinger ///
FLAG_MANAGER_SERVER_FLAG_IMPORTED(adpf_use_fmq_channel, "", android::os)
+/// Trunk stable readonly flags from outside SurfaceFlinger ///
+FLAG_MANAGER_READ_ONLY_FLAG_IMPORTED(idle_screen_refresh_rate_timeout, "",
+ com::android::server::display::feature::flags)
+
} // namespace android
diff --git a/services/surfaceflinger/common/include/common/FlagManager.h b/services/surfaceflinger/common/include/common/FlagManager.h
index 320e34b..964943c 100644
--- a/services/surfaceflinger/common/include/common/FlagManager.h
+++ b/services/surfaceflinger/common/include/common/FlagManager.h
@@ -76,6 +76,7 @@
bool dont_skip_on_early_ro() const;
bool protected_if_client() const;
bool ce_fence_promise() const;
+ bool idle_screen_refresh_rate_timeout() const;
protected:
// overridden for unit tests
diff --git a/services/surfaceflinger/common/include/common/test/FlagUtils.h b/services/surfaceflinger/common/include/common/test/FlagUtils.h
index d61fcb5..5317cbb 100644
--- a/services/surfaceflinger/common/include/common/test/FlagUtils.h
+++ b/services/surfaceflinger/common/include/common/test/FlagUtils.h
@@ -18,9 +18,13 @@
#include <common/FlagManager.h>
-#define SET_FLAG_FOR_TEST(name, value) \
- TestFlagSetter _testflag_ { \
- (name), (name), (value) \
+// indirection to resolve __LINE__ in SET_FLAG_FOR_TEST, it's used to create a unique TestFlagSetter
+// setter var name everytime so multiple flags can be set in a test
+#define CONCAT_INNER(a, b) a##b
+#define CONCAT(a, b) CONCAT_INNER(a, b)
+#define SET_FLAG_FOR_TEST(name, value) \
+ TestFlagSetter CONCAT(_testFlag_, __LINE__) { \
+ (name), (name), (value) \
}
namespace android {
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
index 0ede612..cf9a7d3 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectorTest.cpp
@@ -2078,7 +2078,7 @@
constexpr std::chrono::milliseconds kIdleTimerTimeoutMs = 10ms;
auto selector = createSelector(makeModes(kMode60, kMode120), kModeId120,
Config{
- .idleTimerTimeout = kIdleTimerTimeoutMs,
+ .legacyIdleTimerTimeout = kIdleTimerTimeoutMs,
});
ASSERT_EQ(KernelIdleTimerAction::TurnOn, selector.getIdleTimerAction());
ASSERT_EQ(kIdleTimerTimeoutMs, selector.getIdleTimerTimeout());