summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Brian Johnson <hibrian@google.com> 2023-08-15 09:36:37 -0700
committer Huihong Luo <huisinro@google.com> 2023-09-21 10:44:18 -0700
commit5dcd75d46c5e4eda82c42660eea56f0d923acd53 (patch)
tree4361b8ed292282f70c411e458a9f85fabc997bdf
parentc79a756a21be45c13d5578f3c14e7b021cc9927e (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.cpp8
-rw-r--r--libs/gui/DisplayEventDispatcher.cpp8
-rw-r--r--libs/gui/fuzzer/libgui_displayEvent_fuzzer.cpp5
-rw-r--r--libs/gui/fuzzer/libgui_fuzzer_utils.h1
-rw-r--r--libs/gui/include/gui/Choreographer.h3
-rw-r--r--libs/gui/include/gui/DisplayEventDispatcher.h3
-rw-r--r--libs/gui/include/gui/DisplayEventReceiver.h1
-rw-r--r--libs/gui/tests/DisplayEventStructLayout_test.cpp1
-rw-r--r--services/surfaceflinger/Scheduler/EventThread.cpp30
-rw-r--r--services/surfaceflinger/Scheduler/EventThread.h4
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.cpp11
-rw-r--r--services/surfaceflinger/Scheduler/Scheduler.h2
-rw-r--r--services/surfaceflinger/tests/unittests/mock/MockEventThread.h1
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));