Merge "libgui: ConsumerBase-based classes now create their own BufferQueues" into main
diff --git a/include/android/surface_control_input_receiver.h b/include/android/surface_control_input_receiver.h
index bdc5249..f0503f6 100644
--- a/include/android/surface_control_input_receiver.h
+++ b/include/android/surface_control_input_receiver.h
@@ -59,17 +59,13 @@
AInputEvent *_Nonnull keyEvent)
__INTRODUCED_IN(__ANDROID_API_V__);
-struct AInputReceiverCallbacks;
-
-struct AInputReceiver;
+typedef struct AInputReceiverCallbacks AInputReceiverCallbacks;
/**
* The InputReceiver that holds the reference to the registered input channel. This must be released
* using AInputReceiver_release
- *
- * Available since API level 35.
*/
-typedef struct AInputReceiver AInputReceiver __INTRODUCED_IN(__ANDROID_API_V__);
+typedef struct AInputReceiver AInputReceiver;
/**
* Registers an input receiver for an ASurfaceControl that will receive batched input event. For
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index b826466..ed4c47d 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -48,6 +48,7 @@
"libtonemap",
"libaidlcommonsupport",
"libprocessgroup",
+ "libprocessgroup_util",
"libcgrouprc",
"libjsoncpp",
"libcgrouprc_format",
diff --git a/services/surfaceflinger/Scheduler/RefreshRateSelector.h b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
index 998b1b8..a398c01 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateSelector.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateSelector.h
@@ -210,6 +210,8 @@
// within the timeout of DisplayPowerTimer.
bool powerOnImminent = false;
+ bool shouldEmitEvent() const { return !idle; }
+
bool operator==(GlobalSignals other) const {
return touch == other.touch && idle == other.idle &&
powerOnImminent == other.powerOnImminent;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 84584a4..6b31135 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -424,50 +424,49 @@
eventThreadFor(cycle).onHdcpLevelsChanged(displayId, connectedLevel, maxLevel);
}
-void Scheduler::onPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) {
- {
+bool Scheduler::onDisplayModeChanged(PhysicalDisplayId displayId, const FrameRateMode& mode) {
+ const bool isPacesetter =
+ FTL_FAKE_GUARD(kMainThreadContext,
+ (std::scoped_lock(mDisplayLock), displayId == mPacesetterDisplayId));
+
+ if (isPacesetter) {
std::lock_guard<std::mutex> lock(mPolicyLock);
- // Cache the last reported modes for primary display.
- mPolicy.cachedModeChangedParams = {cycle, mode};
+ mPolicy.emittedModeOpt = mode;
// Invalidate content based refresh rate selection so it could be calculated
// again for the new refresh rate.
mPolicy.contentRequirements.clear();
}
- onNonPrimaryDisplayModeChanged(cycle, mode);
-}
-void Scheduler::dispatchCachedReportedMode() {
- // Check optional fields first.
- if (!mPolicy.modeOpt) {
- ALOGW("No mode ID found, not dispatching cached mode.");
- return;
- }
- if (!mPolicy.cachedModeChangedParams) {
- ALOGW("No mode changed params found, not dispatching cached mode.");
- return;
- }
-
- // If the mode is not the current mode, this means that a
- // mode change is in progress. In that case we shouldn't dispatch an event
- // as it will be dispatched when the current mode changes.
- if (pacesetterSelectorPtr()->getActiveMode() != mPolicy.modeOpt) {
- return;
- }
-
- // If there is no change from cached mode, there is no need to dispatch an event
- if (*mPolicy.modeOpt == mPolicy.cachedModeChangedParams->mode) {
- return;
- }
-
- mPolicy.cachedModeChangedParams->mode = *mPolicy.modeOpt;
- onNonPrimaryDisplayModeChanged(mPolicy.cachedModeChangedParams->cycle,
- mPolicy.cachedModeChangedParams->mode);
-}
-
-void Scheduler::onNonPrimaryDisplayModeChanged(Cycle cycle, const FrameRateMode& mode) {
if (hasEventThreads()) {
- eventThreadFor(cycle).onModeChanged(mode);
+ eventThreadFor(Cycle::Render).onModeChanged(mode);
+ }
+
+ return isPacesetter;
+}
+
+void Scheduler::emitModeChangeIfNeeded() {
+ if (!mPolicy.modeOpt || !mPolicy.emittedModeOpt) {
+ ALOGW("No mode change to emit");
+ return;
+ }
+
+ const auto& mode = *mPolicy.modeOpt;
+
+ if (mode != pacesetterSelectorPtr()->getActiveMode()) {
+ // A mode change is pending. The event will be emitted when the mode becomes active.
+ return;
+ }
+
+ if (mode == *mPolicy.emittedModeOpt) {
+ // The event was already emitted.
+ return;
+ }
+
+ mPolicy.emittedModeOpt = mode;
+
+ if (hasEventThreads()) {
+ eventThreadFor(Cycle::Render).onModeChanged(mode);
}
}
@@ -1139,7 +1138,8 @@
for (auto& [id, choice] : modeChoices) {
modeRequests.emplace_back(
display::DisplayModeRequest{.mode = std::move(choice.mode),
- .emitEvent = !choice.consideredSignals.idle});
+ .emitEvent = choice.consideredSignals
+ .shouldEmitEvent()});
}
if (!FlagManager::getInstance().vrr_bugfix_dropped_frame()) {
@@ -1149,12 +1149,10 @@
if (mPolicy.modeOpt != modeOpt) {
mPolicy.modeOpt = modeOpt;
refreshRateChanged = true;
- } else {
- // We don't need to change the display mode, but we might need to send an event
- // about a mode change, since it was suppressed if previously considered idle.
- if (!consideredSignals.idle) {
- dispatchCachedReportedMode();
- }
+ } else if (consideredSignals.shouldEmitEvent()) {
+ // The mode did not change, but we may need to emit if DisplayModeRequest::emitEvent was
+ // previously false.
+ emitModeChangeIfNeeded();
}
}
if (refreshRateChanged) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index e1f4d20..4003d9f 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -154,8 +154,8 @@
void dispatchHotplugError(int32_t errorCode);
- void onPrimaryDisplayModeChanged(Cycle, const FrameRateMode&) EXCLUDES(mPolicyLock);
- void onNonPrimaryDisplayModeChanged(Cycle, const FrameRateMode&);
+ // Returns true if the PhysicalDisplayId is the pacesetter.
+ bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&) EXCLUDES(mPolicyLock);
void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext);
@@ -458,7 +458,7 @@
void updateAttachedChoreographersFrameRate(const surfaceflinger::frontend::RequestedLayerState&,
Fps fps) EXCLUDES(mChoreographerLock);
- void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mDisplayLock);
+ void emitModeChangeIfNeeded() REQUIRES(mPolicyLock) EXCLUDES(mDisplayLock);
// IEventThreadCallback overrides
bool throttleVsync(TimePoint, uid_t) override;
@@ -584,13 +584,8 @@
// Chosen display mode.
ftl::Optional<FrameRateMode> modeOpt;
- struct ModeChangedParams {
- Cycle cycle;
- FrameRateMode mode;
- };
-
- // Parameters for latest dispatch of mode change event.
- std::optional<ModeChangedParams> cachedModeChangedParams;
+ // Display mode of latest emitted event.
+ std::optional<FrameRateMode> emittedModeOpt;
} mPolicy GUARDED_BY(mPolicyLock);
std::mutex mChoreographerLock;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e7d802a..9633cc5 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1358,7 +1358,7 @@
}
if (emitEvent) {
- dispatchDisplayModeChangeEvent(displayId, mode);
+ mScheduler->onDisplayModeChanged(displayId, mode);
}
break;
case DesiredModeAction::None:
@@ -1455,7 +1455,7 @@
}
if (pendingModeOpt->emitEvent) {
- dispatchDisplayModeChangeEvent(displayId, activeMode);
+ mScheduler->onDisplayModeChanged(displayId, activeMode);
}
}
@@ -3589,16 +3589,6 @@
mPhysicalDisplays.erase(displayId);
}
-void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId,
- const scheduler::FrameRateMode& mode) {
- // TODO(b/255635821): Merge code paths and move to Scheduler.
- const auto onDisplayModeChanged = displayId == mActiveDisplayId
- ? &scheduler::Scheduler::onPrimaryDisplayModeChanged
- : &scheduler::Scheduler::onNonPrimaryDisplayModeChanged;
-
- ((*mScheduler).*onDisplayModeChanged)(scheduler::Cycle::Render, mode);
-}
-
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
@@ -7959,13 +7949,9 @@
const scheduler::RefreshRateSelector::Policy currentPolicy = selector.getCurrentPolicy();
ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());
- // TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
- // be depending in this callback.
- if (const auto activeMode = selector.getActiveMode(); displayId == mActiveDisplayId) {
- mScheduler->onPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode);
+ if (const bool isPacesetter =
+ mScheduler->onDisplayModeChanged(displayId, selector.getActiveMode())) {
toggleKernelIdleTimer();
- } else {
- mScheduler->onNonPrimaryDisplayModeChanged(scheduler::Cycle::Render, activeMode);
}
auto preferredModeOpt = getPreferredDisplayMode(displayId, currentPolicy.defaultMode);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9b2dea2..8b71f3b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1067,8 +1067,6 @@
const DisplayDeviceState& drawingState)
REQUIRES(mStateLock, kMainThreadContext);
- void dispatchDisplayModeChangeEvent(PhysicalDisplayId, const scheduler::FrameRateMode&);
-
/*
* VSYNC
*/
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 3df724a..dddda05 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -78,6 +78,8 @@
SchedulerTest();
+ static constexpr RefreshRateSelector::LayerRequirement kLayer = {.weight = 1.f};
+
static constexpr PhysicalDisplayId kDisplayId1 = PhysicalDisplayId::fromPort(255u);
static inline const ftl::NonNull<DisplayModePtr> kDisplay1Mode60 =
ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(0), 60_Hz));
@@ -85,6 +87,9 @@
ftl::as_non_null(createDisplayMode(kDisplayId1, DisplayModeId(1), 120_Hz));
static inline const DisplayModes kDisplay1Modes = makeModes(kDisplay1Mode60, kDisplay1Mode120);
+ static inline FrameRateMode kDisplay1Mode60_60{60_Hz, kDisplay1Mode60};
+ static inline FrameRateMode kDisplay1Mode120_120{120_Hz, kDisplay1Mode120};
+
static constexpr PhysicalDisplayId kDisplayId2 = PhysicalDisplayId::fromPort(254u);
static inline const ftl::NonNull<DisplayModePtr> kDisplay2Mode60 =
ftl::as_non_null(createDisplayMode(kDisplayId2, DisplayModeId(0), 60_Hz));
@@ -123,6 +128,7 @@
.WillRepeatedly(Return(mEventThreadConnection));
mScheduler->setEventThread(Cycle::Render, std::move(eventThread));
+ mScheduler->setEventThread(Cycle::LastComposite, std::make_unique<MockEventThread>());
mFlinger.resetScheduler(mScheduler);
}
@@ -193,11 +199,39 @@
ASSERT_EQ(1u, mScheduler->getNumActiveLayers());
}
-TEST_F(SchedulerTest, dispatchCachedReportedMode) {
- mScheduler->clearCachedReportedMode();
+TEST_F(SchedulerTest, emitModeChangeEvent) {
+ const auto selectorPtr =
+ std::make_shared<RefreshRateSelector>(kDisplay1Modes, kDisplay1Mode120->getId());
+ mScheduler->registerDisplay(kDisplayId1, selectorPtr);
+ mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120);
+ mScheduler->setContentRequirements({kLayer});
+
+ // No event is emitted in response to idle.
EXPECT_CALL(*mEventThread, onModeChanged(_)).Times(0);
- EXPECT_NO_FATAL_FAILURE(mScheduler->dispatchCachedReportedMode());
+
+ using TimerState = TestableScheduler::TimerState;
+
+ mScheduler->idleTimerCallback(TimerState::Expired);
+ selectorPtr->setActiveMode(kDisplay1Mode60->getId(), 60_Hz);
+
+ auto layer = kLayer;
+ layer.vote = RefreshRateSelector::LayerVoteType::ExplicitExact;
+ layer.desiredRefreshRate = 60_Hz;
+ mScheduler->setContentRequirements({layer});
+
+ // An event is emitted implicitly despite choosing the same mode as when idle.
+ EXPECT_CALL(*mEventThread, onModeChanged(kDisplay1Mode60_60)).Times(1);
+
+ mScheduler->idleTimerCallback(TimerState::Reset);
+
+ mScheduler->setContentRequirements({kLayer});
+
+ // An event is emitted explicitly for the mode change.
+ EXPECT_CALL(*mEventThread, onModeChanged(kDisplay1Mode120_120)).Times(1);
+
+ mScheduler->touchTimerCallback(TimerState::Reset);
+ mScheduler->onDisplayModeChanged(kDisplayId1, kDisplay1Mode120_120);
}
TEST_F(SchedulerTest, calculateMaxAcquiredBufferCount) {
@@ -246,14 +280,12 @@
/*updateAttachedChoreographer*/ false);
}
-TEST_F(SchedulerTest, chooseDisplayModesSingleDisplay) {
+TEST_F(SchedulerTest, chooseDisplayModes) {
mScheduler->registerDisplay(kDisplayId1,
std::make_shared<RefreshRateSelector>(kDisplay1Modes,
kDisplay1Mode60->getId()));
- std::vector<RefreshRateSelector::LayerRequirement> layers =
- std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
- mScheduler->setContentRequirements(layers);
+ mScheduler->setContentRequirements({kLayer, kLayer});
GlobalSignals globalSignals = {.idle = true};
mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
@@ -288,15 +320,14 @@
EXPECT_EQ(choice->get(), DisplayModeChoice({120_Hz, kDisplay1Mode120}, globalSignals));
}
-TEST_F(SchedulerTest, chooseDisplayModesSingleDisplayHighHintTouchSignal) {
+TEST_F(SchedulerTest, chooseDisplayModesHighHintTouchSignal) {
mScheduler->registerDisplay(kDisplayId1,
std::make_shared<RefreshRateSelector>(kDisplay1Modes,
kDisplay1Mode60->getId()));
using DisplayModeChoice = TestableScheduler::DisplayModeChoice;
- std::vector<RefreshRateSelector::LayerRequirement> layers =
- std::vector<RefreshRateSelector::LayerRequirement>({{.weight = 1.f}, {.weight = 1.f}});
+ std::vector<RefreshRateSelector::LayerRequirement> layers = {kLayer, kLayer};
auto& lr1 = layers[0];
auto& lr2 = layers[1];
@@ -371,9 +402,7 @@
kDisplay2Mode60},
GlobalSignals{});
- std::vector<RefreshRateSelector::LayerRequirement> layers = {{.weight = 1.f},
- {.weight = 1.f}};
- mScheduler->setContentRequirements(layers);
+ mScheduler->setContentRequirements({kLayer, kLayer});
mScheduler->setTouchStateAndIdleTimerPolicy(globalSignals);
const auto actualChoices = mScheduler->chooseDisplayModes();
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 0814e3d..df16b2e 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -176,6 +176,11 @@
mPolicy.idleTimer = globalSignals.idle ? TimerState::Expired : TimerState::Reset;
}
+ using Scheduler::TimerState;
+
+ using Scheduler::idleTimerCallback;
+ using Scheduler::touchTimerCallback;
+
void setContentRequirements(std::vector<RefreshRateSelector::LayerRequirement> layers) {
std::lock_guard<std::mutex> lock(mPolicyLock);
mPolicy.contentRequirements = std::move(layers);
@@ -188,15 +193,7 @@
return Scheduler::chooseDisplayModes();
}
- void dispatchCachedReportedMode() {
- std::lock_guard<std::mutex> lock(mPolicyLock);
- Scheduler::dispatchCachedReportedMode();
- }
-
- void clearCachedReportedMode() {
- std::lock_guard<std::mutex> lock(mPolicyLock);
- mPolicy.cachedModeChangedParams.reset();
- }
+ using Scheduler::onDisplayModeChanged;
void setInitialHwVsyncEnabled(PhysicalDisplayId id, bool enabled) {
auto schedule = getVsyncSchedule(id);