input: Add input backend 23/297723/2 accepted/tizen_unified_riscv accepted/tizen/unified/20230825.044255 accepted/tizen/unified/riscv/20230829.072050
authorYoungjae Cho <y0.cho@samsung.com>
Wed, 23 Aug 2023 06:25:29 +0000 (15:25 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Wed, 23 Aug 2023 08:28:58 +0000 (17:28 +0900)
It has been separated from the deviced iot-headed plugin.

Change-Id: Ie21942654846882b5e4e2fa2931592651c8a08a6
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
src/deviced-input/CMakeLists.txt
src/deviced-input/deviced-input.c

index 26f038ac7b99d34857177762d8714b21d211d06a..98580b74e548ce54806a4b1bff604a5ac20e031b 100644 (file)
@@ -11,7 +11,8 @@ pkg_check_modules(pkgs REQUIRED
        libsyscommon
        libsyscommon-plugin-api-deviced
        libinput
-       glib-2.0)
+       glib-2.0
+       vconf)
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_LIB_CFLAGS "${EXTRA_LIB_CFLAGS} ${flag}")
 ENDFOREACH(flag)
index 1a87afbe20707e2ad0e8db2a905ff6895e56d0a9..0c39b848aa5e1a0527017ff3bbb87259a5d3ed95 100644 (file)
  * limitations under the License.
  */
 
-#include <sys/time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <vconf.h>
+#include <sys/types.h>
+#include <linux/input.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-display-interface.h>
+#include <system/syscommon-plugin-deviced-power-interface.h>
 #include <system/syscommon-plugin-deviced-input.h>
 #include <system/syscommon-plugin-deviced-input-interface.h>
 
 #define EXPORT __attribute__ ((visibility("default")))
 
