power: add initial power state transition on deviced startup 75/269075/4 accepted/tizen/unified/20220117.135018 submit/tizen/20220112.015321 submit/tizen/20220113.004629
authorYoungjae Cho <y0.cho@samsung.com>
Fri, 7 Jan 2022 07:47:51 +0000 (16:47 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Mon, 10 Jan 2022 08:17:41 +0000 (17:17 +0900)
The first transition is specified in init.conf. The transition is
selected by /proc/cmdline bootreason=.

Change-Id: I7ce713fac9008c5cdcc3f9a76a089bb6ebd16db8
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
CMakeLists.txt
conf/init.conf [new file with mode: 0644]
packaging/deviced.spec
plugins/iot-headless/battery/battery-plugin.c
plugins/iot-headless/input/input-config.c
plugins/iot-headless/power/power-config-parse.c [new file with mode: 0644]
plugins/iot-headless/power/power-config-parse.h [new file with mode: 0644]
plugins/iot-headless/power/power-state-manager.c
plugins/iot-headless/power/power-state-manager.h

index 96d3312..5a5b58e 100644 (file)
@@ -277,6 +277,7 @@ IF(BATTERY_MODULE STREQUAL on)
 ENDIF()
 
 IF(POWER_MODULE STREQUAL on)
+       INSTALL_CONF(conf init)
        INSTALL_CONF(conf power)
 ENDIF()
 
diff --git a/conf/init.conf b/conf/init.conf
new file mode 100644 (file)
index 0000000..6dea3b4
--- /dev/null
@@ -0,0 +1,11 @@
+[EVENT_ACTION]
+#INITIAL_STATE_BY_POWERKEY_BOOTING
+Enum=3000
+BootReason=powerkey
+Action=start,normal
+
+[EVENT_ACTION]
+#INITIAL_STATE_BY_CHARGER_BOOTING
+Enum=3001
+BootReason=charger
+Action=start,sleep
index e32051c..e45ed0c 100644 (file)
@@ -268,6 +268,7 @@ mv %{_libdir}/iot-headless-battery.so %{_libdir}/deviced/battery.so
 %endif
 %config %{_sysconfdir}/dbus-1/system.d/org.tizen.system.deviced.conf
 %config %{_sysconfdir}/deviced/power.conf
+%config %{_sysconfdir}/deviced/init.conf
 %if %{?battery_module} == on
 %config %{_sysconfdir}/deviced/battery.conf
 %endif
index e0b2bbd..1e867f8 100644 (file)
@@ -32,20 +32,6 @@ static void parse_device_notifier(struct battery_event_handler *handler, const c
        }
 }
 
