shared: Replace device_notifier_type with the libsyscommon
[platform/core/system/deviced.git] / src / power / power-boot.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <stdio.h>
20 #include <unistd.h>
21 #include <bundle.h>
22 #include <eventsystem.h>
23 #include <libsyscommon/libgdbus.h>
24 #include <libsyscommon/libsystemd.h>
25 #include <libsyscommon/list.h>
26 #include <libsyscommon/file.h>
27 #include <libsyscommon/ini-parser.h>
28 #include <hal/device/hal-board.h>
29
30 #include "core/log.h"
31 #include "shared/device-notifier.h"
32 #include "shared/common.h"
33 #include "poll.h"
34 #include "display-ops.h"
35 #include "shared/plugin.h"
36 #include "power-doze.h"
37 #include "power.h"
38
39 #define SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED     "StartupFinished"
40 #define SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED       "UserSessionStartupFinished"
41
42 #define INIT_CONF_PATH    "/etc/deviced/init.conf"
43
44 static struct trans_info init_ti = {
45         .reason = -1,
46         .curr = 0,
47         .next = 0,
48 };
49
50 static struct boot_condition {
51         char reason[128];
52         char mode[128];
53 } bc = { "unknown", "normal" };
54
55 static guint sig_id[2] = {0, 0};
56
57 void remove_delayed_init_done_handler(void *data)
58 {
59         gdbus_signal_unsubscribe(NULL, sig_id[0]);
60         gdbus_signal_unsubscribe(NULL, sig_id[1]);
61 }
62
63 static void delayed_init_done_received(GDBusConnection  *conn,
64         const gchar      *sender,
65         const gchar      *path,
66         const gchar      *iface,
67         const gchar      *name,
68         GVariant         *param,
69         gpointer          data)
70 {
71         static int system_done = 0;
72         static int user_done = 0;
73
74         if (strcmp(name, SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED) == 0) {
75                 if (system_done)
76                         return;
77
78                 system_done = check_system_boot_finished();
79                 if (system_done == 0) {
80                         _E("System session is not ready yet.");
81                         return;
82                 }
83                 CRITICAL_LOG("System session is ready.");
84                 syscommon_notifier_emit_notify_once(DEVICED_NOTIFIER_DELAYED_INIT, &system_done);
85
86         } else if (strcmp(name, SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED) == 0) {
87                 if (user_done)
88                         return;
89                 user_done = 1;
90                 _I("User session is ready.");
91         }
92
93         if (!system_done || !user_done)
94                 return;
95
96         remove_delayed_init_done_handler(NULL);
97
98         doze_init();
99 }
100
101 void add_delayed_init_done_handler(void *data)
102 {
103         /* System Session is loaded completely */
104         /*ret = */
105         sig_id[0] = gdbus_signal_subscribe(NULL,
106                                         SYSTEMD_DBUS_PATH,
107                                         SYSTEMD_DBUS_IFACE_MANAGER,
108                                         SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED,
109                                         delayed_init_done_received,
110                                         NULL, NULL);
111
112         if (sig_id[0] <= 0)
113                 _E("Failed to init dbus signal(%s).", SYSTEMD_DBUS_SIGNAL_SYSTEM_STARTUP_FINISHED);
114
115         /* User Session is loaded completely */
116         sig_id[1] = gdbus_signal_subscribe(NULL,
117                                         SYSTEMD_DBUS_PATH,
118                                         SYSTEMD_DBUS_IFACE_MANAGER,
119                                         SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED,
120                                         delayed_init_done_received,
121                                         NULL, NULL);
122
123         if (sig_id[1] <= 0)
124                 _E("Failed to init dbus signal(%s).", SYSTEMD_DBUS_SIGNAL_USER_STARTUP_FINISHED);
125 }
126
127 static void parse_transition_info(const char *action)
128 {
129         char curr[16] = { 0, };
130         char next[16] = { 0, };
131
132         if (sscanf(action, "%15[^,],%15s", curr, next) == 2) {
133                 init_ti.curr = convert_action_string_to_power_state(curr);
134                 init_ti.next = convert_action_string_to_power_state(next);
135         }
136 }
137
138 static void parse_init_ti(const struct parse_result *result)
139 {
140         GList *elem;
141         struct section_property *prop;
142
143         SYS_G_LIST_FOREACH(result->props, elem, prop) {
144                 if (MATCH(prop->key, "Enum"))
145                         init_ti.reason = atoi(prop->value);
146                 else if (MATCH(prop->key, "ActionChangeState"))
147                         parse_transition_info(prop->value);
148         }
149 }
150
151 static int parse_matching_boot_condition(const struct parse_result *result, void *data)
152 {
153         GList *elem;
154         struct section_property *prop;
155         struct boot_condition config_bc = { "", "normal" };
156
157         if (!MATCH(result->section, "EventAction"))
158                 return 0;
159
160         SYS_G_LIST_FOREACH(result->props, elem, prop) {
161                 if (MATCH(prop->key, "BootReason"))
162                         snprintf(config_bc.reason, sizeof(config_bc.reason), "%s", prop->value);
163                 else if (MATCH(prop->key, "BootMode"))
164                         snprintf(config_bc.mode, sizeof(config_bc.mode), "%s", prop->value);
165         }
166
167         if (MATCH(bc.reason, config_bc.reason) && MATCH(bc.mode, config_bc.mode))
168                 parse_init_ti(result);
169
170         return 0;
171 }
172
173 void initial_transition_by_boot_condition(void)
174 {
175         int retval;
176
177         retval = hal_device_board_get_boot_reason(bc.reason, sizeof(bc.reason));
178         if (retval != 0) {
179                 _I("Failed to get BootReason, %d. Default change state to normal.", retval);
180                 power_request_change_state_strict(DEVICED_POWER_STATE_START, DEVICED_POWER_STATE_NORMAL, 1, NULL);
181                 return;
182         }
183
184         retval = hal_device_board_get_boot_mode(bc.mode, sizeof(bc.mode));
185         if (retval != 0)
186                 _I("Failed to get BootMode, %d", retval);
187
188         CRITICAL_LOG("BootReason=%s, BootMode=%s", bc.reason, bc.mode);
189         syscommon_config_parse_by_section(INIT_CONF_PATH, parse_matching_boot_condition, NULL);
190
191         power_request_change_state_strict(init_ti.curr, init_ti.next, init_ti.reason, NULL);
192 }