-static syscommon_plugin_backend_deviced_input_funcs g_input_funcs;
+#ifndef KEY_SCREENLOCK
+#define KEY_SCREENLOCK         0x98
+#endif
+#ifndef SW_GLOVE
+#define SW_GLOVE               0x16
+#endif
+
+#define USEC_PER_SEC                   1000000
+
+#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 */
+
+#define LONGKEY_PRESSED_TIME   4       /* 4 second */
+
+#define SIGNAL_CHANGE_HARDKEY          "ChangeHardkey"
+#define SIGNAL_LCDON_BY_POWERKEY       "LCDOnByPowerkey"
+#define SIGNAL_LCDOFF_BY_POWERKEY      "LCDOffByPowerkey"
+
+/**
+ * FIXME: Move it to the libsyscommon. Fix it and so does the deviced.
+ */
+#define KEY_RELEASED           0
+#define KEY_PRESSED            1
+#define KEY_BEING_PRESSED      2
+
+enum key_combination_flags {
+       KEY_COMBINATION_STOP            = 0,
+       KEY_COMBINATION_POWERKEY        = (1 << 0),
+       KEY_COMBINATION_MENUKEY         = (1 << 1),
+       KEY_COMBINATION_VOLUMEUP        = (1 << 2),
+       KEY_COMBINATION_VOLUMEDOWN      = (1 << 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 bezel_wakeup = true;
+static int booting_check = true;
+
+#define POPUP_METHOD "PopupLaunch"
+#define APP_POWERKEY "powerkey"
+#define APP_OVERHEAT "overheat"
+#define APP_DEFAULT  "system"
+#define APP_ABNORMAL "abnormal"
+#define APP_REMOVE   "remove"
+#define APP_KEY_TYPE "_SYSPOPUP_CONTENT_"
 
-static void deviced_input_event_cb(struct timeval time, unsigned short type,
-                               unsigned short keycode, unsigned int keyvalue)
+static const struct app_dbus_match {
+       const char *type;
+       const char *bus;
+       const char *path;
+       const char *iface;
+       const char *method;
+} app_match[] = {
+       { APP_DEFAULT , POPUP_BUS_NAME, POPUP_PATH_SYSTEM  , POPUP_INTERFACE_SYSTEM  , POPUP_METHOD },
+       { APP_POWERKEY, POPUP_BUS_NAME, POPUP_PATH_POWERKEY, POPUP_INTERFACE_POWERKEY, POPUP_METHOD },
+       { APP_OVERHEAT, POPUP_BUS_NAME, POPUP_PATH_OVERHEAT, POPUP_INTERFACE_OVERHEAT, POPUP_METHOD },
+       { APP_ABNORMAL, POPUP_BUS_NAME, POPUP_PATH_SYSTEM  , POPUP_INTERFACE_SYSTEM  , POPUP_METHOD },
+       { APP_REMOVE  , POPUP_BUS_NAME, POPUP_PATH_SYSTEM  , POPUP_INTERFACE_SYSTEM  , POPUP_METHOD },
+};
+
+#define ARRAY_SIZE(arr)   (sizeof(arr)/sizeof(arr[0]))
+
+static void __cb(GVariant *var, void *user_data, GError *err)
 {
+        int ret;
+
+       if (!var) {
+               _E("No message: %s", err->message);
+               return;
+       }
+
+       if (!g_variant_get_safe(var, "(i)", &ret)) {
+               _E("No message: %s", g_variant_get_type_string(var));
+               goto out;
+       }
+
+       _D("Reply value: %d", ret);
+
+out:
+       g_variant_unref(var);
 }
 
-static int deviced_input_init(void **data)
+static int launch_system_app(char *type, int num, ...)
 {
-       *data = (void *)&g_input_funcs;
+       char *app_type;
+       va_list args;
+       int i, match, ret;
+
+       if (type)
+               app_type = type;
+       else
+               app_type = APP_DEFAULT;
+
+       match = -1;
+       for (i = 0 ; i < ARRAY_SIZE(app_match) ; i++) {
+               if (strncmp(app_type, app_match[i].type, strlen(app_type)))
+               continue;
+               match = i;
+               break;
+       }
+       if (match < 0) {
+               _E("Failed to find matched app type(%s).", app_type);
+               return -EINVAL;
+       }
+
+       va_start(args, num);
+
+       ret = gdbus_call_pairs_async_with_reply(app_match[match].bus,
+               app_match[match].path,
+               app_match[match].iface,
+               app_match[match].method,
+               num,
+               args,
+               __cb,
+               -1,
+               NULL);
 
+       va_end(args);
+
+       syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_TUPLE2_SET_CURRENT_STATE,
+               SYSCOMMON_DEVICED_DISPLAY_STATE_ON,
+               DEVICED_EVENT_MISC_POPUP);
+
+       return ret;
+}
+
+static int is_lockscreen_enabled(void)
+{
+       int ret;
+       int enabled;
+
+       ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &enabled);
+
+       return (ret == 0 && enabled) ? VCONFKEY_IDLE_LOCK : VCONFKEY_IDLE_UNLOCK;
+}
+
+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_GET_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_GET_CURRENT_STATE, (int32_t *) &current);
+       if (ret < 0)
+               return;
+
+       syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_CUSTOM_BRIGHTNESS, (int *) &custom_status);
+       if (current == SYSCOMMON_DEVICED_DISPLAY_STATE_DIM && custom_status)
+               syscommon_resman_set_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_INT_CUSTOM_BRIGHTNESS, true);
+}
+
+static int set_lcdoff_reason(int source)
+{
+       int ret;
+
+       switch (source) {
+       case VCONFKEY_PM_LCDOFF_BY_TIMEOUT:
+               _I("LCD OFF by timeout.");
+               break;
+       case VCONFKEY_PM_LCDOFF_BY_POWERKEY:
+               _I("LCD OFF by powerkey.");
+               break;
+       default:
+               _E("Invalid value(%d).", source);
+               return -EINVAL;
+       }
+       ret = vconf_set_int(VCONFKEY_PM_LCDOFF_SOURCE, source);
+       if (ret < 0) {
+               _E("Failed to set vconf value for lcd off source: %d", vconf_get_ext_errno());
+               return -EPERM;
+       }
        return 0;
 }
 
