drm_hwcomposer: Add headless mode support
Headless mode required to keep SurfaceFlinger alive when all displays are
disconnected, Without headless mode Android will continuously crash.
Only single internal (primary) display is required to be in HEADLESS mode
to prevent the crash. See [1].
[1]: https://source.android.com/devices/graphics/hotplug#handling-common-scenarios
Closes: https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer/-/issues/57
Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/hwc2_device/HwcDisplayConfigs.cpp b/hwc2_device/HwcDisplayConfigs.cpp
index e3d17a2..16f1ed0 100644
--- a/hwc2_device/HwcDisplayConfigs.cpp
+++ b/hwc2_device/HwcDisplayConfigs.cpp
@@ -23,10 +23,38 @@
#include "drm/DrmConnector.h"
#include "utils/log.h"
+constexpr uint32_t kHeadlessModeDisplayWidthMm = 163;
+constexpr uint32_t kHeadlessModeDisplayHeightMm = 122;
+constexpr uint32_t kHeadlessModeDisplayWidthPx = 1024;
+constexpr uint32_t kHeadlessModeDisplayHeightPx = 768;
+constexpr uint32_t kHeadlessModeDisplayVRefresh = 60;
+
namespace android {
// NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
HWC2::Error HwcDisplayConfigs::Update(DrmConnector &connector) {
+ /* In case UpdateModes will fail we will still have one mode for headless
+ * mode*/
+ hwc_configs.clear();
+
+ last_config_id++;
+ preferred_config_id = active_config_id = last_config_id;
+ auto headless_drm_mode_info = (drmModeModeInfo){
+ .hdisplay = kHeadlessModeDisplayWidthPx,
+ .vdisplay = kHeadlessModeDisplayHeightPx,
+ .vrefresh = kHeadlessModeDisplayVRefresh,
+ .name = "HEADLESS-MODE",
+ };
+ hwc_configs[active_config_id] = (HwcDisplayConfig){
+ .id = active_config_id,
+ .group_id = 1,
+ .mode = DrmMode(&headless_drm_mode_info),
+ };
+
+ mm_width = kHeadlessModeDisplayWidthMm;
+ mm_height = kHeadlessModeDisplayHeightMm;
+
+ /* Read real configs */
int ret = connector.UpdateModes();
if (ret != 0) {
ALOGE("Failed to update display modes %d", ret);
@@ -39,6 +67,9 @@
}
hwc_configs.clear();
+ mm_width = connector.mm_width();
+ mm_height = connector.mm_height();
+
preferred_config_id = 0;
int preferred_config_group_id = 0;
@@ -159,6 +190,8 @@
}
}
+ /* Set active mode to be valid mode */
+ active_config_id = preferred_config_id;
return HWC2::Error::None;
}