Loading services/surfaceflinger/Scheduler/EventThread.cpp +40 −17 Original line number Diff line number Diff line Loading @@ -264,24 +264,29 @@ void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, void EventThread::onScreenReleased() { std::lock_guard<std::mutex> lock(mMutex); if (!mVSyncState.synthetic) { mVSyncState.synthetic = true; mCondition.notify_all(); if (!mVSyncState || mVSyncState->synthetic) { return; } mVSyncState->synthetic = true; mCondition.notify_all(); } void EventThread::onScreenAcquired() { std::lock_guard<std::mutex> lock(mMutex); if (mVSyncState.synthetic) { mVSyncState.synthetic = false; mCondition.notify_all(); if (!mVSyncState || !mVSyncState->synthetic) { return; } mVSyncState->synthetic = false; mCondition.notify_all(); } void EventThread::onVSyncEvent(nsecs_t timestamp) { std::lock_guard<std::mutex> lock(mMutex); mPendingEvents.push_back(makeVSync(mVSyncState.displayId, timestamp, ++mVSyncState.count)); LOG_FATAL_IF(!mVSyncState); mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count)); mCondition.notify_all(); } Loading @@ -304,10 +309,22 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { event = mPendingEvents.front(); mPendingEvents.pop_front(); if (mInterceptVSyncsCallback && event->header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { switch (event->header.type) { case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: if (event->hotplug.connected && !mVSyncState) { mVSyncState.emplace(event->header.id); } else if (!event->hotplug.connected && mVSyncState && mVSyncState->displayId == event->header.id) { mVSyncState.reset(); } break; case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: if (mInterceptVSyncsCallback) { mInterceptVSyncsCallback(event->header.timestamp); } break; } } bool vsyncRequested = false; Loading @@ -334,9 +351,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { } State nextState; if (vsyncRequested) { nextState = mVSyncState.synthetic ? State::SyntheticVSync : State::VSync; if (mVSyncState && vsyncRequested) { nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync; } else { ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected"); nextState = State::Idle; } Loading Loading @@ -364,9 +382,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) { ALOGW_IF(mState == State::VSync, "Faking VSYNC due to driver stall"); mPendingEvents.push_back(makeVSync(mVSyncState.displayId, LOG_FATAL_IF(!mVSyncState); mPendingEvents.push_back(makeVSync(mVSyncState->displayId, systemTime(SYSTEM_TIME_MONOTONIC), ++mVSyncState.count)); ++mVSyncState->count)); } } } Loading Loading @@ -419,9 +438,13 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, void EventThread::dump(std::string& result) const { std::lock_guard<std::mutex> lock(mMutex); StringAppendF(&result, "%s: state=%s", mThreadName, toCString(mState)); StringAppendF(&result, " VSyncState{displayId=%u, count=%u%s}\n", mVSyncState.displayId, mVSyncState.count, mVSyncState.synthetic ? ", synthetic" : ""); StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState)); if (mVSyncState) { StringAppendF(&result, "{displayId=%u, count=%u%s}\n", mVSyncState->displayId, mVSyncState->count, mVSyncState->synthetic ? ", synthetic" : ""); } else { StringAppendF(&result, "none\n"); } StringAppendF(&result, " pending events (count=%zu):\n", mPendingEvents.size()); for (const auto& event : mPendingEvents) { Loading services/surfaceflinger/Scheduler/EventThread.h +7 −2 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <cstdint> #include <deque> #include <mutex> #include <optional> #include <thread> #include <vector> Loading Loading @@ -198,7 +199,9 @@ private: // VSYNC state of connected display. struct VSyncState { uint32_t displayId = 0; explicit VSyncState(uint32_t displayId) : displayId(displayId) {} const uint32_t displayId; // Number of VSYNC events since display was connected. uint32_t count = 0; Loading @@ -207,7 +210,9 @@ private: bool synthetic = false; }; VSyncState mVSyncState GUARDED_BY(mMutex); // TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals, // and support headless mode by injecting a fake display with synthetic VSYNC. std::optional<VSyncState> mVSyncState GUARDED_BY(mMutex); // State machine for event loop. enum class State { Loading services/surfaceflinger/SurfaceFlinger.cpp +15 −28 Original line number Diff line number Diff line Loading @@ -2564,6 +2564,17 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { mPendingHotplugEvents.clear(); } void SurfaceFlinger::dispatchDisplayHotplugEvent(EventThread::DisplayType displayType, bool connected) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, displayType, connected); mScheduler->hotplugReceived(mSfConnectionHandle, displayType, connected); } else { mEventThread->onHotplugReceived(displayType, connected); mSFEventThread->onHotplugReceived(displayType, connected); } } sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const wp<IBinder>& displayToken, const std::optional<DisplayId>& displayId, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, Loading Loading @@ -2668,19 +2679,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { display->disconnect(); } if (internalDisplayId && internalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, false); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false); } dispatchDisplayHotplugEvent(EventThread::DisplayType::Primary, false); } else if (externalDisplayId && externalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, false); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::External, false); } dispatchDisplayHotplugEvent(EventThread::DisplayType::External, false); } mDisplays.erase(draw.keyAt(i)); } else { Loading Loading @@ -2786,23 +2787,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { LOG_ALWAYS_FATAL_IF(!displayId); if (displayId == getInternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, true); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, true); } dispatchDisplayHotplugEvent(EventThread::DisplayType::Primary, true); } else if (displayId == getExternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, true); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::External, true); } dispatchDisplayHotplugEvent(EventThread::DisplayType::External, true); } } } Loading services/surfaceflinger/SurfaceFlinger.h +2 −4 Original line number Diff line number Diff line Loading @@ -294,10 +294,6 @@ public: // starts SurfaceFlinger main loop in the current thread void run() ANDROID_API; enum { EVENT_VSYNC = HWC_EVENT_VSYNC }; // post an asynchronous message to the main thread status_t postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0); Loading Loading @@ -754,6 +750,8 @@ private: void processDisplayChangesLocked(); void processDisplayHotplugEventsLocked(); void dispatchDisplayHotplugEvent(EventThread::DisplayType displayType, bool connected); /* ------------------------------------------------------------------------ * VSync */ Loading services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +13 −12 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ public: TestableSurfaceFlinger mFlinger; mock::EventThread* mEventThread = new mock::EventThread(); mock::EventThread* mSFEventThread = new mock::EventThread(); mock::EventControlThread* mEventControlThread = new mock::EventControlThread(); sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow(); sp<GraphicBuffer> mBuffer = new GraphicBuffer(); Loading Loading @@ -161,6 +162,7 @@ DisplayTransactionTest::DisplayTransactionTest() { mFlinger.mutableEventControlThread().reset(mEventControlThread); mFlinger.mutableEventThread().reset(mEventThread); mFlinger.mutableSFEventThread().reset(mSFEventThread); mFlinger.mutableEventQueue().reset(mMessageQueue); mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine)); mFlinger.mutableInterceptor().reset(mSurfaceInterceptor); Loading Loading @@ -319,6 +321,11 @@ struct DisplayVariant { // Whether the display is primary static constexpr Primary PRIMARY = primary; static constexpr auto displayType() { return static_cast<bool>(PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External; } static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { auto injector = FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(), Loading Loading @@ -1404,23 +1411,17 @@ void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessin Case::PerFrameMetadataSupport::setupComposerCallExpectations(this); EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(static_cast<bool>(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, true)) .Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::displayType(), true)).Times(1); EXPECT_CALL(*mSFEventThread, onHotplugReceived(Case::Display::displayType(), true)).Times(1); } template <typename Case> void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() { EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(static_cast<bool>(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, false)) .Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::displayType(), false)).Times(1); EXPECT_CALL(*mSFEventThread, onHotplugReceived(Case::Display::displayType(), false)).Times(1); } template <typename Case> Loading Loading
services/surfaceflinger/Scheduler/EventThread.cpp +40 −17 Original line number Diff line number Diff line Loading @@ -264,24 +264,29 @@ void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, void EventThread::onScreenReleased() { std::lock_guard<std::mutex> lock(mMutex); if (!mVSyncState.synthetic) { mVSyncState.synthetic = true; mCondition.notify_all(); if (!mVSyncState || mVSyncState->synthetic) { return; } mVSyncState->synthetic = true; mCondition.notify_all(); } void EventThread::onScreenAcquired() { std::lock_guard<std::mutex> lock(mMutex); if (mVSyncState.synthetic) { mVSyncState.synthetic = false; mCondition.notify_all(); if (!mVSyncState || !mVSyncState->synthetic) { return; } mVSyncState->synthetic = false; mCondition.notify_all(); } void EventThread::onVSyncEvent(nsecs_t timestamp) { std::lock_guard<std::mutex> lock(mMutex); mPendingEvents.push_back(makeVSync(mVSyncState.displayId, timestamp, ++mVSyncState.count)); LOG_FATAL_IF(!mVSyncState); mPendingEvents.push_back(makeVSync(mVSyncState->displayId, timestamp, ++mVSyncState->count)); mCondition.notify_all(); } Loading @@ -304,10 +309,22 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { event = mPendingEvents.front(); mPendingEvents.pop_front(); if (mInterceptVSyncsCallback && event->header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) { switch (event->header.type) { case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: if (event->hotplug.connected && !mVSyncState) { mVSyncState.emplace(event->header.id); } else if (!event->hotplug.connected && mVSyncState && mVSyncState->displayId == event->header.id) { mVSyncState.reset(); } break; case DisplayEventReceiver::DISPLAY_EVENT_VSYNC: if (mInterceptVSyncsCallback) { mInterceptVSyncsCallback(event->header.timestamp); } break; } } bool vsyncRequested = false; Loading @@ -334,9 +351,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { } State nextState; if (vsyncRequested) { nextState = mVSyncState.synthetic ? State::SyntheticVSync : State::VSync; if (mVSyncState && vsyncRequested) { nextState = mVSyncState->synthetic ? State::SyntheticVSync : State::VSync; } else { ALOGW_IF(!mVSyncState, "Ignoring VSYNC request while display is disconnected"); nextState = State::Idle; } Loading Loading @@ -364,9 +382,10 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { if (mCondition.wait_for(lock, timeout) == std::cv_status::timeout) { ALOGW_IF(mState == State::VSync, "Faking VSYNC due to driver stall"); mPendingEvents.push_back(makeVSync(mVSyncState.displayId, LOG_FATAL_IF(!mVSyncState); mPendingEvents.push_back(makeVSync(mVSyncState->displayId, systemTime(SYSTEM_TIME_MONOTONIC), ++mVSyncState.count)); ++mVSyncState->count)); } } } Loading Loading @@ -419,9 +438,13 @@ void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event, void EventThread::dump(std::string& result) const { std::lock_guard<std::mutex> lock(mMutex); StringAppendF(&result, "%s: state=%s", mThreadName, toCString(mState)); StringAppendF(&result, " VSyncState{displayId=%u, count=%u%s}\n", mVSyncState.displayId, mVSyncState.count, mVSyncState.synthetic ? ", synthetic" : ""); StringAppendF(&result, "%s: state=%s VSyncState=", mThreadName, toCString(mState)); if (mVSyncState) { StringAppendF(&result, "{displayId=%u, count=%u%s}\n", mVSyncState->displayId, mVSyncState->count, mVSyncState->synthetic ? ", synthetic" : ""); } else { StringAppendF(&result, "none\n"); } StringAppendF(&result, " pending events (count=%zu):\n", mPendingEvents.size()); for (const auto& event : mPendingEvents) { Loading
services/surfaceflinger/Scheduler/EventThread.h +7 −2 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <cstdint> #include <deque> #include <mutex> #include <optional> #include <thread> #include <vector> Loading Loading @@ -198,7 +199,9 @@ private: // VSYNC state of connected display. struct VSyncState { uint32_t displayId = 0; explicit VSyncState(uint32_t displayId) : displayId(displayId) {} const uint32_t displayId; // Number of VSYNC events since display was connected. uint32_t count = 0; Loading @@ -207,7 +210,9 @@ private: bool synthetic = false; }; VSyncState mVSyncState GUARDED_BY(mMutex); // TODO(b/74619554): Create per-display threads waiting on respective VSYNC signals, // and support headless mode by injecting a fake display with synthetic VSYNC. std::optional<VSyncState> mVSyncState GUARDED_BY(mMutex); // State machine for event loop. enum class State { Loading
services/surfaceflinger/SurfaceFlinger.cpp +15 −28 Original line number Diff line number Diff line Loading @@ -2564,6 +2564,17 @@ void SurfaceFlinger::processDisplayHotplugEventsLocked() { mPendingHotplugEvents.clear(); } void SurfaceFlinger::dispatchDisplayHotplugEvent(EventThread::DisplayType displayType, bool connected) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, displayType, connected); mScheduler->hotplugReceived(mSfConnectionHandle, displayType, connected); } else { mEventThread->onHotplugReceived(displayType, connected); mSFEventThread->onHotplugReceived(displayType, connected); } } sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( const wp<IBinder>& displayToken, const std::optional<DisplayId>& displayId, const DisplayDeviceState& state, const sp<compositionengine::DisplaySurface>& dispSurface, Loading Loading @@ -2668,19 +2679,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { display->disconnect(); } if (internalDisplayId && internalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, false); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, false); } dispatchDisplayHotplugEvent(EventThread::DisplayType::Primary, false); } else if (externalDisplayId && externalDisplayId == draw[i].displayId) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, false); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::External, false); } dispatchDisplayHotplugEvent(EventThread::DisplayType::External, false); } mDisplays.erase(draw.keyAt(i)); } else { Loading Loading @@ -2786,23 +2787,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { LOG_ALWAYS_FATAL_IF(!displayId); if (displayId == getInternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::Primary, true); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::Primary, true); } dispatchDisplayHotplugEvent(EventThread::DisplayType::Primary, true); } else if (displayId == getExternalDisplayId()) { if (mUseScheduler) { mScheduler->hotplugReceived(mAppConnectionHandle, EventThread::DisplayType::External, true); } else { mEventThread->onHotplugReceived(EventThread::DisplayType::External, true); } dispatchDisplayHotplugEvent(EventThread::DisplayType::External, true); } } } Loading
services/surfaceflinger/SurfaceFlinger.h +2 −4 Original line number Diff line number Diff line Loading @@ -294,10 +294,6 @@ public: // starts SurfaceFlinger main loop in the current thread void run() ANDROID_API; enum { EVENT_VSYNC = HWC_EVENT_VSYNC }; // post an asynchronous message to the main thread status_t postMessageAsync(const sp<MessageBase>& msg, nsecs_t reltime = 0, uint32_t flags = 0); Loading Loading @@ -754,6 +750,8 @@ private: void processDisplayChangesLocked(); void processDisplayHotplugEventsLocked(); void dispatchDisplayHotplugEvent(EventThread::DisplayType displayType, bool connected); /* ------------------------------------------------------------------------ * VSync */ Loading
services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +13 −12 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ public: TestableSurfaceFlinger mFlinger; mock::EventThread* mEventThread = new mock::EventThread(); mock::EventThread* mSFEventThread = new mock::EventThread(); mock::EventControlThread* mEventControlThread = new mock::EventControlThread(); sp<mock::NativeWindow> mNativeWindow = new mock::NativeWindow(); sp<GraphicBuffer> mBuffer = new GraphicBuffer(); Loading Loading @@ -161,6 +162,7 @@ DisplayTransactionTest::DisplayTransactionTest() { mFlinger.mutableEventControlThread().reset(mEventControlThread); mFlinger.mutableEventThread().reset(mEventThread); mFlinger.mutableSFEventThread().reset(mSFEventThread); mFlinger.mutableEventQueue().reset(mMessageQueue); mFlinger.setupRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine)); mFlinger.mutableInterceptor().reset(mSurfaceInterceptor); Loading Loading @@ -319,6 +321,11 @@ struct DisplayVariant { // Whether the display is primary static constexpr Primary PRIMARY = primary; static constexpr auto displayType() { return static_cast<bool>(PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External; } static auto makeFakeExistingDisplayInjector(DisplayTransactionTest* test) { auto injector = FakeDisplayDeviceInjector(test->mFlinger, DISPLAY_ID::get(), Loading Loading @@ -1404,23 +1411,17 @@ void HandleTransactionLockedTest::setupCommonCallExpectationsForConnectProcessin Case::PerFrameMetadataSupport::setupComposerCallExpectations(this); EXPECT_CALL(*mSurfaceInterceptor, saveDisplayCreation(_)).Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(static_cast<bool>(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, true)) .Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::displayType(), true)).Times(1); EXPECT_CALL(*mSFEventThread, onHotplugReceived(Case::Display::displayType(), true)).Times(1); } template <typename Case> void HandleTransactionLockedTest::setupCommonCallExpectationsForDisconnectProcessing() { EXPECT_CALL(*mSurfaceInterceptor, saveDisplayDeletion(_)).Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(static_cast<bool>(Case::Display::PRIMARY) ? EventThread::DisplayType::Primary : EventThread::DisplayType::External, false)) .Times(1); EXPECT_CALL(*mEventThread, onHotplugReceived(Case::Display::displayType(), false)).Times(1); EXPECT_CALL(*mSFEventThread, onHotplugReceived(Case::Display::displayType(), false)).Times(1); } template <typename Case> Loading