diff options
author | 2023-08-15 09:36:37 -0700 | |
---|---|---|
committer | 2023-09-21 10:44:18 -0700 | |
commit | 5dcd75d46c5e4eda82c42660eea56f0d923acd53 (patch) | |
tree | 4361b8ed292282f70c411e458a9f85fabc997bdf | |
parent | c79a756a21be45c13d5578f3c14e7b021cc9927e (diff) |
SF: Propagate display hotplug errors
Add support for SurfaceFlinger to handle display connection
errors and propagate any error code on hotplug event up the
stack.
Bug: 241286153
Test: manual
Change-Id: I88afeb4f61b13714a81138180db0762cf3ae4ab0
-rw-r--r-- | libs/gui/Choreographer.cpp | 8 | ||||
-rw-r--r-- | libs/gui/DisplayEventDispatcher.cpp | 8 | ||||
-rw-r--r-- | libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp | 5 | ||||
-rw-r--r-- | libs/gui/fuzzer/libgui_fuzzer_utils.h | 1 | ||||
-rw-r--r-- | libs/gui/include/gui/Choreographer.h | 3 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventDispatcher.h | 3 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventReceiver.h | 1 | ||||
-rw-r--r-- | libs/gui/tests/DisplayEventStructLayout_test.cpp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/EventThread.cpp | 30 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/EventThread.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.cpp | 11 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/mock/MockEventThread.h | 1 |
13 files changed, 69 insertions, 9 deletions
diff --git a/libs/gui/Choreographer.cpp b/libs/gui/Choreographer.cpp index 46fb068dee..93df12471d 100644 --- a/libs/gui/Choreographer.cpp +++ b/libs/gui/Choreographer.cpp @@ -324,6 +324,12 @@ void Choreographer::dispatchHotplug(nsecs_t, PhysicalDisplayId displayId, bool c to_string(displayId).c_str(), toString(connected)); } +void Choreographer::dispatchHotplugConnectionError(nsecs_t, int32_t connectionError) { + ALOGV("choreographer %p ~ received hotplug connection error event (connectionError=%d), " + "ignoring.", + this, connectionError); +} + void Choreographer::dispatchModeChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) { LOG_ALWAYS_FATAL("dispatchModeChanged was called but was never registered"); } @@ -394,4 +400,4 @@ int64_t Choreographer::getStartTimeNanosForVsyncId(AVsyncId vsyncId) { return iter->second; } -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index 8a883770d8..5dd058cf9f 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -173,7 +173,13 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, *outVsyncEventData = ev.vsync.vsyncData; break; case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: - dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected); + if (ev.hotplug.connectionError == 0) { + dispatchHotplug(ev.header.timestamp, ev.header.displayId, + ev.hotplug.connected); + } else { + dispatchHotplugConnectionError(ev.header.timestamp, + ev.hotplug.connectionError); + } break; case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: dispatchModeChanged(ev.header.timestamp, ev.header.displayId, diff --git a/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp b/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp index 6e4f074825..0d2a52b576 100644 --- a/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp +++ b/libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp @@ -62,7 +62,10 @@ DisplayEventReceiver::Event buildDisplayEvent(FuzzedDataProvider* fdp, uint32_t } case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG: { - event.hotplug = DisplayEventReceiver::Event::Hotplug{fdp->ConsumeBool() /*connected*/}; + event.hotplug = + DisplayEventReceiver::Event::Hotplug{fdp->ConsumeBool() /*connected*/, + fdp->ConsumeIntegral< + int32_t>() /*connectionError*/}; break; } case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: { diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h index 177d5f89c9..bdf8856a75 100644 --- a/libs/gui/fuzzer/libgui_fuzzer_utils.h +++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h @@ -197,6 +197,7 @@ public: MOCK_METHOD4(dispatchVsync, void(nsecs_t, PhysicalDisplayId, uint32_t, VsyncEventData)); MOCK_METHOD3(dispatchHotplug, void(nsecs_t, PhysicalDisplayId, bool)); + MOCK_METHOD2(dispatchHotplugConnectionError, void(nsecs_t, int32_t)); MOCK_METHOD4(dispatchModeChanged, void(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t)); MOCK_METHOD2(dispatchNullEvent, void(nsecs_t, PhysicalDisplayId)); MOCK_METHOD3(dispatchFrameRateOverrides, diff --git a/libs/gui/include/gui/Choreographer.h b/libs/gui/include/gui/Choreographer.h index 1df9b11432..9fef512b64 100644 --- a/libs/gui/include/gui/Choreographer.h +++ b/libs/gui/include/gui/Choreographer.h @@ -110,6 +110,7 @@ private: void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count, VsyncEventData vsyncEventData) override; void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override; + void dispatchHotplugConnectionError(nsecs_t timestamp, int32_t connectionError) override; void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t vsyncPeriod) override; void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override; @@ -137,4 +138,4 @@ private: static constexpr size_t kMaxStartTimes = 250; }; -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 140efa6d97..fe2dd206ed 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -53,6 +53,9 @@ private: VsyncEventData vsyncEventData) = 0; virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) = 0; + + virtual void dispatchHotplugConnectionError(nsecs_t timestamp, int32_t connectionError) = 0; + virtual void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId, nsecs_t vsyncPeriod) = 0; // AChoreographer-specific hook for processing null-events so that looper diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 7fd6c35c5e..79582ce685 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -88,6 +88,7 @@ public: struct Hotplug { bool connected; + int32_t connectionError __attribute__((aligned(4))); }; struct ModeChange { diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp index 3949d70aac..29eeaa806f 100644 --- a/libs/gui/tests/DisplayEventStructLayout_test.cpp +++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp @@ -59,6 +59,7 @@ TEST(DisplayEventStructLayoutTest, TestEventAlignment) { lastFrameTimelineOffset + 16); CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connected, 0); + CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connectionError, 4); CHECK_OFFSET(DisplayEventReceiver::Event::ModeChange, modeId, 0); CHECK_OFFSET(DisplayEventReceiver::Event::ModeChange, vsyncPeriod, 8); diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index c70ed2c544..21714da0ac 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -111,6 +111,15 @@ DisplayEventReceiver::Event makeHotplug(PhysicalDisplayId displayId, nsecs_t tim return event; } +DisplayEventReceiver::Event makeHotplugError(nsecs_t timestamp, int32_t connectionError) { + DisplayEventReceiver::Event event; + PhysicalDisplayId unusedDisplayId; + event.header = {DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG, unusedDisplayId, timestamp}; + event.hotplug.connected = false; + event.hotplug.connectionError = connectionError; + return event; +} + DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t timestamp, uint32_t count, nsecs_t expectedPresentationTime, nsecs_t deadlineTimestamp) { @@ -408,6 +417,13 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) mCondition.notify_all(); } +void EventThread::onHotplugConnectionError(int32_t errorCode) { + std::lock_guard<std::mutex> lock(mMutex); + + mPendingEvents.push_back(makeHotplugError(systemTime(), errorCode)); + mCondition.notify_all(); +} + void EventThread::onModeChanged(const scheduler::FrameRateMode& mode) { std::lock_guard<std::mutex> lock(mMutex); @@ -439,11 +455,15 @@ void EventThread::threadMain(std::unique_lock<std::mutex>& lock) { mPendingEvents.pop_front(); if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) { - if (event->hotplug.connected && !mVSyncState) { - mVSyncState.emplace(event->header.displayId); - } else if (!event->hotplug.connected && mVSyncState && - mVSyncState->displayId == event->header.displayId) { - mVSyncState.reset(); + if (event->hotplug.connectionError == 0) { + if (event->hotplug.connected && !mVSyncState) { + mVSyncState.emplace(event->header.displayId); + } else if (!event->hotplug.connected && mVSyncState && + mVSyncState->displayId == event->header.displayId) { + mVSyncState.reset(); + } + } else { + // Ignore vsync stuff on an error. } } } diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 7023445581..576910ed6a 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -111,6 +111,8 @@ public: virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0; + virtual void onHotplugConnectionError(int32_t connectionError) = 0; + // called when SF changes the active mode and apps needs to be notified about the change virtual void onModeChanged(const scheduler::FrameRateMode&) = 0; @@ -159,6 +161,8 @@ public: void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override; + void onHotplugConnectionError(int32_t connectionError) override; + void onModeChanged(const scheduler::FrameRateMode&) override; void onFrameRateOverridesChanged(PhysicalDisplayId displayId, diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 595550bd3d..aa24f565f5 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -347,6 +347,17 @@ void Scheduler::onHotplugReceived(ConnectionHandle handle, PhysicalDisplayId dis thread->onHotplugReceived(displayId, connected); } +void Scheduler::onHotplugConnectionError(ConnectionHandle handle, int32_t errorCode) { + android::EventThread* thread; + { + std::lock_guard<std::mutex> lock(mConnectionsLock); + RETURN_IF_INVALID_HANDLE(handle); + thread = mConnections[handle].thread.get(); + } + + thread->onHotplugConnectionError(errorCode); +} + void Scheduler::enableSyntheticVsync(bool enable) { // TODO(b/241285945): Remove connection handles. const ConnectionHandle handle = mAppConnectionHandle; diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index d65df2a65d..822f7cc299 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -161,6 +161,8 @@ public: sp<EventThreadConnection> getEventConnection(ConnectionHandle); void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); + void onHotplugConnectionError(ConnectionHandle, int32_t errorCode); + void onPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&) EXCLUDES(mPolicyLock); void onNonPrimaryDisplayModeChanged(ConnectionHandle, const FrameRateMode&); diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index 9a1a16dd82..8e782ebbb1 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -33,6 +33,7 @@ public: (ResyncCallback, EventRegistrationFlags), (const, override)); MOCK_METHOD(void, enableSyntheticVsync, (bool), (override)); MOCK_METHOD(void, onHotplugReceived, (PhysicalDisplayId, bool), (override)); + MOCK_METHOD(void, onHotplugConnectionError, (int32_t), (override)); MOCK_METHOD(void, onModeChanged, (const scheduler::FrameRateMode&), (override)); MOCK_METHOD(void, onFrameRateOverridesChanged, (PhysicalDisplayId, std::vector<FrameRateOverride>), (override)); |