diff --git a/minui/graphics.cpp b/minui/graphics.cpp index b24c2b11..41a36611 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -502,3 +502,7 @@ void gr_fb_blank(bool blank, int index) { void gr_rotate(GRRotation rot) { rotation = rot; } + +bool gr_has_multiple_connectors() { + return gr_backend->HasMultipleConnectors(); +} diff --git a/minui/graphics.h b/minui/graphics.h index 5408c93e..ff063ae2 100644 --- a/minui/graphics.h +++ b/minui/graphics.h @@ -40,8 +40,11 @@ class MinuiBackend { // Blank (or unblank) the specific screen. virtual void Blank(bool blank, DrmConnector index) = 0; + // Return true if the device supports multiple connectors. + virtual bool HasMultipleConnectors() = 0; + // Device cleanup when drawing is done. - virtual ~MinuiBackend() {}; + virtual ~MinuiBackend() = default; }; #endif // _GRAPHICS_H_ diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp index c5570227..6c3a5bde 100644 --- a/minui/graphics_drm.cpp +++ b/minui/graphics_drm.cpp @@ -200,6 +200,10 @@ void MinuiBackendDrm::Blank(bool blank, DrmConnector index) { } } +bool MinuiBackendDrm::HasMultipleConnectors() { + return (drm[DRM_SEC].GRSurfaceDrms[0] && drm[DRM_SEC].GRSurfaceDrms[1]); +} + static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources, drmModeConnector* connector) { // Find the encoder. If we already have one, just use it. diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h index fe3beaff..a8c9886e 100644 --- a/minui/graphics_drm.h +++ b/minui/graphics_drm.h @@ -60,6 +60,7 @@ class MinuiBackendDrm : public MinuiBackend { GRSurface* Flip() override; void Blank(bool) override; void Blank(bool blank, DrmConnector index) override; + bool HasMultipleConnectors() override; private: void DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc); diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp index 1cb0c0ab..4a7d3252 100644 --- a/minui/graphics_fbdev.cpp +++ b/minui/graphics_fbdev.cpp @@ -47,6 +47,11 @@ void MinuiBackendFbdev::Blank(bool blank, DrmConnector index) { fprintf(stderr, "Unsupported multiple connectors, blank = %d, index = %d\n", blank, index); } +bool MinuiBackendFbdev::HasMultipleConnectors() { + fprintf(stderr, "Unsupported multiple connectors\n"); + return false; +} + void MinuiBackendFbdev::SetDisplayedFramebuffer(size_t n) { if (n > 1 || !double_buffered) return; diff --git a/minui/graphics_fbdev.h b/minui/graphics_fbdev.h index 7e193c4f..c772428d 100644 --- a/minui/graphics_fbdev.h +++ b/minui/graphics_fbdev.h @@ -57,6 +57,7 @@ class MinuiBackendFbdev : public MinuiBackend { GRSurface* Flip() override; void Blank(bool) override; void Blank(bool blank, DrmConnector index) override; + bool HasMultipleConnectors() override; private: void SetDisplayedFramebuffer(size_t n); diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h index f9be82f5..2353ed3b 100644 --- a/minui/include/minui/minui.h +++ b/minui/include/minui/minui.h @@ -129,6 +129,7 @@ int gr_fb_height(); void gr_flip(); void gr_fb_blank(bool blank); void gr_fb_blank(bool blank, int index); +bool gr_has_multiple_connectors(); // Clears entire surface to current color. void gr_clear(); diff --git a/recovery_ui/include/recovery_ui/screen_ui.h b/recovery_ui/include/recovery_ui/screen_ui.h index 92b3c254..99ad5342 100644 --- a/recovery_ui/include/recovery_ui/screen_ui.h +++ b/recovery_ui/include/recovery_ui/screen_ui.h @@ -245,6 +245,9 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface { const std::vector& backup_headers, const std::vector& backup_items, const std::function& key_handler) override; + // For Lid switch handle + int SetSwCallback(int code, int value) override; + protected: static constexpr int kMenuIndent = 4; @@ -404,6 +407,9 @@ class ScreenRecoveryUI : public RecoveryUI, public DrawInterface { std::mutex updateMutex; + // Switch the display to active one after graphics is ready + bool is_graphics_available; + private: void SetLocale(const std::string&); diff --git a/recovery_ui/include/recovery_ui/stub_ui.h b/recovery_ui/include/recovery_ui/stub_ui.h index 511b1314..49689ba3 100644 --- a/recovery_ui/include/recovery_ui/stub_ui.h +++ b/recovery_ui/include/recovery_ui/stub_ui.h @@ -80,6 +80,10 @@ class StubRecoveryUI : public RecoveryUI { } void SetTitle(const std::vector& /* lines */) override {} + + int SetSwCallback(int /* code */, int /* value */) override { + return 0; + } }; #endif // RECOVERY_STUB_UI_H diff --git a/recovery_ui/include/recovery_ui/ui.h b/recovery_ui/include/recovery_ui/ui.h index 512732f9..c3e3ee26 100644 --- a/recovery_ui/include/recovery_ui/ui.h +++ b/recovery_ui/include/recovery_ui/ui.h @@ -231,6 +231,8 @@ class RecoveryUI { bool InitScreensaver(); void SetScreensaverState(ScreensaverState state); + virtual int SetSwCallback(int code, int value) = 0; + // Key event input queue std::mutex key_queue_mutex; std::condition_variable key_queue_cond; diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp index b2c828f3..ee3cbb13 100644 --- a/recovery_ui/screen_ui.cpp +++ b/recovery_ui/screen_ui.cpp @@ -48,6 +48,11 @@ #include "recovery_ui/device.h" #include "recovery_ui/ui.h" +enum DirectRenderManager { + DRM_INNER, + DRM_OUTER, +}; + // Return the current time as a double (including fractions of a second). static double now() { struct timeval tv; @@ -334,7 +339,8 @@ ScreenRecoveryUI::ScreenRecoveryUI(bool scrollable_menu) stage(-1), max_stage(-1), locale_(""), - rtl_locale_(false) {} + rtl_locale_(false), + is_graphics_available(false) {} ScreenRecoveryUI::~ScreenRecoveryUI() { progress_thread_stopped_ = true; @@ -906,6 +912,7 @@ bool ScreenRecoveryUI::Init(const std::string& locale) { if (!InitGraphics()) { return false; } + is_graphics_available = true; if (!InitTextParams()) { return false; @@ -950,6 +957,9 @@ bool ScreenRecoveryUI::Init(const std::string& locale) { // Keep the progress bar updated, even when the process is otherwise busy. progress_thread_ = std::thread(&ScreenRecoveryUI::ProgressThreadLoop, this); + // set the callback for hall sensor event + (void)ev_sync_sw_state([this](auto&& a, auto&& b) { return this->SetSwCallback(a, b);}); + return true; } @@ -1367,3 +1377,45 @@ void ScreenRecoveryUI::SetLocale(const std::string& new_locale) { } } } + +int ScreenRecoveryUI::SetSwCallback(int code, int value) { + if (!is_graphics_available) { return -1; } + if (code > SW_MAX) { return -1; } + if (code != SW_LID) { return 0; } + + /* detect dual display */ + if (!gr_has_multiple_connectors()) { return -1; } + + /* turn off all screen */ + gr_fb_blank(true, DirectRenderManager::DRM_INNER); + gr_fb_blank(true, DirectRenderManager::DRM_OUTER); + gr_color(0, 0, 0, 255); + gr_clear(); + + /* turn on the screen */ + gr_fb_blank(false, value); + gr_flip(); + + /* set the retation */ + std::string rotation_str; + if (value == DirectRenderManager::DRM_OUTER) { + rotation_str = + android::base::GetProperty("ro.minui.second_rotation", "ROTATION_NONE"); + } else { + rotation_str = + android::base::GetProperty("ro.minui.default_rotation", "ROTATION_NONE"); + } + + if (rotation_str == "ROTATION_RIGHT") { + gr_rotate(GRRotation::RIGHT); + } else if (rotation_str == "ROTATION_DOWN") { + gr_rotate(GRRotation::DOWN); + } else if (rotation_str == "ROTATION_LEFT") { + gr_rotate(GRRotation::LEFT); + } else { // "ROTATION_NONE" or unknown string + gr_rotate(GRRotation::NONE); + } + Redraw(); + + return 0; +} diff --git a/recovery_ui/ui.cpp b/recovery_ui/ui.cpp index 6e67b1d4..eb87f526 100644 --- a/recovery_ui/ui.cpp +++ b/recovery_ui/ui.cpp @@ -341,6 +341,11 @@ int RecoveryUI::OnInputEvent(int fd, uint32_t epevents) { ProcessKey(ev.code, ev.value); } + // For Lid switch handle + if (ev.type == EV_SW) { + SetSwCallback(ev.code, ev.value); + } + return 0; }