-static int deviced_input_exit(void *data)
+static void pwroff_popup(void)
+{
+       int ret;
+
+       ret = launch_system_app(APP_POWERKEY, 2, APP_KEY_TYPE, APP_POWERKEY);
+       if (ret < 0)
+               _E("Failed to launch power off popup.");
+}
+
+static int check_actor_caps(int actor_id, unsigned int caps)
+{
+       int ret = 0;
+       u_int64_t capability = 0;
+
+       ret = syscommon_resman_get_resource_attr_uint64_with_2_user_data(
+               SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_UINT64_GET_ACTOR_CAPABILITY,
+               (u_int64_t *) &actor_id,
+               (u_int64_t *) &caps,
+               &capability);
+
+       if (ret < 0)
+               return 0; /* no capability */
+
+       return capability;
+}
+
+static void longkey_pressed(void)
+{
+       _I("Power key long pressed!");
+       cancel_lcdoff = 1;
+       if (check_actor_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON)) {
+               /* change state - LCD on */
+               syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_TUPLE2_SET_CURRENT_STATE,
+                       SYSCOMMON_DEVICED_DISPLAY_STATE_ON, DEVICED_EVENT_INPUT_POWERKEY);
+       }
+
+       if (!check_actor_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF)) {
+               _D("No poweroff capability!");
+               return;
+       }
+
+       pwroff_popup();
+}
+
+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)
+{
+       int dpms_state;
+       int ret;
+
+       if (current_state_in_on())
+               return false;
+
+       ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_DPMS_STATE, &dpms_state);
+       if (ret == 0 && dpms_state == SYSCOMMON_DEVICED_DPMS_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");
+       else
+               reason = DEVICED_EVENT_UNKNOWN;
+
+       syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_TUPLE2_SET_DISPLAY_DIRECT, SYSCOMMON_DEVICED_DPMS_ON, reason);
+
+       return true;
+}
+
+static inline void switch_off_lcd(void)
+{
+       int dpms_state;
+       int ret;
+
+       if (!current_state_in_on())
+               return;
+
+       ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_DPMS_STATE, &dpms_state);
+       if (ret == 0 && 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_SET_DISPLAY_DIRECT, SYSCOMMON_DEVICED_DPMS_OFF, DEVICED_EVENT_INPUT_POWERKEY);
+}
+
+static void check_key_combination(struct input_event *pinput)
+{
+       double press_time, diff_time;
+       press_time = (pinput->time).tv_sec + ((pinput->time).tv_usec / 1000000.0);
+       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 == KEY_PRESSED)
+               start_key_combination(pinput);
+       else if (pinput->value == KEY_RELEASED)
+               stop_key_combination(pinput);
+}
+
+static int process_menu_key(struct input_event *pinput)
+{
+       if (!check_actor_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_MENU_KEY, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON)) {
+               if (current_state_in_on())
+                       return false;
+               _D("No lcd-on capability!");
+               return true;
+       } else if (pinput->value == KEY_PRESSED)
+               switch_on_lcd(DEVICED_EVENT_INPUT_POWERKEY);
+
+       return false;
+}
+
+static int decide_lcdoff(void)
+{
+       int dpms_state;
+       int ret;
+
+       ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_DPMS_STATE, &dpms_state);
+
+       if (ret < 0)
+               return false;
+
+       /* 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_SET_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_SET_RELEASE_LOCK_ALL, SYSCOMMON_DEVICED_DISPLAY_STATE_DIM);
+               set_lcdoff_reason(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
+               syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_TUPLE2_SET_CURRENT_STATE,
+                       SYSCOMMON_DEVICED_DISPLAY_STATE_OFF, DEVICED_EVENT_INPUT_POWERKEY);
+       } else {
+               ignore = false;
+               skip_combination = false;
+       }
+       cancel_lcdoff = 0;
+
+       return ignore;
+}
+
+static int process_back_key(struct input_event *pinput)
+{
+       int ignore = true;
+
+       if (pinput->value == 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 = KEY_RELEASED;
+       int powerkey_doublepress;
+       double longpress_interval;
+       int ret;
+
+       ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_INT_GET_CONFIG_POWERKEY_DOUBLEPRESS, &powerkey_doublepress);
+       if (ret < 0) /* TODO : Haven't checked returning false is correct */
+               return false;
+
+       ret = syscommon_resman_get_resource_attr_double(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_DOUBLE_GET_CONFIG_LONGPRESS_INTERVAL, &longpress_interval);
+       if (ret < 0) /* TODO : Haven't checked returning false is correct */
+               return false;
+
+       switch (pinput->value) {
+       case KEY_RELEASED:
+               check_key_pair(pinput->code, pinput->value, &value);
+
+
+               if (!powerkey_doublepress) {
+                       if (check_actor_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF))
+
+                               lcdoff_powerkey();
+                       else
+                               _D("No lcdoff capability!");
+               } else if (skip_lcd_off)
+                       ignore = false;
+
+               if (!check_actor_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON))
+                       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 KEY_PRESSED:
+               if (check_actor_caps(SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY, SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON)) {
+                       skip_lcd_off = switch_on_lcd(DEVICED_EVENT_INPUT_POWERKEY);
+               } 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_seconds(
+                                   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 KEY_BEING_PRESSED:
+               if (timediff_usec(pressed_time, pinput->time) >
+                   (longpress_interval * USEC_PER_SEC))
+                       longkey_pressed();
+               break;
+       }
+       return ignore;
+}
+
+static int process_screenlock_key(struct input_event *pinput)
+{
+       if (pinput->value != 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_SET_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_SET_RELEASE_LOCK_ALL, SYSCOMMON_DEVICED_DISPLAY_STATE_DIM);
+       set_lcdoff_reason(VCONFKEY_PM_LCDOFF_BY_POWERKEY);
+
+       /* LCD off forcly */
+       syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_TUPLE2_SET_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)
+{
+       _E("pinput->value : %d", pinput->value);
+       if (pinput->value == KEY_PRESSED) {
+               /* Sound & Vibrate only in unlock state */
+               if (is_lockscreen_enabled() == VCONFKEY_IDLE_UNLOCK)
+                       sound_vibrate_hardkey();
+       } else if (pinput->value == KEY_RELEASED) {
+               /* if lockscreen is idle lock */
+               if (is_lockscreen_enabled() == VCONFKEY_IDLE_LOCK) {
+                       _D("Lock state, key backlight is off when phone is unlocked!");
+                       return;
+               }
+       }
+}
+
+static void update_vital_state(struct input_event *pinput)
+{
+       int type;
+       int vital_mode;
+       int ret;
+
+       /* Change vital state to  SYSCOMMON_DEVICED_VITAL_EXIT only if vital mode is active */
+       ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_POWER),
+               DEVICED_POWER_ATTR_INT_GET_VITAL_MODE, &vital_mode);
+       if (ret < 0 || vital_mode != 0)
+               return;
+
+       /* Touch or Menu Key Release Event */
+       if (pinput->type == EV_ABS || (pinput->type == EV_KEY &&
+           pinput->value == KEY_RELEASED && pinput->code == KEY_MENU)) {
+               /* Enable all services upon receiving user input, else maintain same state */
+               type = SYSCOMMON_DEVICED_VITAL_EXIT;
+               syscommon_notifier_emit_notify(DEVICED_NOTIFIER_VITAL_STATE, &type);
+       }
+}
+
+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 == KEY_PRESSED)
+               syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_POWER),
+                       DEVICED_POWER_ATTR_TUPLE2_SET_HISTORY_LOG,
+                       SYSCOMMON_DEVICED_POWER_LOG_TYPE_KEY_PRESS, pinput->code);
+       else if (pinput->value == KEY_RELEASED)
+               syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_POWER),
+                       DEVICED_POWER_ATTR_TUPLE2_SET_HISTORY_LOG,
+                       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 = 0;
+       int touch_wakeup = 0;
+
+       assert(pinput);
+
+       switch (pinput->type) {
+       case EV_KEY:
+               if (pinput->code == BTN_TOUCH &&
+                       pinput->value == 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);
+               }
+               gdbus_signal_emit(NULL,
+                                DEVICED_PATH_INPUT,
+                                DEVICED_INTERFACE_INPUT,
+                                "key",
+                                g_variant_new("(iiii)", pinput->code, pinput->value, pinput->time.tv_sec, pinput->time.tv_usec));
+
+               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_GET_CURRENT_STATE, (int32_t *) &current);
+               if (ret < 0)
+                       break;
+
+               if (current == SYSCOMMON_DEVICED_DISPLAY_STATE_OFF && bezel_wakeup) {
+                       switch_on_lcd(DEVICED_EVENT_INPUT_BEZEL);
+                       ignore = false;
+               } else if (current != SYSCOMMON_DEVICED_DISPLAY_STATE_OFF)
+                       ignore = false;
+               break;
+       case EV_ABS:
+               ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_INT_GET_TOUCH_EVENT_BLOCKED, &touch_event_blocked);
+               if (ret < 0)
+                       break;
+
+               ret = syscommon_resman_get_resource_attr_int(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+                       DEVICED_DISPLAY_ATTR_INT_GET_CONFIG_TOUCH_WAKEUP, &touch_wakeup);
+               if (ret < 0)
+                       break;
+
+               if (touch_event_blocked
+                       && !touch_wakeup
+                       && pinput->value == KEY_BEING_PRESSED)
+                       return;
+
+               update_vital_state(pinput);
+               if (pinput->value == KEY_PRESSED) {
+                       switch_on_lcd(DEVICED_EVENT_TOUCHSCREEN);
+                       ignore = false;
+               }
+
+               if (current_state_in_on())
+                       ignore = false;
+
+               restore_custom_brightness();
+
+               if (pinput->value == KEY_PRESSED)
+                       touch_pressed = true;
+               else if (pinput->value == KEY_RELEASED)
+                       touch_pressed = false;
+               break;
+       case EV_SW:
+               break;
+       }
+
+       if (ignore)
+               return;
+
+       /* lcd on or update lcd timeout */
+       syscommon_resman_set_resource_attr_uint64_2(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_TUPLE2_SET_CURRENT_STATE,
+               SYSCOMMON_DEVICED_DISPLAY_STATE_ON, DEVICED_EVENT_INPUT);
+}
+
+static int delayed_init_done(void *data)
 {
+       booting_check = 0;
+
+       return 0;
+}
+
+static int bezel_wakeup_cb(void *data)
+{
+       bezel_wakeup = (int)((intptr_t)data);
+
        return 0;
 }
 
 static syscommon_plugin_backend_deviced_input_funcs g_input_funcs = {
-       .input_event_cb = deviced_input_event_cb,
+       .input_event_cb = check_key_filter,
 };
 
