3 #include <libsyscommon/list.h>
4 #include <device/power-internal.h>
6 #include "shared/log.h"
7 #include "shared/device-notifier.h"
8 #include "shared/common.h"
10 #include "power-state-wait.h"
11 #include "power-state-manager.h"
13 #define MAX_WAIT_SECOND 5 /* second */
22 struct change_state_wait {
28 static GList *proc_list;
29 static GList *waiting_list;
30 static int max_wait_timer;
31 static void (*__change_state_wait_done) (void);
32 static enum psm_state waiting_state;
34 static void change_state_wait_done(void)
36 _D("%s wait done", psm_name[waiting_state]);
39 g_source_remove(max_wait_timer);
43 if (__change_state_wait_done) {
44 __change_state_wait_done();
48 static gboolean max_wait_expired_cb(void *data)
50 struct change_state_wait *csw;
52 GList *elem, *elem_next;
56 SYS_G_LIST_FOREACH_SAFE(waiting_list, elem, elem_next, csw) {
57 if (kill(csw->pi->pid, 0) != 0)
60 _E("pid=%d(%s) hasn't confirmed id=%ld(%s)", csw->pi->pid, csw->pi->comm, csw->id, psm_name[csw->state]);
61 waiting_list = g_list_remove_link(waiting_list, elem);
66 SYS_G_LIST_FOREACH_SAFE(proc_list, elem, elem_next, pi) {
68 _D("Clean up not existing pid=%d(%s)", pi->pid, pi->comm);
69 proc_list = g_list_remove_link(proc_list, elem);
75 change_state_wait_done();
77 return G_SOURCE_REMOVE;
80 int add_change_state_wait(pid_t pid, guint64 state)
85 _D("pid=%d added csw for %#lx", pid, state);
87 SYS_G_LIST_FOREACH(proc_list, elem, pi) {
89 pi->state_bitmap |= state;
94 pi = calloc(1, sizeof(struct proc_info));
99 pi->state_bitmap = state;
100 get_command(pid, pi->comm, sizeof(pi->comm));
101 SYS_G_LIST_APPEND(proc_list, pi);
106 void remove_change_state_wait(pid_t pid, guint64 state)
108 struct proc_info *pi;
109 GList *elem, *elem_next;
111 _D("pid=%d removed csw for %#lx", pid, state);
113 SYS_G_LIST_FOREACH_SAFE(proc_list, elem, elem_next, pi) {
114 if (pi->pid == pid) {
115 pi->state_bitmap &= ~state;
116 if (pi->state_bitmap == 0) {
117 proc_list = g_list_remove_link(proc_list, elem);
125 int confirm_change_state_wait(pid_t pid, guint64 id)
127 struct change_state_wait *csw;
128 GList *elem, *elem_next;
130 SYS_G_LIST_FOREACH_SAFE(waiting_list, elem, elem_next, csw) {
131 if (csw->pi->pid == pid && csw->id == id) {
132 _D("pid=%d(%s) confirmed id=%lu(%s)", csw->pi->pid, csw->pi->comm, csw->id, psm_name[csw->state]);
133 waiting_list = g_list_remove_link(waiting_list, elem);
137 if (SYS_G_LIST_LENGTH(waiting_list) == 0) {
138 change_state_wait_done();
147 static int check_proc_requested_wait_for_state(struct proc_info *pi, enum psm_state state)
152 if (state == PSM_NORMAL)
153 return (pi->state_bitmap & POWER_STATE_NORMAL);
154 if (state == PSM_SLEEP)
155 return (pi->state_bitmap & POWER_STATE_SLEEP);
156 if (state == PSM_POWEROFF)
157 return (pi->state_bitmap & POWER_STATE_POWEROFF);
158 if (state == PSM_REBOOT)
159 return (pi->state_bitmap & POWER_STATE_REBOOT);
164 int update_change_state_wait(guint64 id, const struct trans_info *ti, change_state_wait_done_cb callback)
166 struct proc_info *pi;
167 struct change_state_wait *csw;
168 GList *elem, *elem_next;
172 if (max_wait_timer) {
173 g_source_remove(max_wait_timer);
177 // we are waiting for confirm of transition to the next state
178 waiting_state = ti->next;
179 _D("%s wait is triggered, id=%ld", psm_name[waiting_state], id);
181 // cancel all ongoing csw that is not a waiting for the next state
182 SYS_G_LIST_FOREACH_SAFE(waiting_list, elem, elem_next, csw) {
183 if (csw->state != waiting_state) {
184 waiting_list = g_list_remove_link(waiting_list, elem);
186 _D("Cancel waiting: pid=%d(%s) for id=%ld(%s)", csw->pi->pid, csw->pi->comm, csw->id, psm_name[csw->state]);
192 SYS_G_LIST_FOREACH(proc_list, elem, pi) {
193 if (check_proc_requested_wait_for_state(pi, waiting_state)) {
194 csw = calloc(1, sizeof(struct change_state_wait));
200 csw->state = waiting_state;
201 SYS_G_LIST_APPEND(waiting_list, csw);
205 n_waiting = SYS_G_LIST_LENGTH(waiting_list);
206 if (n_waiting == 0) {
207 _D("There were no csw requests for %s, skip waiting", psm_name[waiting_state]);
208 __change_state_wait_done = NULL;
212 __change_state_wait_done = callback;
214 _D("Expected number of wait confirm=%d", n_waiting);
215 max_wait_timer = g_timeout_add_seconds(MAX_WAIT_SECOND, max_wait_expired_cb, NULL);