input: Add SYSCOMMON_PLUGIN_MODULE_DEVICED_INPUT plugin-backend 97/312897/1 accepted/tizen/unified/20240618.060048 accepted/tizen/unified/dev/20240620.000245
authorYunhee Seo <yuni.seo@samsung.com>
Fri, 14 Jun 2024 07:34:10 +0000 (16:34 +0900)
committerYunhee Seo <yuni.seo@samsung.com>
Mon, 17 Jun 2024 04:40:12 +0000 (13:40 +0900)
Add SYSCOMMON_PLUGIN_MODULE_DEVICED_INPUT plugin-backend skeleton code
for mobile profile.
There were logic that changed the display state according to input key
in the mobile profile.
Those logic related display is moved to plugin-backend from deviced mobile profile.

After display module is refactored, these codes will also be refactored.

Change-Id: I7d9b9bac0251ee1a48d8563a6e7b4a96aa5ba3f7
Signed-off-by: Yunhee Seo <yuni.seo@samsung.com>
CMakeLists.txt
packaging/system-plugin-backend-deviced-mobile.spec
src/input/CMakeLists.txt [new file with mode: 0644]
src/input/input.c [new file with mode: 0644]

index 6137912f0f436b57c9ab941d19b2586d860e4b93..9687bf7b0ec62b4013e3aad027754281defbfc65 100644 (file)
@@ -7,3 +7,4 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -Wall -Werror")
 
 ADD_SUBDIRECTORY(src/battery)
 ADD_SUBDIRECTORY(src/display)
+ADD_SUBDIRECTORY(src/input)
index f83c300cf63dabc26bb50bcd40886de22d2cf520..25e838334efafbde5011833876b8d5b0077f50ab 100644 (file)
@@ -14,6 +14,7 @@ BuildRequires:  cmake
 BuildRequires:  pkgconfig(libsyscommon)
 BuildRequires:  pkgconfig(libsyscommon-plugin-api-deviced)
 BuildRequires:  pkgconfig(dlog)
+BuildRequires:  pkgconfig(vconf)
 
 %description
 System plugin backend for deviced mobile profile
@@ -46,3 +47,4 @@ make %{?jobs:-j%jobs}
 %license LICENSE.Apache-2.0
 %{SYSTEM_PLUGIN_LIBDIR}/libplugin-backend-deviced-battery.so
 %{SYSTEM_PLUGIN_LIBDIR}/libplugin-backend-deviced-display.so
