Merge "InputDevice: remove touchpad gestures library flag" 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/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 97279c3..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,
@@ -861,7 +862,7 @@
// interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
// vote we should not change it if we get a touch event. Only apply touch boost if it will
// actually increase the refresh rate over the normal selection.
- const bool touchBoostForExplicitExact = [&] {
+ const auto isTouchBoostForExplicitExact = [&]() -> bool {
if (supportsAppFrameRateOverrideByContent()) {
// Enable touch boost if there are other layers besides exact
return explicitExact + noVoteLayers + explicitGteLayers != layers.size();
@@ -869,13 +870,11 @@
// Enable touch boost if there are no exact layers
return explicitExact == 0;
}
- }();
+ };
- const bool touchBoostForCategory =
- explicitCategoryVoteLayers + noVoteLayers + explicitGteLayers != layers.size();
-
- const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
- using fps_approx_ops::operator<;
+ const auto isTouchBoostForCategory = [&]() -> bool {
+ return explicitCategoryVoteLayers + noVoteLayers + explicitGteLayers != layers.size();
+ };
// A method for UI Toolkit to send the touch signal via "HighHint" category vote,
// which will touch boost when there are no ExplicitDefault layer votes. This is an
@@ -883,13 +882,17 @@
// compatibility to limit the frame rate, which should not have touch boost.
const bool hasInteraction = signals.touch || interactiveLayers > 0;
- if (hasInteraction && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
- touchBoostForCategory &&
- scores.front().frameRateMode.fps < touchRefreshRates.front().frameRateMode.fps) {
- ALOGV("Touch Boost");
- ATRACE_FORMAT_INSTANT("%s (Touch Boost [late])",
- to_string(touchRefreshRates.front().frameRateMode.fps).c_str());
- return {touchRefreshRates, GlobalSignals{.touch = true}};
+ if (hasInteraction && explicitDefaultVoteLayers == 0 && isTouchBoostForExplicitExact() &&
+ isTouchBoostForCategory()) {
+ const auto touchRefreshRates = rankFrameRates(anchorGroup, RefreshRateOrder::Descending);
+ using fps_approx_ops::operator<;
+
+ if (scores.front().frameRateMode.fps < touchRefreshRates.front().frameRateMode.fps) {
+ ALOGV("Touch Boost");
+ ATRACE_FORMAT_INSTANT("%s (Touch Boost [late])",
+ to_string(touchRefreshRates.front().frameRateMode.fps).c_str());
+ return {touchRefreshRates, GlobalSignals{.touch = true}};
+ }
}
// If we never scored any layers, and we don't favor high refresh rates, prefer to stay with the
@@ -903,8 +906,8 @@
return {ascendingWithPreferred, kNoSignals};
}
- ALOGV("%s (scored))", to_string(ranking.front().frameRateMode.fps).c_str());
- ATRACE_FORMAT_INSTANT("%s (scored))", to_string(ranking.front().frameRateMode.fps).c_str());
+ ALOGV("%s (scored)", to_string(ranking.front().frameRateMode.fps).c_str());
+ ATRACE_FORMAT_INSTANT("%s (scored)", to_string(ranking.front().frameRateMode.fps).c_str());
return {ranking, kNoSignals};
}
@@ -1253,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()) {
@@ -1383,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();
@@ -1587,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/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index 186a2d6..9b8f310 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -217,6 +217,11 @@
mMoreSamplesNeeded = mTracker.needsMoreSamples();
}
+ if (mExternalIgnoreFences) {
+ // keep HWVSync on as long as we ignore present fences.
+ mMoreSamplesNeeded = true;
+ }
+
if (!mMoreSamplesNeeded) {
setIgnorePresentFencesInternal(false);
}
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());
diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
index 8d9623d..e3aa4ef 100644
--- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
@@ -195,9 +195,7 @@
TEST_F(VSyncReactorTest, ignoresProperlyAfterAPeriodConfirmation) {
bool periodFlushed = true;
- EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
- mReactor.setIgnorePresentFences(true);
-
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(3);
nsecs_t const newPeriod = 5000;
mReactor.onDisplayModeChanged(displayMode(newPeriod), false);
@@ -207,7 +205,7 @@
EXPECT_FALSE(mReactor.addHwVsyncTimestamp(newPeriod, std::nullopt, &periodFlushed));
EXPECT_TRUE(periodFlushed);
- EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
+ EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
}
TEST_F(VSyncReactorTest, setPeriodCalledOnceConfirmedChange) {
@@ -463,8 +461,7 @@
TEST_F(VSyncReactorTest, periodChangeWithGivenVsyncPeriod) {
bool periodFlushed = true;
- EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
- mReactor.setIgnorePresentFences(true);
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(3);
nsecs_t const newPeriod = 5000;
mReactor.onDisplayModeChanged(displayMode(newPeriod), false);
@@ -476,7 +473,7 @@
EXPECT_FALSE(mReactor.addHwVsyncTimestamp(newPeriod, newPeriod, &periodFlushed));
EXPECT_TRUE(periodFlushed);
- EXPECT_TRUE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
+ EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
}
TEST_F(VSyncReactorTest, periodIsMeasuredIfIgnoringComposer) {
@@ -486,8 +483,7 @@
*mMockTracker, kPendingLimit, true /* supportKernelIdleTimer */);
bool periodFlushed = true;
- EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(4);
- idleReactor.setIgnorePresentFences(true);
+ EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(5);
// First, set the same period, which should only be confirmed when we receive two
// matching callbacks
@@ -512,7 +508,7 @@
EXPECT_FALSE(idleReactor.addHwVsyncTimestamp(20000, 5000, &periodFlushed));
EXPECT_TRUE(periodFlushed);
- EXPECT_TRUE(idleReactor.addPresentFence(generateSignalledFenceWithTime(0)));
+ EXPECT_FALSE(idleReactor.addPresentFence(generateSignalledFenceWithTime(0)));
}
} // namespace android::scheduler