power: introduce power-state-manager for iot-headless 48/267648/2
authorYoungjae Cho <y0.cho@samsung.com>
Wed, 8 Dec 2021 07:10:32 +0000 (16:10 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Wed, 8 Dec 2021 07:17:08 +0000 (16:17 +0900)
Change-Id: I7b4d299d4f05585762b6c3f72d90e8e978eab2e0
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
conf/iot-headless-input.conf
plugins/iot-headless/input/CMakeLists.txt
plugins/iot-headless/input/input-config.c
plugins/iot-headless/input/input-config.h
plugins/iot-headless/input/input-handler.c
plugins/iot-headless/power/power-dbus.c [moved from plugins/iot-headless/power/power-control.c with 69% similarity]
plugins/iot-headless/power/power-dbus.h [new file with mode: 0644]
plugins/iot-headless/power/power-state-manager.c [new file with mode: 0644]
plugins/iot-headless/power/power-state-manager.h [new file with mode: 0644]
plugins/iot-headless/power/sleep-wait.c
src/shared/device-notifier.h

index ea0f901..d798628 100644 (file)
 # TriggerType: edge / level
 #  - edge: trigger event on releaseing key within a specific interval
 #  - level: trigger event on holding key for a duration
-# Action: sleep_toggle / poweroff / broadcast
-#  - sleep_toggle: toggle sleep state
-#  - poweroff: trigger poweroff
-#  - broadcast,string: broadcast dbus signal with following string
+# Action=broadcast
+#  - broadcast event using dbus signal
+# Action=curr,next
+#  - add state transition event from curr to next
 
-[SHORTKEY]
+[BLINKKEY_EDGE]
+Enum=1000
+Keycode=power
+Duration=0,2000
+TriggerType=edge
+Action=sleep,sleep
+
+[SHORTKEY_LEVEL]
+Enum=1001
+Keycode=power
+Duration=2000,-1
+TriggerType=level
+Action=broadcast
+
+[SHORTKEY_EDGE]
+Enum=1002
 Keycode=power
 Duration=2000,7000
 TriggerType=edge
-Action=sleep_toggle
+Action=normal,sleep
+Action=sleep,normal
 
-[LONGKEY]
+[LONGKEY_LEVEL]
+Enum=1003
 Keycode=power
 Duration=7000,-1
-TriggerType=edge
-Action=poweroff
+TriggerType=level
+Action=broadcast
 
-#[SHORTKEY_FEEDBACK]
-#Keycode=power
-#Duration=2000,-1
-#TriggerType=level
-#Action=broadcast,sleep
-#
-#[LONGKEY_FEEDBACK]
-#Keycode=power
-#Duration=7000,-1
-#TriggerType=level
-#Action=broadcast,poweroff
-#
-#[BT_FEEDBACK]
-#Keycode=bluetooth
-#Duration=0,2000
-#TriggerType=level
-#Action=broadcast,bluetooth
+[LONGKEY_EDGE]
+Enum=1004
+Keycode=power
+Duration=7000,-1
+TriggerType=edge
+Action=normal,poweroff
index f9a7881..5de54d4 100644 (file)
@@ -9,6 +9,7 @@ PKG_CHECK_MODULES(REQUIRED_PKGS REQUIRED
        libinput)
 
 INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../power)
 
 FILE(GLOB SRCS "*.c")
 ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS})
index e223359..126eec3 100644 (file)
@@ -9,13 +9,14 @@
 
 #include "shared/device-notifier.h"
 #include "shared/log.h"
+
 #include "input-config.h"
+#include "power-state-manager.h"
 
 #define INPUT_CONF_PATH    "/etc/deviced/input.conf"
 
 /* input config list */
 static GList *input_config_list;
-static int ieu_counter = 0;
 
 struct input_config *find_input_config(int keycode)
 {
@@ -69,23 +70,51 @@ static void parse_trigger_type(struct input_event_unit *ieu, const char *type)
 
 }
 
