SF: Introduce a configure stage
Decouple hotplug processing from commit of display transactions, as a
step toward per-display commit/composite. The configure stage will be
responsible for mode setting as well.
Bug: 241285876
Test: libsurfaceflinger_unittest
Change-Id: I72b7223760fa5896debb046f158845a0b4f4599a
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
index 93af225..982b9ff 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_InitiateModeChange.cpp
@@ -42,6 +42,7 @@
PrimaryDisplayVariant::setupHwcGetActiveConfigCallExpectations(this);
mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
+ mFlinger.configureAndCommit();
mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
.setDisplayModes(makeModes(kMode60, kMode90, kMode120), kModeId60)
diff --git a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
index f20b9f9..5e1042e 100644
--- a/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/MessageQueueTest.cpp
@@ -32,6 +32,7 @@
using CallbackToken = scheduler::VSyncDispatch::CallbackToken;
struct NoOpCompositor final : ICompositor {
+ void configure() override {}
bool commit(TimePoint, VsyncId, TimePoint) override { return false; }
void composite(TimePoint, VsyncId) override {}
void sample() override {}
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index b607b88..57937dc 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -40,18 +40,17 @@
PrimaryDisplayVariant::setupNativeWindowSurfaceCreationCallExpectations(this);
PrimaryDisplayVariant::setupHwcGetActiveConfigCallExpectations(this);
+ DisplayModes modes = makeModes(kMode60, kMode90, kMode120, kMode90_4K);
+ auto configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
+
+ setupScheduler(configs);
+
mFlinger.onComposerHalHotplug(PrimaryDisplayVariant::HWC_DISPLAY_ID, Connection::CONNECTED);
+ mFlinger.configureAndCommit();
- {
- DisplayModes modes = makeModes(kMode60, kMode90, kMode120, kMode90_4K);
- auto configs = std::make_shared<scheduler::RefreshRateConfigs>(modes, kModeId60);
-
- mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
- .setDisplayModes(std::move(modes), kModeId60, std::move(configs))
- .inject();
- }
-
- setupScheduler(mDisplay->holdRefreshRateConfigs());
+ mDisplay = PrimaryDisplayVariant::makeFakeExistingDisplayInjector(this)
+ .setDisplayModes(std::move(modes), kModeId60, std::move(configs))
+ .inject();
// isVsyncPeriodSwitchSupported should return true, otherwise the SF's HWC proxy
// will call setActiveConfig instead of setActiveConfigWithConstraints.
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
index bc9e801..71f1a2b 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayTransactionCommitTest.cpp
@@ -175,7 +175,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ mFlinger.configureAndCommit();
// --------------------------------------------------------------------
// Postconditions
@@ -204,7 +204,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ mFlinger.configureAndCommit();
// --------------------------------------------------------------------
// Postconditions
@@ -239,7 +239,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ mFlinger.configureAndCommit();
// --------------------------------------------------------------------
// Postconditions
@@ -321,7 +321,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ mFlinger.configureAndCommit();
// --------------------------------------------------------------------
// Postconditions
@@ -366,7 +366,7 @@
// --------------------------------------------------------------------
// Invocation
- mFlinger.commitTransactionsLocked(eDisplayTransactionNeeded);
+ mFlinger.configureAndCommit();
// --------------------------------------------------------------------
// Postconditions
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
index 1da3bb6..e5cf4d7 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HotplugTest.cpp
@@ -23,37 +23,15 @@
class HotplugTest : public DisplayTransactionTest {};
-TEST_F(HotplugTest, enqueuesEventsForDisplayTransaction) {
+TEST_F(HotplugTest, schedulesConfigureToProcessHotplugEvents) {
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleConfigure()).Times(2);
+
constexpr HWDisplayId hwcDisplayId1 = 456;
- constexpr HWDisplayId hwcDisplayId2 = 654;
-
- // --------------------------------------------------------------------
- // Preconditions
-
- // Set the main thread id so that the current thread does not appear to be
- // the main thread.
- mFlinger.mutableMainThreadId() = std::thread::id();
-
- // --------------------------------------------------------------------
- // Call Expectations
-
- // We expect a scheduled commit for the display transaction.
- EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
-
- // --------------------------------------------------------------------
- // Invocation
-
- // Simulate two hotplug events (a connect and a disconnect)
mFlinger.onComposerHalHotplug(hwcDisplayId1, Connection::CONNECTED);
+
+ constexpr HWDisplayId hwcDisplayId2 = 654;
mFlinger.onComposerHalHotplug(hwcDisplayId2, Connection::DISCONNECTED);
- // --------------------------------------------------------------------
- // Postconditions
-
- // The display transaction needed flag should be set.
- EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-
- // All events should be in the pending event queue.
const auto& pendingEvents = mFlinger.mutablePendingHotplugEvents();
ASSERT_EQ(2u, pendingEvents.size());
EXPECT_EQ(hwcDisplayId1, pendingEvents[0].hwcDisplayId);
@@ -62,48 +40,16 @@
EXPECT_EQ(Connection::DISCONNECTED, pendingEvents[1].connection);
}
-TEST_F(HotplugTest, processesEnqueuedEventsIfCalledOnMainThread) {
- constexpr HWDisplayId displayId1 = 456;
-
- // --------------------------------------------------------------------
- // Note:
- // --------------------------------------------------------------------
- // This test case is a bit tricky. We want to verify that
- // onComposerHalHotplug() calls processDisplayHotplugEventsLocked(), but we
- // don't really want to provide coverage for everything the later function
- // does as there are specific tests for it.
- // --------------------------------------------------------------------
-
- // --------------------------------------------------------------------
- // Preconditions
-
- // Set the main thread id so that the current thread does appear to be the
- // main thread.
- mFlinger.mutableMainThreadId() = std::this_thread::get_id();
-
- // --------------------------------------------------------------------
- // Call Expectations
-
- // We expect a scheduled commit for the display transaction.
+TEST_F(HotplugTest, schedulesFrameToCommitDisplayTransaction) {
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
- // --------------------------------------------------------------------
- // Invocation
-
- // Simulate a disconnect on a display id that is not connected. This should
- // be enqueued by onComposerHalHotplug(), and dequeued by
- // processDisplayHotplugEventsLocked(), but then ignored as invalid.
+ constexpr HWDisplayId displayId1 = 456;
mFlinger.onComposerHalHotplug(displayId1, Connection::DISCONNECTED);
+ mFlinger.configure();
- // --------------------------------------------------------------------
- // Postconditions
-
- // The display transaction needed flag should be set.
- EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-
- // There should be no event queued on return, as it should have been
- // processed.
+ // The configure stage should consume the hotplug queue and produce a display transaction.
EXPECT_TRUE(mFlinger.mutablePendingHotplugEvents().empty());
+ EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
}
TEST_F(HotplugTest, rejectsHotplugIfFailedToLoadDisplayModes) {
@@ -125,14 +71,14 @@
.WillOnce(Return(Error::NONE));
ExternalDisplay::injectPendingHotplugEvent(this, Connection::CONNECTED);
- mFlinger.processDisplayHotplugEvents();
+ mFlinger.configure();
// The hotplug should be rejected, so no HWComposer::DisplayData should be created.
EXPECT_FALSE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
// Disconnecting a display that does not exist should be a no-op.
ExternalDisplay::injectPendingHotplugEvent(this, Connection::DISCONNECTED);
- mFlinger.processDisplayHotplugEvents();
+ mFlinger.configure();
EXPECT_FALSE(hasPhysicalHwcDisplay(ExternalDisplay::HWC_DISPLAY_ID));
}
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index 66cdfd7..93e3059 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -50,6 +50,7 @@
});
}
+ MOCK_METHOD(void, scheduleConfigure, (), (override));
MOCK_METHOD(void, scheduleFrame, (), (override));
MOCK_METHOD(void, postMessage, (sp<MessageHandler>&&), (override));
@@ -109,6 +110,7 @@
private:
// ICompositor overrides:
+ void configure() override {}
bool commit(TimePoint, VsyncId, TimePoint) override { return false; }
void composite(TimePoint, VsyncId) override {}
void sample() override {}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 7dd9935..42585b5 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -317,8 +317,15 @@
* Forwarding for functions being tested
*/
- TimePoint commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVSyncTime) {
- mFlinger->commit(frameTime, vsyncId, expectedVSyncTime);
+ void configure() { mFlinger->configure(); }
+
+ void configureAndCommit() {
+ configure();
+ commitTransactionsLocked(eDisplayTransactionNeeded);
+ }
+
+ TimePoint commit(TimePoint frameTime, VsyncId vsyncId, TimePoint expectedVsyncTime) {
+ mFlinger->commit(frameTime, vsyncId, expectedVsyncTime);
return frameTime;
}
@@ -362,19 +369,15 @@
dispSurface, producer);
}
- auto commitTransactionsLocked(uint32_t transactionFlags) {
+ void commitTransactionsLocked(uint32_t transactionFlags) {
Mutex::Autolock lock(mFlinger->mStateLock);
- return mFlinger->commitTransactionsLocked(transactionFlags);
+ mFlinger->commitTransactionsLocked(transactionFlags);
}
void onComposerHalHotplug(hal::HWDisplayId hwcDisplayId, hal::Connection connection) {
mFlinger->onComposerHalHotplug(hwcDisplayId, connection);
}
- void processDisplayHotplugEvents() {
- FTL_FAKE_GUARD(mFlinger->mStateLock, mFlinger->processDisplayHotplugEventsLocked());
- }
-
auto setDisplayStateLocked(const DisplayState& s) {
Mutex::Autolock lock(mFlinger->mStateLock);
return mFlinger->setDisplayStateLocked(s);