power: refactor power operations
[platform/core/system/deviced.git] / src / power / power-state-manager.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2022 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 <stdint.h>
21 #include <linux/input.h>
22 #include <libsyscommon/libgdbus.h>
23 #include <libsyscommon/list.h>
24 #include <device/power-internal.h>
25
26 #include "shared/devices.h"
27 #include "shared/device-notifier.h"
28 #include "shared/log.h"
29 #include "power-state-manager.h"
30 #include "power-suspend.h"
31 #include "power-dbus.h"
32 #include "power-boot.h"
33 #include "power-off.h"
34 #include "power-state-wait.h"
35 #include "power-event-lock.h"
36
37 #define EVENT_TYPE_SLEEP    0
38 #define EVENT_TYPE_WAKEUP   1
39
40 char *psm_name[PSM_MAX] = {
41         [PSM_START] = "PSM_START",
42         [PSM_NORMAL] = "PSM_NORMAL",
43         [PSM_SLEEP] = "PSM_SLEEP",
44         [PSM_POWEROFF] = "PSM_POWEROFF",
45         [PSM_REBOOT] = "PSM_REBOOT",
46 };
47
48 static int delayed_init_done = 0;
49 static guint64 state_transition_counter = 0;
50 static enum psm_state current = PSM_START;
51
52 /* hold trans_info until delayed_init_done */
53 static GList *deferred_transition_list;
54
55 static void psm_wake_unlock(void)
56 {
57         /* for PSM_NORMAL, PSM_POWEROFF, do not wake unlock */
58         if (current != PSM_SLEEP) {
59                 _E("Ignore sleep wait done, current=%s", psm_name[current]);
60                 return;
61         }
62
63         power_release_wakelock();
64 }
65
66 static void psm_trigger_poweroff(void)
67 {
68         poweroff_trigger_poweroff("poweroff");
69 }
70
71 static void broadcast_transition_info(const struct trans_info *ti)
72 {
73         // mapping deviced state to capi signame
74         static const char *capi_signame[PSM_MAX] = {
75                 [PSM_START] = SIGNAME_CHANGE_STATE_TO_START,
76                 [PSM_NORMAL] = SIGNAME_CHANGE_STATE_TO_NORMAL,
77                 [PSM_SLEEP] = SIGNAME_CHANGE_STATE_TO_SLEEP,
78                 [PSM_POWEROFF] = SIGNAME_CHANGE_STATE_TO_POWEROFF,
79                 [PSM_REBOOT] = SIGNAME_CHANGE_STATE_TO_REBOOT,
80         };
81
82         // mapping deviced state to capi state
83         static const guint64 capi_state[PSM_MAX] = {
84                 [PSM_START] = POWER_STATE_START,
85                 [PSM_NORMAL] = POWER_STATE_NORMAL,
86                 [PSM_SLEEP] = POWER_STATE_SLEEP,
87                 [PSM_POWEROFF] = POWER_STATE_POWEROFF,
88                 [PSM_REBOOT] = POWER_STATE_REBOOT,
89         };
90
91         gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER, capi_signame[ti->next],
92                 g_variant_new("(ttti)", capi_state[ti->curr], capi_state[ti->next], state_transition_counter, ti->reason));
93 }
94
95 static void psm_transition_start_to_normal(const struct trans_info *ti)
96 {
97         current = PSM_NORMAL;
98
99         power_acquire_wakelock();
100         broadcast_transition_info(ti);
101 }
102
103 static void psm_transition_start_to_sleep(const struct trans_info *ti)
104 {
105         int waiting;
106
107         current = PSM_SLEEP;
108
109         power_acquire_wakelock();
110         broadcast_transition_info(ti);
111         waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock);
112         if (waiting > 0) {
113                 _D("Defer wake unlock.");
114                 return;
115         }
116
117         psm_wake_unlock();
118 }
119
120 static void psm_transition_normal_to_normal(const struct trans_info *ti)
121 {
122         broadcast_transition_info(ti);
123         update_change_state_wait(state_transition_counter, ti, NULL);
124 }
125
126 static void psm_transition_normal_to_sleep(const struct trans_info *ti)
127 {
128         int waiting;
129
130         current = PSM_SLEEP;
131
132         broadcast_transition_info(ti);
133         waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock);
134         if (waiting > 0) {
135                 _D("Defer wake unlock.");
136                 return;
137         }
138
139         psm_wake_unlock();
140 }
141
142 static void psm_transition_sleep_to_normal(const struct trans_info *ti)
143 {
144         current = PSM_NORMAL;
145
146         power_acquire_wakelock();
147         broadcast_transition_info(ti);
148         update_change_state_wait(state_transition_counter, ti, NULL);
149 }
150
151 static void psm_transition_sleep_to_sleep(const struct trans_info *ti)
152 {
153         int waiting;
154
155         power_acquire_wakelock();
156         broadcast_transition_info(ti);
157         waiting = update_change_state_wait(state_transition_counter, ti, psm_wake_unlock);
158         if (waiting > 0) {
159                 _D("Defer wake unlock.");
160                 return;
161         }
162
163         psm_wake_unlock();
164 }
165
166 static void psm_transition_normal_to_poweroff(const struct trans_info *ti)
167 {
168         int waiting;
169
170         current = PSM_POWEROFF;
171
172         broadcast_transition_info(ti);
173         waiting = update_change_state_wait(state_transition_counter, ti, psm_trigger_poweroff);
174         if (waiting > 0) {
175                 _D("Defer poweroff.");
176                 return;
177         }
178
179         psm_trigger_poweroff();
180 }
181
182 static void transition_state(const struct trans_info *ti)
183 {
184         enum psm_state next;
185
186         next = ti->next;
187
188         _D("Transition power state: %s -> %s, reason=%d",
189                 psm_name[current], psm_name[next], ti->reason);
190
191         /* transition */
192         ++state_transition_counter;
193         if (current == PSM_START) {
194                 if (next == PSM_NORMAL)
195                         psm_transition_start_to_normal(ti);
196                 else if (next == PSM_SLEEP)
197                         psm_transition_start_to_sleep(ti);
198         } else if (current == PSM_NORMAL) {
199                 if (next == PSM_NORMAL)
200                         psm_transition_normal_to_normal(ti);
201                 else if (next == PSM_SLEEP)
202                         psm_transition_normal_to_sleep(ti);
203                 else if (next == PSM_POWEROFF)
204                         psm_transition_normal_to_poweroff(ti);
205         } else if (current == PSM_SLEEP) {
206                 if (next == PSM_NORMAL)
207                         psm_transition_sleep_to_normal(ti);
208                 else if (next == PSM_SLEEP)
209                         psm_transition_sleep_to_sleep(ti);
210         }
211 }
212
213 static void deferred_transition_state(gpointer data)
214 {
215         transition_state(data);
216         free(data);
217 }
218
219 static int psm_transition_state_cb(void *data)
220 {
221         GList *action_list, *elem;
222         const struct trans_info *ti = NULL;
223
224         if (!data)
225                 return 0;
226
227         action_list = (GList *) data;
228
229         /* look for transition defined on the current state */
230         SYS_G_LIST_FOREACH(action_list, elem, ti) {
231                 if (ti->curr == current)
232                         break;
233         }
234
235         if (!ti)
236                 return 0;
237
238         /* defer state transition until delayed_init_done */
239         if (!delayed_init_done) {
240                 struct trans_info *deferred_ti = calloc(1, sizeof(struct trans_info));
241                 if (!deferred_ti) {
242                         CRITICAL_LOG("Failed to defer transition.");
243                         return 0;
244                 }
245
246                 // Pseudo state transition.
247                 current = ti->next;
248
249                 // Reserve the trans_info.
250                 // Those are used on receiving delayed_init_done for real transitioning state.
251                 memcpy(deferred_ti, ti, sizeof(struct trans_info));
252                 deferred_transition_list = g_list_append(deferred_transition_list, deferred_ti);
253                 _D("Defer state transition %s->%s until delayed init done.", psm_name[ti->curr], psm_name[ti->next]);
254
255                 return 0;
256         }
257
258         transition_state(ti);
259
260         return 0;
261 }
262
263 static int delayed_init_cb(void *data)
264 {
265         delayed_init_done = 1;
266
267         _D("Start deferred state transition.");
268
269          /* rewind current state to initial state and do the deferred transition */
270         current = PSM_START;
271         g_list_free_full(g_steal_pointer(&deferred_transition_list), deferred_transition_state);
272
273         /* Enable autosleep at this point.
274          * This prevents system go suspend(autosleep) before booting done */
275         _D("Finished deferred state transition. Enable autosleep.");
276         power_enable_autosleep();
277
278         return 0;
279 }
280
281 void power_state_manager_init(void *data)
282 {
283         GList *initial_ti = NULL;
284
285         register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_cb);
286         register_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, psm_transition_state_cb);
287
288         power_dbus_init();
289         power_off_init();
290         power_suspend_init();
291         power_event_lock_init();
292         power_state_wait_init();
293
294         /* Take the first transition from PSM_START.
295          * It is determined by bootreason to which state to transition, PSM_NORMAL or PSM_SLEEP. */
296         get_initial_transition_by_bootreason(&initial_ti);
297         psm_transition_state_cb(initial_ti);
298         g_list_free(initial_ti);
299 }
300
301 static const struct device_ops power_state_manager_device_ops = {
302         DECLARE_NAME_LEN("power-state-manager"),
303         .init              = power_state_manager_init,
304         /* It should be initilalized earlier than the almost other modules so that
305          * it can receive and handle power request from the other modules. Therefore
306          * give a high enough priority. */
307         .priority          = 990,
308         .execute           = poweroff_trigger_poweroff,
309 };
310
311 DEVICE_OPS_REGISTER(&power_state_manager_device_ops)