+%{SYSTEM_PLUGIN_LIBDIR}/libplugin-backend-deviced-input.so
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5260b97
--- /dev/null
@@ -0,0 +1,29 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+PROJECT(plugin-backend-deviced-input C)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+
+FILE(GLOB ALL_SRCS "*.c")
+SET(SRCS ${ALL_SRCS})
+
+if (${PLUGIN_DEVICED_ENABLE_DLOG})
+       ADD_DEFINITIONS("-DENABLE_DLOG")
+       ADD_DEFINITIONS("-DLOG_TAG=\"SYSTEM_PLUGIN_DEVICED_BATTERY\"")
+endif()
+SET(PKG_MODULES
+       libsyscommon
+       libsyscommon-plugin-api-deviced
+       vconf)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(PKGS REQUIRED ${PKG_MODULES})
+FOREACH(flag ${PKGS_CFLAGS})
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${PKGS_LDFLAGS})
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${PLUGIN_LIB_DIR} COMPONENT RuntimeLibraries)
\ No newline at end of file
diff --git a/src/input/input.c b/src/input/input.c
new file mode 100644 (file)
index 0000000..49dc1eb
--- /dev/null
@@ -0,0 +1,876 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <glib.h>
+#include <linux/input.h>
+#include <sys/types.h>
+#include <vconf.h>
+
+#include <libsyscommon/ini-parser.h>
+#include <libsyscommon/log.h>
+#include <libsyscommon/libgdbus.h>
+#include <libsyscommon/notifier.h>
+#include <libsyscommon/resource-manager.h>
+#include <system/syscommon-plugin-common-interface.h>
+#include <system/syscommon-plugin-deviced-common-interface.h>
+#include <system/syscommon-plugin-deviced-input.h>
+#include <system/syscommon-plugin-deviced-input-interface.h>
+#include <system/syscommon-plugin-deviced-display-interface.h>
+#include <system/syscommon-plugin-deviced-power-interface.h>
+#include <system/syscommon-plugin-deviced-touchled-interface.h>
+
+#define EXPORT __attribute__ ((visibility("default")))
+
+#define BYTES_PER_LONG         (sizeof(unsigned long))
+#define BITS_PER_LONG          (BYTES_PER_LONG * 8)
+#define OFFSET(x)              ((x) & (BITS_PER_LONG - 1))
+#define BIT(x)                 (1UL << OFFSET(x))
+#define USEC_TO_SEC(x) ((x)/1000000.0)
+
+#define SIGNAL_CHANGE_HARDKEY          "ChangeHardkey"
+#define SIGNAL_LCDON_BY_POWERKEY       "LCDOnByPowerkey"
+#define SIGNAL_LCDOFF_BY_POWERKEY      "LCDOffByPowerkey"
+
+#define USEC_PER_SEC                   1000000
+#define USEC_PER_MSEC                  1000
+
+#define LONGKEY_PRESSED_TIME   4       /* 4 second */
+
+#define CAPTURE_COMBINATION_INTERVAL           0.5     /* 0.5 second */
+#define TORCH_COMBINATION_INTERVAL             0.1     /* 0.1 second */
+#define DEFAULT_COMBINATION_INTERVAL           0.1     /* 0.1 second */
+
+enum key_combination_flags {
+       KEY_COMBINATION_STOP            = 0,
+       KEY_COMBINATION_POWERKEY        = BIT(0),
+       KEY_COMBINATION_MENUKEY         = BIT(1),
+       KEY_COMBINATION_VOLUMEUP        = BIT(2),
+       KEY_COMBINATION_VOLUMEDOWN      = BIT(3),
+};
+
+enum combination_process {
+       COMBINATION_STOP        = KEY_COMBINATION_STOP,
+       COMBINATION_SCREENCAPTURE       = KEY_COMBINATION_POWERKEY | KEY_COMBINATION_MENUKEY,
+       COMBINATION_TORCH       = KEY_COMBINATION_POWERKEY | KEY_COMBINATION_VOLUMEUP,
+       COMBINATION_QUICKTALK   = KEY_COMBINATION_POWERKEY | KEY_COMBINATION_VOLUMEDOWN,
+};
+
+static struct timeval pressed_time;
+static guint longkey_timeout_id = 0;
+static guint longkey_restore_id = 0;
+static guint displayon_by_powerkey_timeout_id = 0;
+static int cancel_lcdoff;
+static int key_combination = KEY_COMBINATION_STOP;
+static double combination_pressed_time;
+static bool touch_pressed = false;
+static int skip_lcd_off = false;
+static int skip_combination = false;
+static int booting_check = true;
+
+/* FIXME: This module needs actual operation test in mobile target */
+static inline int current_state_in_on(void)
+{
+       int ret;
+       enum syscommon_deviced_display_state current;
+
+       ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_CURRENT_STATE, (int32_t *) &current);
+       if (ret < 0)
+               return 0;
+
+       return ((current == SYSCOMMON_DEVICED_DISPLAY_STATE_DIM) || (current == SYSCOMMON_DEVICED_DISPLAY_STATE_ON));
+}
+
+static inline void restore_custom_brightness(void)
+{
+       bool custom_status;
+       int ret;
+       enum syscommon_deviced_display_state current;
+
+       ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_CURRENT_STATE, (int32_t *) &current);
+       if (ret < 0)
+               return;
+
+       if (current != SYSCOMMON_DEVICED_DISPLAY_STATE_DIM)
+               return;
+
+       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_CUSTOM_BRIGHTNESS,
+                                       (int32_t *) &custom_status);
+       syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_CUSTOM_BRIGHTNESS,
+                                       custom_status);
+}
+
+static void longkey_pressed(void)
+{
+       unsigned int caps;
+       enum syscommon_deviced_display_actor_id actor_power_key = SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY;
+       enum syscommon_deviced_display_capability lcdon_cap = SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON;
+       enum syscommon_deviced_display_capability lcdoff_cap = SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF;
+
+       _I("Power key long pressed!");
+       cancel_lcdoff = 1;
+
+       syscommon_resman_get_resource_attr_uint64_with_2_user_data(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_UINT64_ACTOR_CAPABILITY,
+                                       (u_int64_t *) &actor_power_key,
+                                       (u_int64_t *) &lcdon_cap,
+                                       (u_int64_t *) &caps);
+
+       if (caps) {
+               /* change state - LCD on */
+               syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_TUPLE2_CURRENT_STATE,
+                       SYSCOMMON_DEVICED_DISPLAY_STATE_ON, DEVICED_EVENT_INPUT_POWERKEY);
+       }
+
+       syscommon_resman_get_resource_attr_uint64_with_2_user_data(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_UINT64_ACTOR_CAPABILITY,
+                                       (u_int64_t *) &actor_power_key,
+                                       (u_int64_t *) &lcdoff_cap,
+                                       (u_int64_t *) &caps);
+
+       if (!caps) {
+               _D("No poweroff capability!");
+               return;
+       }
+}
+
+static gboolean longkey_restore_cb(void *data)
+{
+       syscommon_notifier_emit_notify(DEVICED_NOTIFIER_LONGKEY_RESTORE, (void *)NULL);
+       longkey_restore_id = 0;
+
+       return G_SOURCE_REMOVE;
+}
+
+static gboolean longkey_pressed_cb(void *data)
+{
+       longkey_pressed();
+       longkey_timeout_id = 0;
+
+       return G_SOURCE_REMOVE;
+}
+
+static unsigned long timediff_usec(struct timeval t1, struct timeval t2)
+{
+       unsigned long udiff;
+
+       udiff = (t2.tv_sec - t1.tv_sec) * USEC_PER_SEC;
+       udiff += (t2.tv_usec - t1.tv_usec);
+
+       return udiff;
+}
+
+static inline void check_key_pair(int code, int new, int *old)
+{
+       if (new == *old)
+               _E("key pair is not matched! (%d, %d)", code, new);
+       else
+               *old = new;
+}
+
+static inline void broadcast_lcdon_by_powerkey(void)
+{
+       gdbus_signal_emit(NULL,
+                       DEVICED_PATH_DISPLAY,
+                       DEVICED_INTERFACE_DISPLAY,
+                       SIGNAL_LCDON_BY_POWERKEY,
+                       NULL);
+}
+
+static inline void broadcast_lcdoff_by_powerkey(void)
+{
+       gdbus_signal_emit(NULL,
+                       DEVICED_PATH_DISPLAY,
+                       DEVICED_INTERFACE_DISPLAY,
+                       SIGNAL_LCDOFF_BY_POWERKEY,
+                       NULL);
+}
+
+static inline bool switch_on_lcd(enum deviced_event reason)
+{
+       if (current_state_in_on())
+               return false;
+
+       if (reason == DEVICED_EVENT_INPUT_POWERKEY)
+               broadcast_lcdon_by_powerkey();
+       else if (reason == DEVICED_EVENT_TOUCHSCREEN)
+               _I("Display on by Touch_wakeup event");
+
+       syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_TUPLE2_DISPLAY_DIRECT,
+                                       SYSCOMMON_DEVICED_DPMS_ON,
+                                       reason);
+
+       return true;
+}
+
+static inline void switch_off_lcd(void)
+{
+       int dpms_state;
+
+       if (!current_state_in_on())
+               return;
+
+       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_DPMS_STATE,
+                                       (int32_t *) &dpms_state);
+       if (dpms_state == SYSCOMMON_DEVICED_DPMS_OFF)
+               return;
+
+       broadcast_lcdoff_by_powerkey();
+
+       syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_TUPLE2_DISPLAY_DIRECT,
+                                       SYSCOMMON_DEVICED_DPMS_OFF,
+                                       DEVICED_EVENT_INPUT_POWERKEY);
+}
+
+static void update_vital_state(struct input_event *pinput)
+{
+       int vital_mode;
+       /* Change vital state to  SYSCOMMON_DEVICED_VITAL_EXIT only if vital mode is active */
+       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_POWER),
+                                       DEVICED_POWER_ATTR_INT_VITAL_MODE,
+                                       &vital_mode);
+       if (!vital_mode)
+               return;
+
+       /* Touch or Menu Key Release Event */
+       if (pinput->type == EV_ABS || (pinput->type == EV_KEY &&
+               pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_RELEASED && pinput->code == KEY_MENU)) {
+               /* Enable all services upon receiving user input, else maintain same state */
+               syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_POWER),
+                       DEVICED_POWER_ATTR_INT_VITAL_MODE, SYSCOMMON_DEVICED_VITAL_EXIT);
+       }
+}
+
+static void check_key_combination(struct input_event *pinput)
+{
+       double press_time, diff_time;
+       press_time = (pinput->time).tv_sec + USEC_TO_SEC((pinput->time).tv_usec);
+       diff_time = press_time - combination_pressed_time;
+
+       switch (key_combination) {
+       case COMBINATION_SCREENCAPTURE:
+               if (diff_time <= CAPTURE_COMBINATION_INTERVAL) {
+                       _I("Combination key : SCREENCAPTURE mode");
+                       skip_combination = true;
+               }
+               break;
+       case COMBINATION_TORCH:
+               if (diff_time <= TORCH_COMBINATION_INTERVAL) {
+                       /* When torch combination, display control should be not change. */
+                       if (displayon_by_powerkey_timeout_id) {
+                               g_source_remove(displayon_by_powerkey_timeout_id);
+                               displayon_by_powerkey_timeout_id = 0;
+                       }
+                       _I("Combination key : TORCH mode");
+                       skip_combination = true;
+               } else
+                       key_combination = COMBINATION_STOP;
+               break;
+       case COMBINATION_QUICKTALK:
+               if (diff_time <= DEFAULT_COMBINATION_INTERVAL) {
+                       _I("Combination key : QUICK-TALK mode");
+                       skip_combination = true;
+                       if (longkey_timeout_id) {
+                               g_source_remove(longkey_timeout_id);
+                               longkey_timeout_id = 0;
+                       }
+               }
+               break;
+       default:
+               combination_pressed_time = press_time;
+               return;
+       }
+}
+
+static void start_key_combination(struct input_event *pinput)
+{
+       switch (pinput->code) {
+       case KEY_POWER:
+               key_combination |= KEY_COMBINATION_POWERKEY;
+               break;
+       case KEY_MENU:
+               key_combination |= KEY_COMBINATION_MENUKEY;
+               break;
+       case KEY_VOLUMEUP:
+               key_combination |= KEY_COMBINATION_VOLUMEUP;
+               break;
+       case KEY_VOLUMEDOWN:
+               key_combination |= KEY_COMBINATION_VOLUMEDOWN;
+               break;
+       default:
+               return;
+       }
+
+       check_key_combination(pinput);
+}
+
+static void stop_key_combination(struct input_event *pinput)
+{
+       if (pinput == NULL) {
+               key_combination = KEY_COMBINATION_STOP;
+               return;
+       }
+
+       switch (pinput->code) {
+       case KEY_POWER:
+               key_combination &= ~KEY_COMBINATION_POWERKEY;
+               break;
+       case KEY_MENU:
+               key_combination &= ~KEY_COMBINATION_MENUKEY;
+               break;
+       case KEY_VOLUMEUP:
+               key_combination &= ~KEY_COMBINATION_VOLUMEUP;
+               break;
+       case KEY_VOLUMEDOWN:
+               key_combination &= ~KEY_COMBINATION_VOLUMEDOWN;
+               break;
+       default:
+               _E("This code(%d) is not combination type.", pinput->code);
+               break;
+       }
+}
+
+static void process_combination_key(struct input_event *pinput)
+{
+       if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_PRESSED)
+               start_key_combination(pinput);
+       else if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_RELEASED)
+               stop_key_combination(pinput);
+}
+
+
+static int process_menu_key(struct input_event *pinput)
+{
+       int caps;
+       enum syscommon_deviced_display_actor_id actor_menu_key = SYSCOMMON_DEVICED_DISPLAY_ACTOR_MENU_KEY;
+       enum syscommon_deviced_display_capability lcdon_cap = SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON;
+
+       syscommon_resman_get_resource_attr_uint64_with_2_user_data(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_UINT64_ACTOR_CAPABILITY,
+                                       (u_int64_t *) &actor_menu_key,
+                                       (u_int64_t *) &lcdon_cap,
+                                       (u_int64_t *) &caps);
+       if (!caps) {
+               if (current_state_in_on())
+                       return false;
+               _D("No lcd-on capability!");
+               return true;
+       } else if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_PRESSED)
+               switch_on_lcd(DEVICED_EVENT_INPUT_POWERKEY);
+
+       return false;
+}
+
+static int decide_lcdoff(void)
+{
+       int dpms_state;
+
+       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_DPMS_STATE,
+                                       (int32_t *) &dpms_state);
+
+       /* It's not needed if it's already LCD off state */
+       if (!current_state_in_on() && dpms_state != SYSCOMMON_DEVICED_DPMS_ON)
+               return false;
+
+       /*
+        * This flag is set at the moment
+        * that LCD is turned on by power key
+        * LCD has not to turned off in the situation.
+        */
+       if (skip_lcd_off)
+               return false;
+
+       /* LCD is not turned off when powerkey is pressed,not released */
+       if (key_combination == KEY_COMBINATION_POWERKEY)
+               return false;
+
+       /* LCD-off is blocked at the moment poweroff popup shows */
+       if (cancel_lcdoff)
+               return false;
+
+       /* LCD-off is blocked when powerkey and volmedown key are pressed */
+       if (skip_combination)
+               return false;
+
+       /* At booting time, display must do not turn off */
+       if (booting_check)
+               return false;
+
+       return true;
+}
+
+static int lcdoff_powerkey(void)
+{
+       int ignore = true;
+
+       if (decide_lcdoff() == true) {
+               switch_off_lcd();
+               syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_RELEASE_LOCK_ALL,
+                                       SYSCOMMON_DEVICED_DISPLAY_STATE_ON);
+               syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_RELEASE_LOCK_ALL,
+                                       SYSCOMMON_DEVICED_DISPLAY_STATE_DIM);
+               syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_LCDOFF_REASON,
+                                       DEVICED_EVENT_INPUT_POWERKEY);
+               syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_TUPLE2_CURRENT_STATE,
+                       SYSCOMMON_DEVICED_DISPLAY_STATE_OFF, DEVICED_EVENT_INPUT_POWERKEY);
+       } else {
+               ignore = false;
+               skip_combination = false;
+       }
+       cancel_lcdoff = 0;
+
+       return ignore;
+}
+
+static bool key_check_display_on(void)
+{
+       int dpms_state;
+
+       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_DPMS_STATE,
+                                       (int32_t *) &dpms_state);
+
+       if (current_state_in_on())
+               return false;
+
+       if (dpms_state == SYSCOMMON_DEVICED_DPMS_ON) {
+               _W("display power was on");
+               return false;
+       }
+
+       return true;
+}
+
+
+static gboolean display_on_cb(void *data)
+{
+       int dpms_state;
+
+       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_DPMS_STATE,
+                                       (int32_t *) &dpms_state);
+
+       if (displayon_by_powerkey_timeout_id == 0)
+               return G_SOURCE_REMOVE;
+
+       displayon_by_powerkey_timeout_id = 0;
+       if (dpms_state != SYSCOMMON_DEVICED_DPMS_ON || current_state_in_on() == false) {
+               broadcast_lcdon_by_powerkey();
+               syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_TUPLE2_DISPLAY_DIRECT,
+                                       SYSCOMMON_DEVICED_DPMS_ON,
+                                       DEVICED_EVENT_INPUT_POWERKEY);
+               syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_STATE_TRANSITION,
+                                       DEVICED_EVENT_INPUT);
+       }
+
+       return G_SOURCE_REMOVE;
+}
+
+static int process_back_key(struct input_event *pinput)
+{
+       int ignore = true;
+
+       if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_PRESSED) {
+               switch_on_lcd(DEVICED_EVENT_INPUT_BACKKEY);
+               _I("back key pressed");
+               ignore = false;
+       }
+
+       return ignore;
+}
+
+static int process_power_key(struct input_event *pinput)
+{
+       int ignore = true;
+       static int value = SYSCOMMON_DEVICED_INPUT_KEY_RELEASED;
+       int dpms_state;
+       int powerkey_doublepress;
+       double longpress_interval;
+       unsigned int lcdoff_caps;
+       unsigned int lcdon_caps;
+       enum syscommon_deviced_display_actor_id actor_power_key = SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY;
+       enum syscommon_deviced_display_capability lcdon_cap = SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON;
+       enum syscommon_deviced_display_capability lcdoff_cap = SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF;
+
+       syscommon_resman_get_resource_attr_uint64_with_2_user_data(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_UINT64_ACTOR_CAPABILITY,
+                                       (u_int64_t *) &actor_power_key,
+                                       (u_int64_t *) &lcdoff_cap,
+                                       (u_int64_t *) &lcdoff_caps);
+       syscommon_resman_get_resource_attr_uint64_with_2_user_data(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_UINT64_ACTOR_CAPABILITY,
+                                       (u_int64_t *) &actor_power_key,
+                                       (u_int64_t *) &lcdon_cap,
+                                       (u_int64_t *) &lcdon_caps);
+       syscommon_resman_get_resource_attr_double(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_DOUBLE_CONFIG_LONGPRESS_INTERVAL,
+                                       (double *) &longpress_interval);
+
+       switch (pinput->value) {
+       case SYSCOMMON_DEVICED_INPUT_KEY_RELEASED:
+               check_key_pair(pinput->code, pinput->value, &value);
+
+               syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                               DEVICED_DISPLAY_ATTR_INT_CONFIG_POWERKEY_DOUBLEPRESS,
+                               (int32_t *) &powerkey_doublepress);
+               if (!powerkey_doublepress) {
+                       if (lcdoff_caps)
+                               lcdoff_powerkey();
+                       else
+                               _D("No lcdoff capability!");
+               } else if (skip_lcd_off)
+                       ignore = false;
+
+               if (!lcdon_caps)
+                       ignore = true;
+
+               if (longkey_timeout_id > 0) {
+                       g_source_remove(longkey_timeout_id);
+                       longkey_timeout_id = 0;
+               }
+
+               if (longkey_restore_id > 0) {
+                       g_source_remove(longkey_restore_id);
+                       longkey_restore_id = 0;
+               }
+
+               break;
+       case SYSCOMMON_DEVICED_INPUT_KEY_PRESSED:
+               if (lcdon_caps) {
+                       /*
+                        * LCD does not turn on immediately at mobile.
+                        * It will be turned on after 0.1 second because of torch concept.
+                        */
+                       skip_lcd_off = key_check_display_on();
+                       ignore = true;
+
+                       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                               DEVICED_DISPLAY_ATTR_INT_DPMS_STATE,
+                                               (int32_t *) &dpms_state);
+                       if (!displayon_by_powerkey_timeout_id &&
+                               dpms_state != SYSCOMMON_DEVICED_DPMS_ON &&
+                               key_combination != COMBINATION_TORCH) {
+                               displayon_by_powerkey_timeout_id = g_timeout_add(
+                                               100,
+                                               display_on_cb, NULL);
+                       }
+               } else {
+                       _D("No lcdon capability!");
+                       skip_lcd_off = false;
+               }
+               check_key_pair(pinput->code, pinput->value, &value);
+               _I("power key pressed");
+               pressed_time.tv_sec = (pinput->time).tv_sec;
+               pressed_time.tv_usec = (pinput->time).tv_usec;
+               if (key_combination == KEY_COMBINATION_POWERKEY) {
+                       /* add long key timer */
+                       longkey_timeout_id = g_timeout_add(
+                                       longpress_interval,
+                                       longkey_pressed_cb, NULL);
+                       /* add long key restore timer */
+                       longkey_restore_id = g_timeout_add_seconds(
+                                       LONGKEY_PRESSED_TIME,
+                                       longkey_restore_cb, NULL);
+               }
+               cancel_lcdoff = 0;
+
+               break;
+       case SYSCOMMON_DEVICED_INPUT_KEY_BEING_PRESSED:
+               if (timediff_usec(pressed_time, pinput->time) > (longpress_interval * USEC_PER_MSEC))
+                       longkey_pressed();
+               break;
+       }
+       return ignore;
+}
+
+static int process_screenlock_key(struct input_event *pinput)
+{
+       if (pinput->value != SYSCOMMON_DEVICED_INPUT_KEY_RELEASED) {
+               stop_key_combination(NULL);
+               return true;
+       }
+
+       if (!current_state_in_on())
+               return false;
+
+       syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_RELEASE_LOCK_ALL,
+                                       SYSCOMMON_DEVICED_DISPLAY_STATE_ON);
+       syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_RELEASE_LOCK_ALL,
+                                       SYSCOMMON_DEVICED_DISPLAY_STATE_DIM);
+       syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_LCDOFF_REASON,
+                                       DEVICED_EVENT_INPUT_POWERKEY);
+
+       /* LCD off forcly */
+       syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_TUPLE2_CURRENT_STATE,
+               SYSCOMMON_DEVICED_DISPLAY_STATE_OFF, DEVICED_EVENT_INPUT_POWERKEY);
+
+       return true;
+}
+
+static void sound_vibrate_hardkey(void)
+{
+       /* device notify(vibrator) */
+       /* sound(dbus) */
+       /* Need to notify to deviced-vibrator. deviced-vibrator receives ChangedHardKey signal */
+       gdbus_signal_emit(NULL,
+                       DEVICED_PATH_KEY,
+                       DEVICED_INTERFACE_KEY,
+                       SIGNAL_CHANGE_HARDKEY,
+                       NULL);
+}
+
+static void process_hardkey_backlight(struct input_event *pinput)
+{
+       int lockscreen_state = VCONFKEY_IDLE_UNLOCK;
+       int lockscreen_bg_state = 0;
+
+       _D("pinput->value : %d", pinput->value);
+
+       syscommon_resman_get_resource_attr_int(
+               SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_LOCKSCREEN_STATE, &lockscreen_state);
+       syscommon_resman_get_resource_attr_int(
+               SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_LOCKSCREEN_BG_STATE, &lockscreen_bg_state);
+
+       if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_PRESSED) {
+               /* Sound & Vibrate only in unlock state */
+               if (lockscreen_state == VCONFKEY_IDLE_UNLOCK || lockscreen_bg_state)
+                       sound_vibrate_hardkey();
+
+               syscommon_resman_set_resource_attr_int(
+                       SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_TOUCHLED),
+                       DEVICED_TOUCHLED_ATTR_INT_BACKLIGHT,
+                       SYSCOMMON_DEVICED_TOUCHLED_PRESS);
+       } else if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_RELEASED) {
+               /* if lockscreen is idle lock */
+               if (lockscreen_state == VCONFKEY_IDLE_LOCK) {
+                       _D("Lock state, key backlight is off when phone is unlocked!");
+                       return;
+               }
+
+               syscommon_resman_set_resource_attr_int(
+                       SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_TOUCHLED),
+                       DEVICED_TOUCHLED_ATTR_INT_BACKLIGHT,
+                       SYSCOMMON_DEVICED_TOUCHLED_RELEASE);
+       }
+}
+
+static int check_key(struct input_event *pinput)
+{
+       int ignore = true;
+
+       process_combination_key(pinput);
+       switch (pinput->code) {
+       case KEY_MENU:
+               ignore = process_menu_key(pinput);
+               break;
+       case KEY_POWER:
+               ignore = process_power_key(pinput);
+               if (current_state_in_on())
+                       ignore = false;
+               break;
+       case KEY_SCREENLOCK:
+               ignore = process_screenlock_key(pinput);
+               break;
+       case KEY_BACK:
+               ignore = process_back_key(pinput);
+               stop_key_combination(NULL);
+               if (current_state_in_on()) {
+                       process_hardkey_backlight(pinput);
+                       ignore = false;
+               }
+               break;
+       case KEY_PHONE:
+               stop_key_combination(NULL);
+               if (current_state_in_on()) {
+                       process_hardkey_backlight(pinput);
+                       ignore = false;
+               }
+               break;
+       case KEY_VOLUMEUP:
+       case KEY_VOLUMEDOWN:
+               if (current_state_in_on())
+                       ignore = false;
+               break;
+       case KEY_CAMERA:
+       case KEY_EXIT:
+       case KEY_CONFIG:
+       case KEY_MEDIA:
+       case KEY_MUTE:
+       case KEY_PLAYPAUSE:
+       case KEY_PLAYCD:
+       case KEY_PAUSECD:
+       case KEY_STOPCD:
+       case KEY_NEXTSONG:
+       case KEY_PREVIOUSSONG:
+       case KEY_REWIND:
+       case KEY_FASTFORWARD:
+               stop_key_combination(NULL);
+               if (current_state_in_on())
+                       ignore = false;
+               break;
+       case 0x1DB:
+       case 0x1DC:
+       case 0x1DD:
+       case 0x1DE:
+               stop_key_combination(NULL);
+               break;
+       default:
+               stop_key_combination(NULL);
+               ignore = false;
+       }
+#ifdef ENABLE_PM_LOG
+       if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_PRESSED)
+               pm_history_save(SYSCOMMON_DEVICED_POWER_LOG_TYPE_KEY_PRESS, pinput->code);
+       else if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_RELEASED)
+               pm_history_save(SYSCOMMON_DEVICED_POWER_LOG_TYPE_KEY_RELEASE, pinput->code);
+#endif
+       return ignore;
+}
+
+static void check_key_filter(struct timeval time, unsigned short type, unsigned short keycode, unsigned int keyvalue)
+{
+       struct input_event *pinput = &(struct input_event) {
+               .time = time,
+               .type = type,
+               .code = keycode,
+               .value = keyvalue
+       };
+       int ignore = true;
+       static int code, value;
+       int ret;
+       enum syscommon_deviced_display_state current;
+       int touch_event_blocked;
+       int touch_event_wakeup_config;
+
+       assert(pinput);
+
+       switch (pinput->type) {
+       case EV_KEY:
+               if (pinput->code == BTN_TOUCH &&
+                       pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_RELEASED)
+                       touch_pressed = false;
+               /*
+                * Normally, touch press/release events don't occur
+                * in lcd off state. But touch release events can occur
+                * in the state abnormally. Then touch events are ignored
+                * when lcd is off state.
+                */
+               if (pinput->code == BTN_TOUCH && !current_state_in_on())
+                       break;
+               if (pinput->code == code && pinput->value == value) {
+                       _E("Same key(%d, %d) is polled", code, value);
+               }
+               code = pinput->code;
+               value = pinput->value;
+
+               update_vital_state(pinput);
+               ignore = check_key(pinput);
+               restore_custom_brightness();
+
+               break;
+       case EV_REL:
+               ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_INT_CURRENT_STATE, (int32_t *) &current);
+               if (ret < 0)
+                       break;
+
+               if (current == SYSCOMMON_DEVICED_DISPLAY_STATE_OFF) {
+                       switch_on_lcd(DEVICED_EVENT_INPUT_BEZEL);
+                       ignore = false;
+               } else if (current != SYSCOMMON_DEVICED_DISPLAY_STATE_OFF)
+                       ignore = false;
+               break;
+       case EV_ABS:
+               syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_TOUCH_EVENT_BLOCKED,
+                                       (int32_t *) &touch_event_blocked);
+               syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_CONFIG_TOUCH_WAKEUP,
+                                       (int32_t *) &touch_event_wakeup_config);
+               if (touch_event_blocked
+                       && !touch_event_wakeup_config
+                       && pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_BEING_PRESSED)
+                       return;
+
+               update_vital_state(pinput);
+               if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_PRESSED) {
+                       switch_on_lcd(DEVICED_EVENT_TOUCHSCREEN);
+                       ignore = false;
+               }
+
+               if (current_state_in_on())
+                       ignore = false;
+
+               restore_custom_brightness();
+
+               if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_PRESSED)
+                       touch_pressed = true;
+               else if (pinput->value == SYSCOMMON_DEVICED_INPUT_KEY_RELEASED)
+                       touch_pressed = false;
+               break;
+       case EV_SW:
+               break;
+       }
+
+       if (ignore)
+               return;
+
+       /* lcd on or update lcd timeout */
+       syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                                       DEVICED_DISPLAY_ATTR_INT_STATE_TRANSITION,
+                                       DEVICED_EVENT_INPUT);
+}
+
+static int delayed_init_done(void *data)
+{
+       booting_check = 0;
+
+       return 0;
+}
+
+static syscommon_plugin_backend_deviced_input_funcs g_input_funcs = {
+       .input_event_cb = check_key_filter,
+};
+
+static int deviced_input_init(void **data)
+{
+       if (!data)
+               return -EINVAL;
+
+       *data = (void *)&g_input_funcs;
+       syscommon_notifier_subscribe_notify(DEVICED_NOTIFIER_DELAYED_INIT, delayed_init_done);
+
+       return 0;
+}
+
+static int deviced_input_exit(void *data)
+{
+       return 0;
+}
+
+syscommon_plugin_backend EXPORT system_plugin_backend_deviced_input_data = {
+       .name = "deviced-input",
+       .vendor = "Samsung",
+       .init = deviced_input_init,
+       .exit = deviced_input_exit,
+};