+static enum psm_state convert_action_string_to_psm_state(char *str)
+{
+       if (MATCH(str, "sleep"))
+               return PSM_SLEEP;
+       else if (MATCH(str, "normal"))
+               return PSM_NORMAL;
+       else if (MATCH(str, "poweroff"))
+               return PSM_POWEROFF;
+
+       _W("Invalid psm_state=%s", str);
+
+       return PSM_MAX;
+}
+
+static void add_action_transition_state(struct input_event_unit *ieu, char *curr, char *next)
+{
+       struct trans_info *ti = NULL;
+       GList **action_list = (GList **) &(ieu->user_data);
+
+       ti = calloc(1, sizeof(struct trans_info));
+       if (!ti)
+               return;
+
+       /* In configuration file, Enum= must be followed by Action=.
+        * Otherwise, ieu->id won't be defined at this point.*/
+       ti->reason = ieu->id;
+
+       ti->curr = convert_action_string_to_psm_state(curr);
+       ti->next = convert_action_string_to_psm_state(next);
+
+       SYS_G_LIST_APPEND(*action_list, ti);
+}
+
 static void parse_action(struct input_event_unit *ieu, const char *action)
 {
-       if (MATCH(action, "sleep_toggle")) {
-               ieu->notifier = DEVICE_NOTIFIER_INPUT_SLEEP_TOGGLE;
-               ieu->user_data = (void *)(intptr_t) KEY_POWER;
-       } else if (MATCH(action, "poweroff")) {
-               ieu->notifier = DEVICE_NOTIFIER_INPUT_TRIGGER_POWEROFF;
-               ieu->user_data = (void *)(intptr_t) KEY_POWER;
-       } else if (!strncmp(action, "broadcast", strlen("broadcast"))) { /* compare prefix */
-               char signame[32];
-
-               if (sscanf(action, "broadcast,%s", signame) != 1) {
-                       _E("Invalid action=%s", action);
-                       return;
-               }
+       char curr[16] = { 0, };
+       char next[16] = { 0, };
+
+       if (MATCH(action, "broadcast")) {
                ieu->notifier = DEVICE_NOTIFIER_INPUT_BROADCAST_SIGNAL;
-               ieu->user_data = (void *) strndup(signame, 32);
+               ieu->user_data = (void *) ieu;
+       } else if (sscanf(action, "%15[^,],%15s", curr, next) == 2) {
+               ieu->notifier = DEVICE_NOTIFIER_INPUT_TRANSITION_STATE;
+               /* append transition info to ieu->user_data */
+               add_action_transition_state(ieu, curr, next);
        } else {
                _E("Invalid action=%s", action);
        }
@@ -112,13 +141,13 @@ static int load_input_config(struct parse_result *result, void *data)
                        if (!ieu)
                                return -ENOMEM;
                        ieu->name = strndup(result->section, 32);
-                       ieu->id = ieu_counter++;
-                       ieu->pid = getpid();
                        SYS_G_LIST_APPEND(*tmp, ieu);
                }
        }
 
-       if (MATCH(result->name, "Keycode")) {
+       if (MATCH(result->name, "Enum")) {
+               sscanf(result->value, "%d", &ieu->id);
+       } else if (MATCH(result->name, "Keycode")) {
                parse_keycode(ieu, result->value);
        } else if (MATCH(result->name, "Duration")) {
                parse_duration(ieu, result->value);
@@ -152,8 +181,14 @@ static int parse_input_config(void)
                        SYS_G_LIST_APPEND(input_config_list, ic);
                }
                SYS_G_LIST_APPEND(ic->event_list, ieu);
-               _D("input event unit: name=%s, start=%lu, end=%lu, type=%d, action=%d",
-                       ieu->name, ieu->interval[0], ieu->interval[1], ieu->type, ieu->notifier);
+               _D("Input event unit: name=%s, enum=%d, start=%lu, end=%lu, type=%d, action=%d",
+                       ieu->name, ieu->id, ieu->interval[0], ieu->interval[1], ieu->type, ieu->notifier);
+               if (ieu->notifier == DEVICE_NOTIFIER_INPUT_TRANSITION_STATE) {
+                       struct trans_info *ti;
+                       GList *elem;
+                       SYS_G_LIST_FOREACH((GList *)ieu->user_data, elem, ti)
+                               _D("Transition state event is registered: %d -> %d", ti->curr, ti->next);
+               }
        }
 
        /* cleanup tmp list */