-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_info(struct battery_event_handler *handler, char *curr, char *next)
 {
        struct trans_info *ti = NULL;
index ce798cd..7e193ff 100644 (file)
@@ -70,20 +70,6 @@ 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_info(struct input_event_unit *ieu, char *curr, char *next)
 {
        struct trans_info *ti = NULL;
diff --git a/plugins/iot-headless/power/power-config-parse.c b/plugins/iot-headless/power/power-config-parse.c
new file mode 100644 (file)
index 0000000..94ccb6c
--- /dev/null
@@ -0,0 +1,73 @@
+#include <libsyscommon/list.h>
+#include <libsyscommon/file.h>
+#include <libsyscommon/ini-parser.h>
+#include <hal/device/hal-board.h>
+
+#include "power-state-manager.h"
+
+#define INIT_CONF_PATH    "/etc/deviced/init.conf"
+
+static struct trans_info initial_transition_info = {
+       .reason = -1,
+       .curr = PSM_START,
+       .next = PSM_NORMAL,
+};
+
+static void parse_transition_info(const char *action)
+{
+       char curr[16] = { 0, };
+       char next[16] = { 0, };
+
+       if (sscanf(action, "%15[^,],%15s", curr, next) == 2) {
+               initial_transition_info.curr = convert_action_string_to_psm_state(curr);
+               initial_transition_info.next = convert_action_string_to_psm_state(next);
+       }
+}
+
+static void parse_initial_transition_info(const struct parse_result *result)
+{
+       GList *elem;
+       struct section_property *prop;
+
+       SYS_G_LIST_FOREACH(result->props, elem, prop) {
+               if (MATCH(prop->key, "Enum"))
+                       initial_transition_info.reason = atoi(prop->value);
+               else if (MATCH(prop->key, "Action"))
+                       parse_transition_info(prop->value);
+       }
+}
+
+static int parse_matching_bootreason(const struct parse_result *result, void *data)
+{
+       GList *elem;
+       struct section_property *prop;
+       char *bootreason = (char *) data;
+
+       if (!MATCH(result->section, "EVENT_ACTION"))
+               return 0;
+
+       SYS_G_LIST_FOREACH(result->props, elem, prop) {
+               if (MATCH(prop->key, "BootReason") && MATCH(prop->value, bootreason))
+                       parse_initial_transition_info(result);
+       }
+
+       return 0;
+}
+
+void parse_initial_transition(void *data)
+{
+       int retval;
+       char bootreason[64] = "Unknown";
+       GList **head = (GList **) data;
+
+       if (!head)
+               return;
+
+       retval = hal_device_board_get_boot_reason(bootreason, sizeof(bootreason));
+       if (retval == 0)
+               libsys_config_parse_by_section(INIT_CONF_PATH, parse_matching_bootreason, bootreason);
+
+       CRITICAL_LOG("BootReason=%s", bootreason);
+
+       *head = g_list_append(*head, &initial_transition_info);
+}
diff --git a/plugins/iot-headless/power/power-config-parse.h b/plugins/iot-headless/power/power-config-parse.h
new file mode 100644 (file)
index 0000000..efcdc12
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __POWER_CONFIG_PARSE_H__
+#define __POWER_CONFIG_PARSE_H__
+
+void parse_initial_transition(void *data);
+
+#endif //__POWER_CONFIG_PARSE_H__
index b50fd78..cbc24d2 100644 (file)
 #include "power-dbus.h"
 #include "power-state-wait.h"
 #include "power-event-lock.h"
+#include "power-config-parse.h"
 
 #define EVENT_TYPE_SLEEP    0
 #define EVENT_TYPE_WAKEUP   1
 
 char *psm_name[PSM_MAX] = {
+       [PSM_START] = "PSM_START",
        [PSM_NORMAL] = "PSM_NORMAL",
        [PSM_SLEEP] = "PSM_SLEEP",
        [PSM_POWEROFF] = "PSM_POWEROFF",
@@ -24,7 +26,7 @@ char *psm_name[PSM_MAX] = {
 };
 
 static guint64 state_transition_counter = 0;
-static enum psm_state current;
+static enum psm_state current = PSM_START;
 
 static void psm_wake_unlock(void)
 {
@@ -55,6 +57,7 @@ static void broadcast_transition_info(const struct trans_info *ti)
 {
        // mapping deviced state to capi signame
        static const char *capi_signame[PSM_MAX] = {
+               [PSM_START] = SIGNAME_CHANGE_STATE_TO_START,
                [PSM_NORMAL] = SIGNAME_CHANGE_STATE_TO_NORMAL,
                [PSM_SLEEP] = SIGNAME_CHANGE_STATE_TO_SLEEP,
                [PSM_POWEROFF] = SIGNAME_CHANGE_STATE_TO_POWEROFF,
@@ -63,6 +66,7 @@ static void broadcast_transition_info(const struct trans_info *ti)
 
        // mapping deviced state to capi state
        static const guint64 capi_state[PSM_MAX] = {
+               [PSM_START] = POWER_STATE_START,
                [PSM_NORMAL] = POWER_STATE_NORMAL,
                [PSM_SLEEP] = POWER_STATE_SLEEP,
                [PSM_POWEROFF] = POWER_STATE_POWEROFF,
@@ -73,6 +77,31 @@ static void broadcast_transition_info(const struct trans_info *ti)
                g_variant_new("(ttti)", capi_state[ti->curr], capi_state[ti->next], state_transition_counter, ti->reason));
 }
 
+static void psm_transition_start_to_normal(const struct trans_info *ti)
+{
+       current = PSM_NORMAL;
+
+       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
+       broadcast_transition_info(ti);
+}
+
+static void psm_transition_start_to_sleep(const struct trans_info *ti)
+{
+       int waiting;
+
+       current = PSM_SLEEP;
+
+       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
+       broadcast_transition_info(ti);
+       waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock);
+       if (waiting > 0) {
+               _D("Defer wake unlock");
+               return;
+       }
+
+       psm_wake_unlock();
+}
+
 static void psm_transition_normal_to_normal(const struct trans_info *ti)
 {
        broadcast_transition_info(ti);
@@ -99,8 +128,8 @@ static void psm_transition_sleep_to_normal(const struct trans_info *ti)
 {
        current = PSM_NORMAL;
 
-       broadcast_transition_info(ti);
        device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
+       broadcast_transition_info(ti);
        update_change_state_wait(state_transition_counter, ti, NULL);
 }
 
@@ -108,8 +137,8 @@ static void psm_transition_sleep_to_sleep(const struct trans_info *ti)
 {
        int waiting;
 
-       broadcast_transition_info(ti);
        device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
+       broadcast_transition_info(ti);
        waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock);
        if (waiting > 0) {
                _D("Defer wake unlock");
@@ -162,7 +191,12 @@ static int psm_transition_state_cb(void *data)
 
        /* transition */
        ++state_transition_counter;
-       if (current == PSM_NORMAL) {
+       if (current == PSM_START) {
+               if (next == PSM_NORMAL)
+                       psm_transition_start_to_normal(ti);
+               else if (next == PSM_SLEEP)
+                       psm_transition_start_to_sleep(ti);
+       } else if (current == PSM_NORMAL) {
                if (next == PSM_NORMAL)
                        psm_transition_normal_to_normal(ti);
                else if (next == PSM_SLEEP)
@@ -179,17 +213,29 @@ static int psm_transition_state_cb(void *data)
        return 0;
 }
 
-void power_state_manager_init(void *data)
+static int defer_autosleep_enable(void *data)
 {
-       /* initialize state */
-       current = PSM_NORMAL;
+       /* Deferred autosleep enable,
+        * This prevents system go suspend during booting */
        device_notify(DEVICE_NOTIFIER_REQUEST_ENABLE_AUTOSLEEP, NULL);
-       device_notify(DEVICE_NOTIFIER_REQUEST_WAKE_LOCK, NULL);
 
+       return 0;
+}
+
+void power_state_manager_init(void *data)
+{
+       GList *initial_ti = NULL;
+
+       register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, defer_autosleep_enable);
        register_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, psm_transition_state_cb);
 
        power_plugin_dbus_init(NULL);
        power_event_lock_init();
+
+       /* initialize the power state */
+       parse_initial_transition(&initial_ti);
+       psm_transition_state_cb(initial_ti);
+       g_list_free(initial_ti);
 }
 
 static const struct device_ops power_state_manager_device_ops = {
index 9da0859..3d5c0d2 100644 (file)
@@ -2,8 +2,12 @@
 #define __POWER_STATE_MANAGER_H__
 
 #include <stdio.h>
+#include <libsyscommon/ini-parser.h>
+
+#include "shared/log.h"
 
 enum psm_state {
+       PSM_START,
        PSM_NORMAL,
        PSM_SLEEP,
        PSM_POWEROFF,
@@ -21,4 +25,20 @@ struct trans_info {
 typedef void (*psm_transfunc) (const struct trans_info *info);
 void power_state_manager_init(void *data);
 
+static inline enum psm_state convert_action_string_to_psm_state(const char *str)
+{
+       if (MATCH(str, "start"))
+               return PSM_START;
+       else 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;
+}
+
 #endif //__POWER_STATE_MANAGER_H__