diff --git a/.depend b/.depend
index 3ce7b09b..34b6b73b 100644
--- a/.depend
+++ b/.depend
@@ -168,6 +168,18 @@ mce-dsme.pic.o:\
mce-log.h\
mce.h\
+mce-fbdev.o:\
+ mce-fbdev.c\
+ mce-fbdev.h\
+ mce-hybris.h\
+ mce-log.h\
+
+mce-fbdev.pic.o:\
+ mce-fbdev.c\
+ mce-fbdev.h\
+ mce-hybris.h\
+ mce-log.h\
+
mce-gconf.o:\
mce-gconf.c\
builtin-gconf.h\
@@ -295,6 +307,7 @@ mce.o:\
mce-conf.h\
mce-dbus.h\
mce-dsme.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-log.h\
mce-modules.h\
@@ -315,6 +328,7 @@ mce.pic.o:\
mce-conf.h\
mce-dbus.h\
mce-dsme.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-log.h\
mce-modules.h\
@@ -494,6 +508,7 @@ modules/display.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -511,6 +526,7 @@ modules/display.pic.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -831,6 +847,7 @@ tests/ut/ut_display.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-io.h\
mce-lib.h\
@@ -850,6 +867,7 @@ tests/ut/ut_display.pic.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-io.h\
mce-lib.h\
@@ -869,6 +887,7 @@ tests/ut/ut_display_blanking_inhibit.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -889,6 +908,7 @@ tests/ut/ut_display_blanking_inhibit.pic.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -909,6 +929,7 @@ tests/ut/ut_display_conf.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -929,6 +950,7 @@ tests/ut/ut_display_conf.pic.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -949,6 +971,7 @@ tests/ut/ut_display_filter.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -969,6 +992,7 @@ tests/ut/ut_display_filter.pic.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -989,6 +1013,7 @@ tests/ut/ut_display_stm.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
@@ -1009,6 +1034,7 @@ tests/ut/ut_display_stm.pic.o:\
libwakelock.h\
mce-conf.h\
mce-dbus.h\
+ mce-fbdev.h\
mce-gconf.h\
mce-hybris.h\
mce-io.h\
diff --git a/Makefile b/Makefile
index cb1193e5..862b1228 100644
--- a/Makefile
+++ b/Makefile
@@ -282,6 +282,7 @@ MCE_LDLIBS += $(MCE_PKG_LDLIBS)
MCE_CORE += tklock.c
MCE_CORE += modetransition.c
MCE_CORE += powerkey.c
+MCE_CORE += mce-fbdev.c
MCE_CORE += mce-dbus.c
MCE_CORE += mce-dsme.c
MCE_CORE += mce-gconf.c
@@ -542,6 +543,8 @@ NORMALIZE_USES_SPC =\
filewatcher.c\
filewatcher.h\
libwakelock.h\
+ mce-fbdev.c\
+ mce-fbdev.h\
mce-command-line.c\
mce-command-line.h\
mce-hybris.c\
diff --git a/mce-fbdev.c b/mce-fbdev.c
new file mode 100644
index 00000000..16883228
--- /dev/null
+++ b/mce-fbdev.c
@@ -0,0 +1,281 @@
+/**
+ * @file mce-fbdev.c
+ * Frame buffer device handling code for the Mode Control Entity
+ *
+ * Copyright 2015 Jolla Ltd.
+ *
+ * @author Simo Piiroinen
+ *
+ * mce is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * mce is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mce. If not, see .
+ */
+
+#include "mce-fbdev.h"
+#include "mce-log.h"
+
+#ifdef ENABLE_HYBRIS
+# include "mce-hybris.h"
+#endif
+
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* ========================================================================= *
+ * CONSTANTS
+ * ========================================================================= */
+
+/** Path to the framebuffer device */
+#define FB_DEVICE "/dev/fb0"
+
+/* ========================================================================= *
+ * STATE_DATA
+ * ========================================================================= */
+
+/** File descriptor for frame buffer device */
+static int mce_fbdev_handle = -1;
+
+/** Flag for: use hybris for fb power control */
+#ifdef ENABLE_HYBRIS
+static bool fbdev_use_hybris = false;
+#endif
+
+/** Flag for: Opening frame buffer device is allowed */
+static bool mce_fbdev_allow_open = false;
+
+/* ========================================================================= *
+ * FBDEV_FILE_DESCRIPTOR
+ * ========================================================================= */
+
+/** Frame buffer is open predicate
+ *
+ * @return true if frame buffer device is currently opened, false otherwise
+ */
+bool mce_fbdev_is_open(void)
+{
+ return mce_fbdev_handle != -1;
+}
+
+/** Open frame buffer device unless denied
+ *
+ * @return true on success, or false on failure
+ */
+bool mce_fbdev_open(void)
+{
+#ifdef ENABLE_HYBRIS
+ if( fbdev_use_hybris )
+ goto EXIT;
+#endif
+
+ if( mce_fbdev_handle != -1 )
+ goto EXIT;
+
+ if( !mce_fbdev_allow_open )
+ goto EXIT;
+
+ mce_log(LL_NOTICE, "open frame buffer device");
+
+ if( (mce_fbdev_handle = open(FB_DEVICE, O_RDWR)) == -1 ) {
+ if( errno != ENOENT )
+ mce_log(LL_WARN, "failed to open frame buffer device: %m");
+ goto EXIT;
+ }
+
+ mce_log(LL_DEBUG, "frame buffer device opened");
+
+EXIT:
+ return mce_fbdev_handle != -1;
+}
+
+/** Close frame buffer device
+ */
+void mce_fbdev_close(void)
+{
+ if( mce_fbdev_handle == -1 )
+ goto EXIT;
+
+ mce_log(LL_NOTICE, "closing frame buffer device");
+ close(mce_fbdev_handle), mce_fbdev_handle = -1;
+ mce_log(LL_DEBUG, "closed frame buffer device");
+
+EXIT:
+ return;
+}
+
+/** Reopen frame buffer device unless denied
+ */
+void mce_fbdev_reopen(void)
+{
+ if( mce_fbdev_allow_open )
+ mce_fbdev_close();
+
+ mce_fbdev_open();
+}
+
+/* ========================================================================= *
+ * POST_EXIT_LINGER
+ * ========================================================================= */
+
+/** Create a child process to keep frame buffer device open after mce exits
+ *
+ * The frame buffer device powers off automatically when the last open
+ * file descriptor gets closed.
+ *
+ * To allow the shutdown logo to stay on screen after lipstick and mce
+ * have been terminated, we create a detached child process that hangs
+ * on to frame buffer device.
+ *
+ * @param delay_ms how long the child process should linger
+ */
+void mce_fbdev_linger_after_exit(int delay_ms)
+{
+ static const char msg[] = "closing frame buffer device after delay\n";
+
+ /* Fork a child process */
+
+ int child_pid = fork();
+
+ /* Deal with parent side and return to caller */
+
+ if( child_pid != 0 ) {
+ if( child_pid < 0 )
+ mce_log(LL_ERR, "forking fbdev linger child failed: %m");
+ else
+ mce_log(LL_DEBUG, "fbdev linger child: pid %d", child_pid);
+ return;
+ }
+
+ /* Detach from parent so that we will not get killed with it */
+
+ setsid();
+
+ /* Close all files, except fbdev & stderr */
+
+ int nfd = getdtablesize();
+ for( int fd = 0; fd < nfd; ++fd ) {
+ if( fd != mce_fbdev_handle && fd != STDERR_FILENO )
+ close(fd);
+ }
+
+ if( delay_ms < 500 )
+ delay_ms = 500;
+
+ /* Wait ... */
+
+ struct timespec ts =
+ {
+ .tv_sec = (time_t)(delay_ms / 1000),
+ .tv_nsec = (long)(delay_ms % 1000) * 1000000,
+ };
+
+ while( nanosleep(&ts, &ts) == -1 && errno == EINTR ) { /* nop */ }
+
+ /* If journald is still up, the end-of-linger message written to stderr
+ * ends up in journal and attributed to parent mce process.
+ *
+ * ... and in case journald has already made an exit, we do not want
+ * to die by SIGPIPE, so it needs to be ignored. */
+
+ signal(SIGPIPE, SIG_IGN);
+
+ if( write(STDERR_FILENO, msg, sizeof msg - 1) < 0 ) { /* dontcare */ }
+
+ /* Exit - the frame buffer device will power off if we
+ * were the last process to have an open file descriptor */
+
+ _exit(EXIT_SUCCESS);
+}
+
+/* ========================================================================= *
+ * FRAMEBUFFER_POWER
+ * ========================================================================= */
+
+/** Set the frame buffer power state
+ *
+ * MCE uses this function for display power control only if autosuspend
+ * control sysfs files are not present.
+ *
+ * If there is a hw composer that is also doing fbdev ioctl() calls,
+ * there is some change that kernel side troubles can be caused by
+ * having two entities trying to control the same resource.
+ *
+ * @param power_in true to power up, false to power down
+ */
+void mce_fbdev_set_power(bool power_on)
+{
+ mce_log(LL_DEBUG, "fbdev power %s", power_on ? "up" : "down");
+
+ if( mce_fbdev_handle != -1 ) {
+ int value = power_on ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+
+ if( ioctl(mce_fbdev_handle, FBIOBLANK, value) == -1 )
+ mce_log(LL_ERR, "%s: ioctl(FBIOBLANK,%d): %m", FB_DEVICE, value);
+ else
+ mce_log(LL_DEBUG, "success");
+ }
+#ifdef ENABLE_HYBRIS
+ else if( fbdev_use_hybris ) {
+ mce_hybris_framebuffer_set_power(power_on);
+ }
+#endif
+
+ return;
+}
+
+/* ========================================================================= *
+ * MODULE_INIT
+ * ========================================================================= */
+
+/** Initialize frame buffer module
+ */
+void mce_fbdev_init(void)
+{
+ /* allow opening frame buffer device */
+ mce_fbdev_allow_open = true;
+
+ if( mce_fbdev_open() ) {
+ mce_log(LL_NOTICE, "using ioctl for fb power control");
+ }
+#ifdef ENABLE_HYBRIS
+ else if( mce_hybris_framebuffer_init() ) {
+ mce_log(LL_NOTICE, "using libhybris for fb power control");
+ fbdev_use_hybris = true;
+ }
+#endif
+ else {
+ mce_log(LL_WARN, "no fb power control available");;
+ }
+}
+
+/** De-initialize frame buffer module
+ */
+void mce_fbdev_quit(void)
+{
+ /* deny opening frame buffer device */
+ mce_fbdev_allow_open = false;
+
+ mce_fbdev_close();
+
+#ifdef ENABLE_HYBRIS
+ if( fbdev_use_hybris ) {
+ fbdev_use_hybris = false;
+ mce_hybris_framebuffer_quit();
+ }
+#endif
+}
diff --git a/mce-fbdev.h b/mce-fbdev.h
new file mode 100644
index 00000000..03f09f54
--- /dev/null
+++ b/mce-fbdev.h
@@ -0,0 +1,47 @@
+/**
+ * @file mce-fbdev.h
+ * Frame buffer device handling code for the Mode Control Entity
+ *
+ * Copyright 2015 Jolla Ltd.
+ *
+ * @author Simo Piiroinen
+ *
+ * mce is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * mce is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mce. If not, see .
+ */
+
+#ifndef MCE_FBDEV_H_
+# define MCE_FBDEV_H_
+
+# include
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+void mce_fbdev_init (void);
+void mce_fbdev_quit (void);
+
+bool mce_fbdev_open (void);
+void mce_fbdev_close (void);
+void mce_fbdev_reopen (void);
+bool mce_fbdev_is_open (void);
+
+void mce_fbdev_set_power (bool power_on);
+
+void mce_fbdev_linger_after_exit (int delay_ms);
+
+# ifdef __cplusplus
+};
+# endif
+
+#endif /* MCE_FBDEV_H_ */
diff --git a/mce.c b/mce.c
index 91477dae..943abd0d 100644
--- a/mce.c
+++ b/mce.c
@@ -22,6 +22,7 @@
#include "mce.h"
#include "mce-log.h"
#include "mce-conf.h"
+#include "mce-fbdev.h"
#include "mce-gconf.h"
#include "mce-dbus.h"
#include "mce-dsme.h"
@@ -969,6 +970,9 @@ int main(int argc, char **argv)
/* Initialise subsystems */
+ /* Open fbdev as early as possible */
+ mce_fbdev_init();
+
/* Get configuration options */
if( !mce_conf_init() ) {
mce_log(LL_CRIT,
@@ -1091,6 +1095,7 @@ int main(int argc, char **argv)
mce_gconf_exit();
mce_dbus_exit();
mce_conf_exit();
+ mce_fbdev_quit();
/* If the mainloop is initialised, unreference it */
if (mainloop != NULL) {
diff --git a/modules/display.c b/modules/display.c
index b0191427..fbff5b2a 100644
--- a/modules/display.c
+++ b/modules/display.c
@@ -26,6 +26,7 @@
#include "../mce-log.h"
#include "../mce-io.h"
#include "../mce-lib.h"
+#include "../mce-fbdev.h"
#include "../mce-conf.h"
#include "../mce-gconf.h"
#include "../mce-dbus.h"
@@ -40,10 +41,7 @@
# include "../libwakelock.h"
#endif
-#include
-
#include
-#include
#include
#include
@@ -294,22 +292,7 @@ static void mdy_datapipe_quit(void);
* FBDEV_FD
* ------------------------------------------------------------------------- */
-static bool fbdev_fd_is_open(void);
-static int fbdev_fd_open(void);
-static void fbdev_fd_close(void);
-static void fbdev_fd_close_forever(void);
-static void fbdev_fd_close_after_exit(void);
-
-/* ------------------------------------------------------------------------- *
- * FBDEV_POWER_STATE
- * ------------------------------------------------------------------------- */
-
-#ifdef ENABLE_HYBRIS
-static void mdy_fbdev_set_power_hybris(int value);
-static void mdy_fbdev_set_power_dummy(int value);
-#endif
-static void mdy_fbdev_set_power_default(int value);
-static void mdy_fbdev_set_power(int value);
+static void mdy_fbdev_rethink(void);
/* ------------------------------------------------------------------------- *
* HIGH_BRIGHTNESS_MODE
@@ -752,13 +735,14 @@ static void mdy_shutdown_set_state(bool in_progress)
if( (mdy_shutdown_started_flag = in_progress) ) {
mce_log(LL_DEVEL, "Shutdown started");
mdy_shutdown_started_tick = mdy_get_boot_tick();
- fbdev_fd_open();
}
else {
mce_log(LL_DEVEL, "Shutdown canceled");
- fbdev_fd_close();
}
+ /* Framebuffer must be kept open during shutdown */
+ mdy_fbdev_rethink();
+
EXIT:
return;
}
@@ -1039,11 +1023,6 @@ static void mdy_datapipe_system_state_cb(gconstpointer data)
USE_INDATA, CACHE_INDATA);
#endif
- /* Stable state reached after mce/device startup.
- * There is ui in place and we can close the fbdev
- * (even if there is no shutdown to cancel). */
- fbdev_fd_close();
-
/* Re-entry to actdead/user also means shutdown
* has been cancelled */
mdy_shutdown_set_state(false);
@@ -1062,6 +1041,9 @@ static void mdy_datapipe_system_state_cb(gconstpointer data)
/* re-evaluate suspend policy */
mdy_stm_schedule_rethink();
+ /* Deal with ACTDEAD alarms / not in USER mode */
+ mdy_fbdev_rethink();
+
#ifdef ENABLE_CPU_GOVERNOR
mdy_governor_rethink();
#endif
@@ -1422,9 +1404,15 @@ static void mdy_datapipe_alarm_ui_state_cb(gconstpointer data)
if( alarm_ui_state == prev )
goto EXIT;
- mce_log(LL_DEBUG, "alarm_ui_state = %s",
+ mce_log(LL_DEBUG, "alarm_ui_state: %s -> %s",
+ alarm_state_repr(prev),
alarm_state_repr(alarm_ui_state));
+ /* Act dead alarm ui does not implement compositor service.
+ * Open/close fbdevice as if compositor were started/stopped
+ * based on alarm ui state changes */
+ mdy_fbdev_rethink();
+
mdy_blanking_rethink_timers(false);
// suspend policy
@@ -1753,228 +1741,77 @@ static void mdy_datapipe_quit(void)
* FBDEV_FD
* ========================================================================= */
-/** File descriptor for frame buffer device */
-static int fbdev_fd_handle = -1;
-
-/** Flag for: Opening frame buffer device is denied */
-static bool fbdev_fd_deny_open = false;
-
-/** Frame buffer is open predicate
- */
-static bool fbdev_fd_is_open(void)
-{
- return fbdev_fd_handle != -1;
-}
-
-/** Open frame buffer device unless denied
+/** Decide whether frame buffer device should be kept open or not
+ *
+ * Having mce keep frame buffer device open during startup makes
+ * it possible to make transition from boot logo to ui without
+ * the display blanking in between.
+ *
+ * And similarly during shutdown/reboot the shutdown logo stays
+ * visible after ui processes that drew it has been terminated.
+ *
+ * However we need to release the device file descriptor if ui
+ * side happens to make unexpected exit, otherwise the stale
+ * unresponsive ui would remain on screen.
+ *
+ * And act dead alarms are a special case, because there we have
+ * ui that does compositor dbus inteface (act dead charging ui)
+ * getting replaced with one that does not (act dead alarms ui).
*/
-static int fbdev_fd_open(void)
+static void mdy_fbdev_rethink(void)
{
- if( fbdev_fd_handle != -1 )
- goto EXIT;
+ // have we seen compositor since mce startup
+ static bool compositor_was_available = false;
- if( fbdev_fd_deny_open )
- goto EXIT;
+ // assume framebuffer device should be kept open
+ bool can_close = false;
- if( (fbdev_fd_handle = open(FB_DEVICE, O_RDWR)) == -1 ) {
- mce_log(LL_ERR, "Failed to open %s: %m", FB_DEVICE);
+ // do not close if compositor is up
+ if( mdy_compositor_is_available() ) {
+ compositor_was_available = true;
goto EXIT;
}
- mce_log(LL_DEBUG, "opened frame buffer device");
-
-EXIT:
- return fbdev_fd_handle;
-}
-
-/** Close frame buffer device
- */
-static void fbdev_fd_close(void)
-{
- if( fbdev_fd_handle == -1 )
+ // do not close if compositor has not yet been up
+ if( !compositor_was_available )
goto EXIT;
- mce_log(LL_DEBUG, "closing frame buffer device");
- close(fbdev_fd_handle), fbdev_fd_handle = -1;
-
-EXIT:
- return;
-}
-
-/** Close frame buffer device and deny opening again
- */
-static void fbdev_fd_close_forever(void)
-{
- fbdev_fd_deny_open = true;
- fbdev_fd_close();
-}
-
-/** Create a child process to frame buffer device open after mce exits
- */
-static void fbdev_fd_close_after_exit(void)
-{
- static const char msg[] = "closing frame buffer device after delay\n";
-
- /* Fork a child process */
-
- int child_pid = fork();
-
- /* Deal with parent side and return to caller */
-
- if( child_pid != 0 ) {
- if( child_pid < 0 )
- mce_log(LL_ERR, "forking fbdev linger child failed: %m");
- else
- mce_log(LL_DEBUG, "fbdev linger child: pid %d", child_pid);
- return;
- }
-
- /* Detach from parent so that we will not get killed with it */
-
- setsid();
-
- /* Close all files, except fbdev & stderr */
-
- int nfd = getdtablesize();
- for( int fd = 0; fd < nfd; ++fd ) {
- if( fd != fbdev_fd_handle && fd != STDERR_FILENO )
- close(fd);
- }
-
- /* Calculate when to release fbdev file descriptor
- *
- * use max(shutdown_started + 6.0 s, current_time + 0.5 s)
- */
-
- int64_t delay = mdy_shutdown_started_tick + 6000 - mdy_get_boot_tick();
-
- if( delay < 500 )
- delay = 500;
-
- /* Wait ... */
-
- struct timespec ts =
- {
- .tv_sec = (time_t)(delay / 1000),
- .tv_nsec = (long)(delay % 1000) * 1000000,
- };
-
- while( nanosleep(&ts, &ts) == -1 && errno == EINTR ) { /* nop */ }
-
- /* If journald is still up, the end-of-linger message written to stderr
- * ends up in journal and attributed to parent mce process.
- *
- * ... and in case journald has already made an exit, we do not want
- * to die by SIGPIPE, so it needs to be ignored. */
-
- signal(SIGPIPE, SIG_IGN);
-
- if( write(STDERR_FILENO, msg, sizeof msg - 1) < 0 ) { /* dontcare */ }
-
- /* Exit - the frame buffer device will power off if we
- * were the last process to have an open file descriptor */
-
- _exit(EXIT_SUCCESS);
-}
-
-/* ========================================================================= *
- * FBDEV_POWER_STATE
- * ========================================================================= */
-
-/** Hook for setting the frame buffer power state
- *
- * For use from mdy_fbdev_set_power() only
- *
- * @param value The ioctl value to pass to the backlight
- */
-static void (*mdy_fbdev_set_power_hook)(int value) = 0;
-
-#ifdef ENABLE_HYBRIS
-/** Libhybris backend for mdy_fbdev_set_power()
- *
- * @param value FB_BLANK_POWERDOWN or FB_BLANK_UNBLANK
- */
-static void mdy_fbdev_set_power_hybris(int value)
-{
- static int old_value = -1;
-
- if( old_value == value )
+ // do not close during shutdown
+ if( mdy_shutdown_in_progress() )
goto EXIT;
- switch( value ) {
- case FB_BLANK_POWERDOWN:
- mce_hybris_framebuffer_set_power(false);
- break;
-
- case FB_BLANK_UNBLANK:
- mce_hybris_framebuffer_set_power(true);
- break;
-
- default:
- mce_log(LL_WARN, "ignoring unknown ioctl value %d", value);
- break;
+ if( system_state == MCE_STATE_ACTDEAD ) {
+ // or when there are act dead alarms
+ switch( alarm_ui_state ) {
+ case MCE_ALARM_UI_RINGING_INT32:
+ case MCE_ALARM_UI_VISIBLE_INT32:
+ goto EXIT;
+ default:
+ break;
+ }
}
-
- mce_log(LL_DEBUG, "value %d -> %d", old_value, value);
- old_value = value;
-
-EXIT:
- return;
-}
-/** Dummy backend for mdy_fbdev_set_power()
- *
- * Used in cases where mce should not touch frame buffer
- * power state.
- *
- * @param value (not used)
- * @return TRUE for faked success
- */
-static void mdy_fbdev_set_power_dummy(int value)
-{
- (void)value;
-}
-#endif /* ENABLE_HYBRIS */
-
-/** FBIOBLANK backend for mdy_fbdev_set_power()
- *
- * @param value The ioctl value to pass to the backlight
- * @return TRUE on success, FALSE on failure
- */
-static void mdy_fbdev_set_power_default(int value)
-{
- static int old_value = -1;
-
- int fd = fbdev_fd_open();
-
- if( fd == -1 )
+ else if( system_state != MCE_STATE_USER ) {
+ // or we are not in USER/ACT_DEAD
goto EXIT;
+ }
- if( old_value == value )
+ // and since the whole close + reopen is needed only to
+ // clear the display when something potentially has left
+ // stale ui on screen - we skip it if the display is not
+ // firmly in powered up state
+ if( display_state != display_state_next )
goto EXIT;
-
- if( ioctl(fd, FBIOBLANK, value) == -1 ) {
- mce_log(LL_ERR, "%s: ioctl(FBIOBLANK,%d): %m", FB_DEVICE, value);
- close(fd), fd = -1;
+ if( !mdy_stm_display_state_needs_power(display_state) )
goto EXIT;
- }
- old_value = value;
+ can_close = true;
EXIT:
- return;
-}
-/** Set the frame buffer power state
- *
- * @param value The ioctl value to pass to the backlight
- * @return TRUE on success, FALSE on failure
- */
-static void mdy_fbdev_set_power(int value)
-{
- if( mdy_fbdev_set_power_hook )
- mdy_fbdev_set_power_hook(value);
+ if( can_close )
+ mce_fbdev_close();
else
- mce_log(LL_ERR, "value = %d before initializing hook", value);
+ mce_fbdev_open();
}
/* ========================================================================= *
@@ -4176,15 +4013,6 @@ static gboolean mdy_display_type_get_from_hybris(display_type_t *display_type)
mdy_brightness_level_maximum = 255;
*display_type = DISPLAY_TYPE_GENERIC;
- if( !mce_hybris_framebuffer_init() ) {
- mce_log(LL_NOTICE, "libhybris fb power controls not available; using dummy");
- mdy_fbdev_set_power_hook = mdy_fbdev_set_power_dummy;
- }
- else {
- mce_log(LL_NOTICE, "using libhybris for fb power control");
- mdy_fbdev_set_power_hook = mdy_fbdev_set_power_hybris;
- }
-
res = TRUE;
EXIT:
return res;
@@ -4307,9 +4135,6 @@ static display_type_t mdy_display_type_get(void)
mce_log(LL_DEBUG, "Display type: %d", display_type);
- /* Default to using ioctl() for frame buffer power control */
- if( !mdy_fbdev_set_power_hook )
- mdy_fbdev_set_power_hook = mdy_fbdev_set_power_default;
EXIT:
return display_type;
}
@@ -5742,6 +5567,12 @@ static void mdy_datapipe_compositor_available_cb(gconstpointer aptr)
mdy_compositor_name_owner_set(curr);
+ /* If compositor drops from systembus in USER/ACTDEAD mode while
+ * we are not shutting down, assume we are dealing with lipstick
+ * crash / act-dead-charging stop and power cycling the frame
+ buffer is needed to clear zombie ui off the screen. */
+ mdy_fbdev_rethink();
+
/* set setUpdatesEnabled(true) needs to be called flag */
mdy_stm_enable_rendering_needed = true;
@@ -5852,10 +5683,10 @@ static void mdy_stm_start_fb_suspend(void)
if( mdy_waitfb_data.thread )
wakelock_allow_suspend();
else
- mdy_waitfb_data.suspended = true, mdy_fbdev_set_power(FB_BLANK_POWERDOWN);
+ mdy_waitfb_data.suspended = true, mce_fbdev_set_power(false);
#else
mce_log(LL_NOTICE, "power off frame buffer");
- mdy_waitfb_data.suspended = true, mdy_fbdev_set_power(FB_BLANK_POWERDOWN);
+ mdy_waitfb_data.suspended = true, mce_fbdev_set_power(false);
#endif
}
@@ -5870,10 +5701,10 @@ static void mdy_stm_start_fb_resume(void)
if( mdy_waitfb_data.thread )
wakelock_block_suspend();
else
- mdy_waitfb_data.suspended = false, mdy_fbdev_set_power(FB_BLANK_UNBLANK);
+ mdy_waitfb_data.suspended = false, mce_fbdev_set_power(true);
#else
mce_log(LL_NOTICE, "power off frame buffer");
- mdy_waitfb_data.suspended = false, mdy_fbdev_set_power(FB_BLANK_UNBLANK);
+ mdy_waitfb_data.suspended = false, mce_fbdev_set_power(true);
#endif
}
@@ -8432,11 +8263,6 @@ const gchar *g_module_check_init(GModule *module)
(void)module;
- /* Open fbdev and keep it open until actdead / user mode is reached.
- * This should keep the frame buffer powered on and we should not not
- * lose content drawn by processes that might exit during startup. */
- fbdev_fd_open();
-
/* Initialise the display type and the relevant paths */
(void)mdy_display_type_get();
@@ -8623,11 +8449,17 @@ void g_module_unload(GModule *module)
* open, create a detached child process to hold on to
* it so that display does not power off after mce & ui
* side have been terminated */
- if( mdy_shutdown_in_progress() && fbdev_fd_is_open() )
- fbdev_fd_close_after_exit();
+ if( mdy_shutdown_in_progress() && mce_fbdev_is_open() ) {
+ /* Calculate when to release fbdev file descriptor
+ *
+ * use shutdown_started + 6.0 s
+ */
- /* Close the fbdev handle mce itself uses for good */
- fbdev_fd_close_forever();
+ int delay_ms = (int)(mdy_shutdown_started_tick
+ + 6000
+ - mdy_get_boot_tick());
+ mce_fbdev_linger_after_exit(delay_ms);
+ }
return;
}
diff --git a/modules/display.h b/modules/display.h
index 28c62f6e..577abe3a 100644
--- a/modules/display.h
+++ b/modules/display.h
@@ -96,9 +96,6 @@
/** Generic maximum brightness file */
#define DISPLAY_GENERIC_MAX_BRIGHTNESS_FILE "/backlight_max"
-/** Path to the framebuffer device */
-#define FB_DEVICE "/dev/fb0"
-
/** Path to the GConf settings for the display */
#define MCE_GCONF_DISPLAY_PATH "/system/osso/dsm/display"