diff options
author | 2024-11-07 23:49:46 +0000 | |
---|---|---|
committer | 2024-11-27 20:02:20 +0000 | |
commit | 5ef1fa1b61ed3e73e450b8b4997509fe706b9fbe (patch) | |
tree | a06b223fbb160fac1399c4017a31b830508956e2 | |
parent | b03dfd3b1139d1308f5e6da5057040e8e56b4dcf (diff) |
SF: Propagate Display Mode Rejection from SF to DM
Create a new DisplayEventReceiver callback for onModeRejected
to signal mode rejection from SF to DM so that DM can trigger
a retry.
Add the plumbing through DisplayEventReceiver and EventThread
Bug: 374184110
Test: manual
Flag: com.android.graphics.surfaceflinger.flags.display_config_error_hal
Change-Id: I78515d413bdf2e6e07d6649b7b60df8ced199b19
Signed-off-by: Manasi Navare <navaremanasi@google.com>
-rw-r--r-- | libs/gui/Choreographer.cpp | 4 | ||||
-rw-r--r-- | libs/gui/DisplayEventDispatcher.cpp | 3 | ||||
-rw-r--r-- | libs/gui/include/gui/Choreographer.h | 1 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventDispatcher.h | 2 | ||||
-rw-r--r-- | libs/gui/include/gui/DisplayEventReceiver.h | 6 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/EventThread.cpp | 24 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/EventThread.h | 7 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.cpp | 6 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.h | 4 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 12 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/mock/MockEventThread.h | 2 |
11 files changed, 68 insertions, 3 deletions
diff --git a/libs/gui/Choreographer.cpp b/libs/gui/Choreographer.cpp index 0c8f3fa096..ba50bf83a8 100644 --- a/libs/gui/Choreographer.cpp +++ b/libs/gui/Choreographer.cpp @@ -369,6 +369,10 @@ void Choreographer::dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32 this, to_string(displayId).c_str(), connectedLevel, maxLevel); } +void Choreographer::dispatchModeRejected(PhysicalDisplayId, int32_t) { + LOG_ALWAYS_FATAL("dispatchModeRejected was called but was never registered"); +} + void Choreographer::handleMessage(const Message& message) { switch (message.what) { case MSG_SCHEDULE_CALLBACKS: diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp index c46f9c50ef..68f10f4d80 100644 --- a/libs/gui/DisplayEventDispatcher.cpp +++ b/libs/gui/DisplayEventDispatcher.cpp @@ -211,6 +211,9 @@ bool DisplayEventDispatcher::processPendingEvents(nsecs_t* outTimestamp, ev.hdcpLevelsChange.connectedLevel, ev.hdcpLevelsChange.maxLevel); break; + case DisplayEventReceiver::DISPLAY_EVENT_MODE_REJECTION: + dispatchModeRejected(ev.header.displayId, ev.modeRejection.modeId); + break; default: ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type); break; diff --git a/libs/gui/include/gui/Choreographer.h b/libs/gui/include/gui/Choreographer.h index 2e5aa4a893..a93ba14c57 100644 --- a/libs/gui/include/gui/Choreographer.h +++ b/libs/gui/include/gui/Choreographer.h @@ -127,6 +127,7 @@ private: std::vector<FrameRateOverride> overrides) override; void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel, int32_t maxLevel) override; + void dispatchModeRejected(PhysicalDisplayId displayId, int32_t modeId) override; void scheduleCallbacks(); diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h index 82cd50c7bd..b06ad077f4 100644 --- a/libs/gui/include/gui/DisplayEventDispatcher.h +++ b/libs/gui/include/gui/DisplayEventDispatcher.h @@ -68,6 +68,8 @@ private: virtual void dispatchHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t connectedLevel, int32_t maxLevel) = 0; + virtual void dispatchModeRejected(PhysicalDisplayId displayId, int32_t modeId) = 0; + bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId, uint32_t* outCount, VsyncEventData* outVsyncEventData); diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h index 40a6e79a24..ab6a6b78f7 100644 --- a/libs/gui/include/gui/DisplayEventReceiver.h +++ b/libs/gui/include/gui/DisplayEventReceiver.h @@ -62,6 +62,7 @@ public: DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'), DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'), DISPLAY_EVENT_MODE_CHANGE = fourcc('m', 'o', 'd', 'e'), + DISPLAY_EVENT_MODE_REJECTION = fourcc('r', 'e', 'j', 'e'), DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'), DISPLAY_EVENT_FRAME_RATE_OVERRIDE = fourcc('r', 'a', 't', 'e'), DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH = fourcc('f', 'l', 's', 'h'), @@ -96,6 +97,10 @@ public: nsecs_t vsyncPeriod __attribute__((aligned(8))); }; + struct ModeRejection { + int32_t modeId; + }; + struct FrameRateOverride { uid_t uid __attribute__((aligned(8))); float frameRateHz __attribute__((aligned(8))); @@ -117,6 +122,7 @@ public: ModeChange modeChange; FrameRateOverride frameRateOverride; HdcpLevelsChange hdcpLevelsChange; + ModeRejection modeRejection; }; }; static_assert(sizeof(Event) == 224); diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index fff4284199..c6d7160818 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -43,6 +43,7 @@ #include <utils/Errors.h> #include <common/FlagManager.h> +#include <scheduler/FrameRateMode.h> #include <scheduler/VsyncConfig.h> #include "FrameTimeline.h" #include "VSyncDispatch.h" @@ -102,6 +103,10 @@ std::string toString(const DisplayEventReceiver::Event& event) { to_string(event.header.displayId).c_str(), event.hdcpLevelsChange.connectedLevel, event.hdcpLevelsChange.maxLevel); + case DisplayEventReceiver::DISPLAY_EVENT_MODE_REJECTION: + return StringPrintf("ModeRejected{displayId=%s, modeId=%u}", + to_string(event.header.displayId).c_str(), + event.modeRejection.modeId); default: return "Event{}"; } @@ -186,6 +191,18 @@ DisplayEventReceiver::Event makeHdcpLevelsChange(PhysicalDisplayId displayId, }; } +DisplayEventReceiver::Event makeModeRejection(PhysicalDisplayId displayId, DisplayModeId modeId) { + return DisplayEventReceiver::Event{ + .header = + DisplayEventReceiver::Event::Header{ + .type = DisplayEventReceiver::DISPLAY_EVENT_MODE_REJECTION, + .displayId = displayId, + .timestamp = systemTime(), + }, + .modeRejection.modeId = ftl::to_underlying(modeId), + }; +} + } // namespace EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid, @@ -480,6 +497,13 @@ void EventThread::onHdcpLevelsChanged(PhysicalDisplayId displayId, int32_t conne mCondition.notify_all(); } +void EventThread::onModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) { + std::lock_guard<std::mutex> lock(mMutex); + + mPendingEvents.push_back(makeModeRejection(displayId, modeId)); + mCondition.notify_all(); +} + // Merge lists of buffer stuffed Uids void EventThread::addBufferStuffedUids(BufferStuffingMap bufferStuffedUids) { std::lock_guard<std::mutex> lock(mMutex); diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index 95632c7e66..18bf41643c 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -21,6 +21,7 @@ #include <gui/DisplayEventReceiver.h> #include <private/gui/BitTube.h> #include <sys/types.h> +#include <ui/DisplayId.h> #include <utils/Errors.h> #include <scheduler/FrameRateMode.h> @@ -32,6 +33,7 @@ #include <thread> #include <vector> +#include "DisplayHardware/DisplayMode.h" #include "TracedOrdinal.h" #include "VSyncDispatch.h" #include "VsyncSchedule.h" @@ -115,6 +117,9 @@ public: // called when SF changes the active mode and apps needs to be notified about the change virtual void onModeChanged(const scheduler::FrameRateMode&) = 0; + // called when SF rejects the mode change request + virtual void onModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) = 0; + // called when SF updates the Frame Rate Override list virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId, std::vector<FrameRateOverride> overrides) = 0; @@ -179,6 +184,8 @@ public: void onModeChanged(const scheduler::FrameRateMode&) override; + void onModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) override; + void onFrameRateOverridesChanged(PhysicalDisplayId displayId, std::vector<FrameRateOverride> overrides) override; diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 2875650ed0..86d91d9433 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -465,6 +465,12 @@ bool Scheduler::onDisplayModeChanged(PhysicalDisplayId displayId, const FrameRat } #pragma clang diagnostic pop +void Scheduler::onDisplayModeRejected(PhysicalDisplayId displayId, DisplayModeId modeId) { + if (hasEventThreads()) { + eventThreadFor(Cycle::Render).onModeRejected(displayId, modeId); + } +} + void Scheduler::emitModeChangeIfNeeded() { if (!mPolicy.modeOpt || !mPolicy.emittedModeOpt) { ALOGW("No mode change to emit"); diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 61c68a9473..3fdddac52a 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -36,12 +36,14 @@ #include <ftl/non_null.h> #include <ftl/optional.h> #include <scheduler/Features.h> +#include <scheduler/FrameRateMode.h> #include <scheduler/FrameTargeter.h> #include <scheduler/Time.h> #include <scheduler/VsyncConfig.h> #include <ui/DisplayId.h> #include <ui/DisplayMap.h> +#include "DisplayHardware/DisplayMode.h" #include "EventThread.h" #include "FrameRateOverrideMappings.h" #include "ISchedulerCallback.h" @@ -153,6 +155,8 @@ public: bool onDisplayModeChanged(PhysicalDisplayId, const FrameRateMode&, bool clearContentRequirements) EXCLUDES(mPolicyLock); + void onDisplayModeRejected(PhysicalDisplayId, DisplayModeId); + void enableSyntheticVsync(bool = true) REQUIRES(kMainThreadContext); void omitVsyncDispatching(bool) REQUIRES(kMainThreadContext); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 97c86232f2..0c2922d0ed 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1532,9 +1532,15 @@ void SurfaceFlinger::initiateDisplayModeChanges() { constraints.seamlessRequired = false; hal::VsyncPeriodChangeTimeline outTimeline; - if (mDisplayModeController.initiateModeChange(displayId, std::move(*desiredModeOpt), - constraints, outTimeline) != - display::DisplayModeController::ModeChangeResult::Changed) { + const auto error = + mDisplayModeController.initiateModeChange(displayId, std::move(*desiredModeOpt), + constraints, outTimeline); + if (error != display::DisplayModeController::ModeChangeResult::Changed) { + dropModeRequest(displayId); + if (FlagManager::getInstance().display_config_error_hal() && + error == display::DisplayModeController::ModeChangeResult::Rejected) { + mScheduler->onDisplayModeRejected(displayId, desiredModeId); + } continue; } diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index c976697c08..3036fec456 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -34,6 +34,8 @@ public: 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, onModeRejected, (PhysicalDisplayId displayId, DisplayModeId modeId), + (override)); MOCK_METHOD(void, onFrameRateOverridesChanged, (PhysicalDisplayId, std::vector<FrameRateOverride>), (override)); MOCK_METHOD(void, dump, (std::string&), (const, override)); |