index 5d177d8..1fe1e75 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __INPUT_CONFIG_H__
 #define __INPUT_CONFIG_H__
 
-#include <unistd.h>
-
 #include "shared/device-notifier.h"
 
 enum trigger_type {
@@ -12,7 +10,6 @@ enum trigger_type {
 
 struct input_event_unit {
        char *name;
-       pid_t pid;
        int id;
 
        /* which event to filter */
index e97d286..35c5283 100644 (file)
@@ -38,13 +38,19 @@ static gboolean level_triggered(gpointer data)
        ieu->timer = 0;
 
        if (ieu->notifier > 0) {
-               _D("Trigger(level) event=%s, action=%d", ieu->name, ieu->notifier);
+               _D("Trigger(level) event=%s(%d), action=%d", ieu->name, ieu->id, ieu->notifier);
                device_notify(ieu->notifier, ieu->user_data);
        }
 
        return G_SOURCE_REMOVE;
 }
 
+static void edge_triggered(struct input_event_unit *ieu)
+{
+       _D("Trigger(edge) event=%s(%d), action=%d", ieu->name, ieu->id, ieu->notifier);
+       device_notify(ieu->notifier, ieu->user_data);
+}
+
 static void start_event_timer(struct input_config *ic)
 {
        struct timespec ts;
@@ -81,17 +87,15 @@ static void stop_event_timer(struct input_config *ic)
        ic->start = 0;
 
        SYS_G_LIST_FOREACH(ic->event_list, elem, ieu) {
-               /* remove all timer for level-trigger */
+               /* remove all level-trigger timer */
                if (ieu->timer) {
                        g_source_remove(ieu->timer);
                        ieu->timer = 0;
                }
 
-               /* trigger action of edge-trigger */
-               if (lapse >= ieu->interval[0] && lapse < ieu->interval[1] && ieu->type == TRIGGER_TYPE_EDGE) {
-                       _D("Trigger(edge) event=%s, action=%d", ieu->name, ieu->notifier);
-                       device_notify(ieu->notifier, ieu->user_data);
-               }
+               /* trigger edge-trigger action */
+               if (lapse >= ieu->interval[0] && lapse < ieu->interval[1] && ieu->type == TRIGGER_TYPE_EDGE)
+                       edge_triggered(ieu);
        }
 }
 
@@ -114,7 +118,7 @@ static int input_handler_execute(void *data)
        keycode = libinput_event_keyboard_get_key(ek);
        keyvalue = libinput_event_keyboard_get_key_state(ek);
 
-       _D("key input: code=%d, value=%d", keycode, keyvalue);
+       _D("Key input: code=%d, value=%d", keycode, keyvalue);
 
        /* acquire tmplock on pressing key */
        if (keyvalue == KEYVALUE_PRESS)
@@ -136,7 +140,12 @@ static int input_handler_execute(void *data)
 
 static int broadcast_input_signal_cb(void *data)
 {
-       _D("broadcast siganl callback, signame=%s", (char *) data);
+       struct input_event_unit *ieu = (struct input_event_unit *) data;
+
+       if (!ieu)
+               return 0;
+
+       _D("Broadcast siganl callback, event=%s(%d)", ieu->name, ieu->id);
        // TODO: implement dbus signal broadcast
 
        return 0;
@@ -153,7 +162,7 @@ static const struct device_ops input_handler_device_ops = {
        DECLARE_NAME_LEN("input-handler"),
        .init              = input_handler_init,
        .execute           = input_handler_execute,
-       .disable_auto_init = true,
+       .disable_auto_init = true, /* initialized by core input module */
 };
 
 DEVICE_OPS_REGISTER(&input_handler_device_ops)
similarity index 69%
rename from plugins/iot-headless/power/power-control.c
rename to plugins/iot-headless/power/power-dbus.c
index 60e3998..0a0ac50 100644 (file)
@@ -19,7 +19,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdint.h>
-#include <linux/input.h>
 #include <glib.h>
 #include <time.h>
 #include <libsyscommon/libgdbus.h>
 #include "shared/log.h"
 #include "shared/device-notifier.h"
 
+#include "power-state-manager.h"
 #include "sleep-wait.h"
 
 #ifndef PROCESS_CHECK_TIMEOUT
 #define PROCESS_CHECK_TIMEOUT    600000 /* milisecond, 10 minute */
 #endif
 
-#define KEYPRESS_LOCK_TIMEOUT   4000   /* milisecond */
-
-/* temporal wakelock of powerkey input */
-#define KEY_PRESSED_TEMPORAL_LOCK    "templock"
-#define TEMPORAL_LOCK_WAKE_MARGIN    1000 /* milisecond */
-
 static GList *lock_list;
 
 struct lock_node {
@@ -53,54 +47,6 @@ struct lock_node {
        char locktime[64];
 };
 
-static guint keypress_temporal_timer_id;
-
-static gboolean temporal_lock_expired_cb(void *data)
-{
-       sys_set_str("/sys/power/wake_unlock", KEY_PRESSED_TEMPORAL_LOCK);
-       keypress_temporal_timer_id = 0;
-
-       return G_SOURCE_REMOVE;
-}
-
-static int acquire_temporal_lock(void *data)
-{
-       int keycode = (int)(intptr_t) data;
-
-       if (keycode != KEY_POWER)
-               return 0;
-
-       if (keypress_temporal_timer_id) {
-               g_source_remove(keypress_temporal_timer_id);
-               keypress_temporal_timer_id = 0;
-       }
-
-       sys_set_str("/sys/power/wake_lock", KEY_PRESSED_TEMPORAL_LOCK);
-       keypress_temporal_timer_id = g_timeout_add(KEYPRESS_LOCK_TIMEOUT + TEMPORAL_LOCK_WAKE_MARGIN,
-               temporal_lock_expired_cb, NULL);
-
-       return 0;
-}
-
-static int release_temporal_lock(void * data)
-{
-       int keycode = (int)(intptr_t) data;
-
-       if (keycode != KEY_POWER)
-               return 0;
-
-       if (keypress_temporal_timer_id) {
-               g_source_remove(keypress_temporal_timer_id);
-               keypress_temporal_timer_id = 0;
-       }
-
-       /* shorten timeout */
-       keypress_temporal_timer_id = g_timeout_add(TEMPORAL_LOCK_WAKE_MARGIN,
-               temporal_lock_expired_cb, NULL);
-
-       return 0;
-}
-
 static void print_lock_node(void)
 {
        GList *elem;
@@ -149,7 +95,7 @@ static gboolean lock_expired_cb(void *data)
 {
        struct lock_node *this = (struct lock_node *) data;
 
-       _D("powerlock of pid=%d(%s) for %dms is expired", this->pid, this->comm, this->timeout);
+       _D("Powerlock of pid=%d(%s) for %dms is expired", this->pid, this->comm, this->timeout);
        remove_lock_node(this);
 
        return G_SOURCE_REMOVE;
@@ -362,84 +308,11 @@ static const dbus_interface_u dbus_interface = {
        .nr_methods = ARRAY_SIZE(dbus_methods),
 };
 
-static int sleep_toggle_cb(void *data)
-{
-       int keycode;
-       int retval;
-       guint64 current_time_ms = 0;
-       struct timespec ts;
-
-       static int sleep_enabled = 0; /* initial sleep state: disabled */
-       static guint64 sleep_id = 0;  /* increased by 1 on enabling sleep */
-
-       if (!data)
-               return 0;
-
-       keycode = (int)(intptr_t) data;
-       if (keycode != KEY_POWER)
-               return 0;
-
-       retval = clock_gettime(CLOCK_REALTIME, &ts);
-       if (retval == 0)
-               current_time_ms = ((guint64)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
-
-       sleep_enabled ^= 1; /* toggle status */
-       if (sleep_enabled) {
-               ++sleep_id;
-
-               gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER,
-                       "sleep", g_variant_new("(tt)", current_time_ms, sleep_id));
-               start_sleep_wait(sleep_id);
-       } else {
-               device_notify(DEVICE_NOTIFIER_REQUEST_DISABLE_AUTOSLEEP, NULL);
-               stop_sleep_wait();
-               gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER,
-                       "wakeup", g_variant_new("(tt)", current_time_ms, DEVICE_SIG_WAKEUP_SHORTKEY));
-       }
-
-       return 0;
-}
-
-static int trigger_poweroff_cb(void *data)
-{
-       const struct device_ops *power_device;
-
-       power_device = find_device("power");
-       if (check_default(power_device))
-               return G_SOURCE_REMOVE;
-
-       if (power_device->execute) {
-               /* disable autosleep */
-               device_notify(DEVICE_NOTIFIER_REQUEST_DISABLE_AUTOSLEEP, NULL);
-               _D("powerkey long pressed");
-               power_device->execute("poweroff");
-       }
-
-       return 0;
-}
-
-static void power_control_init(void *data)
+void power_plugin_dbus_init(void *data)
 {
        int retval;
 
        retval = gdbus_add_object(NULL, DEVICED_PATH_POWER, &dbus_interface);
        if (retval < 0)
                _E("Failed to init dbus method.");
-
-       /* initial sleep state: disabled */
-       device_notify(DEVICE_NOTIFIER_REQUEST_DISABLE_AUTOSLEEP, NULL);
-
-       register_notifier(DEVICE_NOTIFIER_KEY_PRESS, acquire_temporal_lock);
-       register_notifier(DEVICE_NOTIFIER_KEY_RELEASE, release_temporal_lock);
-
-       register_notifier(DEVICE_NOTIFIER_INPUT_SLEEP_TOGGLE, sleep_toggle_cb);
-       register_notifier(DEVICE_NOTIFIER_INPUT_TRIGGER_POWEROFF, trigger_poweroff_cb);
 }
-
-static const struct device_ops power_control_plugin_device_ops = {
-       DECLARE_NAME_LEN("power-control-plugin"),
-       .init              = power_control_init,
-       .disable_auto_init = true,
-};
-
-DEVICE_OPS_REGISTER(&power_control_plugin_device_ops)
diff --git a/plugins/iot-headless/power/power-dbus.h b/plugins/iot-headless/power/power-dbus.h
new file mode 100644 (file)
index 0000000..81fb49b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __POWER_DBUS_H__
+#define __POWER_DBUS_H__
+
+void power_plugin_dbus_init(void *data);
+
+#endif //__POWER_DBUS_H__
diff --git a/plugins/iot-headless/power/power-state-manager.c b/plugins/iot-headless/power/power-state-manager.c
new file mode 100644 (file)
index 0000000..fdafba5
--- /dev/null
@@ -0,0 +1,191 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <linux/input.h>
+#include <libsyscommon/libgdbus.h>
+#include <libsyscommon/list.h>
+
+#include "shared/devices.h"
+#include "shared/device-notifier.h"
+#include "shared/log.h"
+#include "power-state-manager.h"
+#include "power-dbus.h"
+#include "sleep-wait.h"
+
+#define KEYPRESS_LOCK_TIMEOUT   4000   /* milisecond */
+
+/* temporal wakelock of powerkey input */
+#define KEY_PRESSED_TEMPORAL_LOCK    "templock"
+#define TEMPORAL_LOCK_WAKE_MARGIN    1000 /* milisecond */
+
+static guint keypress_temporal_timer_id;
+
+static const char *psm_name[PSM_MAX] = {
+       [PSM_NORMAL] = "PSM_NORMAL",
+       [PSM_SLEEP] = "PSM_SLEEP",
+       [PSM_POWEROFF] = "PSM_POWEROFF",
+};
+
+static int sleep_id = 0;
+static enum psm_state current;
+
+static gboolean temporal_lock_expired_cb(void *data)
+{
+       sys_set_str("/sys/power/wake_unlock", KEY_PRESSED_TEMPORAL_LOCK);
+       keypress_temporal_timer_id = 0;
+
+       return G_SOURCE_REMOVE;
+}
+
+static int acquire_temporal_lock(void *data)
+{
+       int keycode = (int)(intptr_t) data;
+
+       if (keycode != KEY_POWER)
+               return 0;
+
+       if (keypress_temporal_timer_id) {
+               g_source_remove(keypress_temporal_timer_id);
+               keypress_temporal_timer_id = 0;
+       }
+
+       sys_set_str("/sys/power/wake_lock", KEY_PRESSED_TEMPORAL_LOCK);
+       keypress_temporal_timer_id = g_timeout_add(KEYPRESS_LOCK_TIMEOUT + TEMPORAL_LOCK_WAKE_MARGIN,
+               temporal_lock_expired_cb, NULL);
+
+       return 0;
+}
+
+static int release_temporal_lock(void * data)
+{
+       int keycode = (int)(intptr_t) data;
+
+       if (keycode != KEY_POWER)
+               return 0;
+
+       if (keypress_temporal_timer_id) {
+               g_source_remove(keypress_temporal_timer_id);
+               keypress_temporal_timer_id = 0;
+       }
+
+       /* shorten timeout */
+       keypress_temporal_timer_id = g_timeout_add(TEMPORAL_LOCK_WAKE_MARGIN,
+               temporal_lock_expired_cb, NULL);
+
+       return 0;
+}
+
+static int psm_sleep_wait_done_cb(void *data)
+{
+       _D("Sleep-wait done, wake unlock");
+       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_UNLOCK, NULL);
+
+       return 0;
+}
+
+static void psm_transition_normal_to_sleep(const struct trans_info *ti)
+{
+       current = PSM_SLEEP;
+       // TODO: tune parameter of the dbus signal
+       gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER,
+               "sleep", g_variant_new("(ti)", sleep_id, ti->reason));
+       start_sleep_wait(++sleep_id);
+}
+
+static void psm_transition_sleep_to_normal(const struct trans_info *ti)
+{
+       current = PSM_NORMAL;
+       stop_sleep_wait();
+       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
+       // TODO: tune parameter of the dbus signal
+       gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER,
+               "wakeup", g_variant_new("(i)", ti->reason));
+}
+
+static void psm_transition_sleep_to_sleep(const struct trans_info *ti)
+{
+       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
+       gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER,
+               "sleep", g_variant_new("(ti)", sleep_id, ti->reason));
+       start_sleep_wait(++sleep_id);
+}
+
+static void psm_transition_normal_to_poweroff(const struct trans_info *ti)
+{
+       const struct device_ops *power_device;
+
+       current = PSM_POWEROFF;
+
+       power_device = find_device("power");
+       if (check_default(power_device))
+               return;
+
+       if (power_device->execute) {
+               device_notify(DEVICE_NOTIFIER_REQUEST_DISABLE_AUTOSLEEP, NULL);
+               _D("Powerkey long pressed");
+               power_device->execute("poweroff");
+       }
+}
+
+static int psm_transition_state_cb(void *data)
+{
+       GList *action_list, *elem;
+       const struct trans_info *ti = NULL;
+       enum psm_state next;
+
+       if (!data)
+               return 0;
+
+       action_list = (GList *) data;
+
+       /* look for transition defined on the current state */
+       SYS_G_LIST_FOREACH(action_list, elem, ti) {
+               if (ti->curr == current)
+                       break;
+       }
+
+       if (!ti)
+               return 0;
+
+       next = ti->next;
+
+       _D("Transition power state: %s -> %s, reason=%d",
+               psm_name[current], psm_name[next], ti->reason);
+
+       /* transition */
+       if (current == PSM_NORMAL) {
+               if (next == PSM_SLEEP)
+                       psm_transition_normal_to_sleep(ti);
+               else if (next == PSM_POWEROFF)
+                       psm_transition_normal_to_poweroff(ti);
+       } else if (current == PSM_SLEEP) {
+               if (next == PSM_NORMAL)
+                       psm_transition_sleep_to_normal(ti);
+               else if (next == PSM_SLEEP)
+                       psm_transition_sleep_to_sleep(ti);
+       }
+
+       return 0;
+}
+
+void power_state_manager_init(void *data)
+{
+       /* initialize state */
+       current = PSM_NORMAL;
+       device_notify(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, NULL);
+       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
+
+       register_notifier(DEVICE_NOTIFIER_KEY_PRESS, acquire_temporal_lock);
+       register_notifier(DEVICE_NOTIFIER_KEY_RELEASE, release_temporal_lock);
+       register_notifier(DEVICE_NOTIFIER_INPUT_TRANSITION_STATE, psm_transition_state_cb);
+       register_notifier(DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE, psm_sleep_wait_done_cb);
+
+       power_plugin_dbus_init(NULL);
+}
+
+static const struct device_ops power_state_manager_device_ops = {
+       DECLARE_NAME_LEN("power-control-plugin"),
+       .init              = power_state_manager_init,
+       .disable_auto_init = true, /* initialized by core power module */
+};
+
+DEVICE_OPS_REGISTER(&power_state_manager_device_ops)
diff --git a/plugins/iot-headless/power/power-state-manager.h b/plugins/iot-headless/power/power-state-manager.h
new file mode 100644 (file)
index 0000000..0497d59
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __POWER_STATE_MANAGER_H__
+#define __POWER_STATE_MANAGER_H__
+
+#include <stdio.h>
+
+enum psm_state {
+       PSM_NORMAL,
+       PSM_SLEEP,
+       PSM_POWEROFF,
+       PSM_MAX,
+};
+
+struct trans_info {
+       int reason;
+       enum psm_state curr;
+       enum psm_state next;
+};
+
+typedef void (*psm_transfunc) (const struct trans_info *info);
+void power_state_manager_init(void *data);
+
+#endif //__POWER_STATE_MANAGER_H__
index d6c1d48..4ae4746 100644 (file)
@@ -40,12 +40,6 @@ static void switch_active_list(void)
        active = tmp;
 }
 
