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>
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index fff4284..c6d7160 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 @@
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 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 @@
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 95632c7..18bf416 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 @@
// 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 @@
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 2875650..86d91d9 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -465,6 +465,12 @@
}
#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 61c68a9..3fdddac 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 @@
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 97c8623..0c2922d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1532,9 +1532,15 @@
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 c976697..3036fec 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -34,6 +34,8 @@
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));