+static int deviced_input_init(void **data)
+{
+       /*
+        * Default capability
+        * powerkey := LCDON | LCDOFF | POWEROFF
+        * homekey  := LCDON
+        */
+       syscommon_resman_set_resource_attr_uint64_3(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_TUPLE3_SET_ACTOR_CAPABILITY,
+               SYSCOMMON_DEVICED_DISPLAY_ACTOR_POWER_KEY,
+               (SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON | SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDOFF | SYSCOMMON_DEVICED_DISPLAY_CAPA_POWEROFF),
+               1);
+       syscommon_resman_set_resource_attr_uint64_3(SYSCOMMON_RESOURCE_ID(DEVICED_RESOURCE_TYPE_DISPLAY),
+               DEVICED_DISPLAY_ATTR_TUPLE3_SET_ACTOR_CAPABILITY,
+               SYSCOMMON_DEVICED_DISPLAY_ACTOR_MENU_KEY,
+               SYSCOMMON_DEVICED_DISPLAY_CAPA_LCDON,
+               1);
+
+       syscommon_notifier_subscribe_notify(DEVICED_NOTIFIER_DELAYED_INIT, delayed_init_done);
+       syscommon_notifier_subscribe_notify(DEVICED_NOTIFIER_BEZEL_WAKEUP, bezel_wakeup_cb);
+
+       *data = (void *)&g_input_funcs;
+
+       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",