-static void request_wake_unlock(void)
-{
-       device_notify(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, NULL);
-       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_UNLOCK, NULL);
-}
-
 static gboolean max_wait_expired_cb(void *data)
 {
        struct sleep_wait *sw;
@@ -68,8 +62,7 @@ static gboolean max_wait_expired_cb(void *data)
                }
        }
 
-       _D("Force wake unlock");
-       request_wake_unlock();
+       device_notify(DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE, NULL);
 
        return G_SOURCE_REMOVE;
 }
@@ -151,8 +144,7 @@ void remove_sleep_wait(pid_t pid)
                        g_source_remove(max_wait_timer);
                        max_wait_timer = 0;
 
-                       _D("All sleep waits have been confirmed, wake unlock");
-                       request_wake_unlock();
+                       device_notify(DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE, NULL);
                }
        }
 }
@@ -194,8 +186,7 @@ int confirm_sleep_wait(pid_t pid, int id)
                                max_wait_timer = 0;
                        }
 
-                       _D("All sleep waits have been confirmed, wake unlock");
-                       request_wake_unlock();
+                       device_notify(DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE, NULL);
                }
 
                return 0;
@@ -218,7 +209,7 @@ void start_sleep_wait(int id)
 
        /* no need to defer sleep. wake unlock */
        if (g_list_length(active) == 0) {
-               request_wake_unlock();
+               device_notify(DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE, NULL);
                return;
        }
 
index fa5d813..07b4ec0 100644 (file)
@@ -38,6 +38,7 @@ enum device_notifier_type {
        DEVICE_NOTIFIER_DISPLAY_AMBIENT_STATE,
        DEVICE_NOTIFIER_DISPLAY_LOCK,
        DEVICE_NOTIFIER_POWER_RESUME,
+       DEVICE_NOTIFIER_POWER_SLEEP_WAIT_DONE,
        DEVICE_NOTIFIER_POWEROFF,
        DEVICE_NOTIFIER_APPLICATION_BACKGROUND,
        DEVICE_NOTIFIER_APPLICATION_FOREGROUND,
@@ -64,9 +65,10 @@ enum device_notifier_type {
        DEVICE_NOTIFIER_KEY_RELEASE,
 
        /* action triggered by input event */
-       DEVICE_NOTIFIER_INPUT_SLEEP_TOGGLE,
        DEVICE_NOTIFIER_INPUT_TRIGGER_POWEROFF,
        DEVICE_NOTIFIER_INPUT_BROADCAST_SIGNAL,
+       DEVICE_NOTIFIER_INPUT_TRANSITION_STATE,
+
 
        /* Purpose of calling methods of different modules
         * Use prefix DEVICE_NOTIFIER_REQUEST */