3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
22 * @brief Power manager main loop.
24 * This file includes Main loop, the FSM, signal processing.
36 #include <sys/types.h>
42 #include <vconf-keys.h>
43 #include <device-node.h>
46 #include "pm_battery.h"
48 #define USB_CON_PIDFILE "/var/run/.system_server.pid"
49 #define PM_STATE_LOG_FILE "/var/log/pm_state.log"
50 #define PM_WAKEUP_NOTI_NAME "system_wakeup"
51 #define PM_EVENT_NOTI_NAME "pm_event"
52 #define PM_EVENT_NOTI_PATH "/opt/share/noti/"PM_EVENT_NOTI_NAME
55 * @addtogroup POWER_MANAGER
59 #define LOCKSTATUS_TIMEOUT 3
60 #define TELEPHONY_SIGNAL_TIMEOUT 10
62 #define SET_BRIGHTNESS_IN_BOOTLOADER "/usr/bin/save_blenv SLP_LCD_BRIGHT"
64 /* default transition, action fuctions */
65 static int default_trans(int evt);
66 static int default_action(int timeout);
67 static int default_check(int next);
69 unsigned int status_flag;
71 static void (*power_saving_func) (int onoff);
72 static void reset_timeout(int timeout);
76 static GMainLoop *mainloop;
79 static int pre_suspend_flag = false;
80 int system_wakeup_flag = false;
82 struct state states[S_END] = {
83 {S_START, default_trans, default_action, default_check,},
84 {S_NORMAL, default_trans, default_action, default_check,},
85 {S_LCDDIM, default_trans, default_action, default_check,},
86 {S_LCDOFF, default_trans, default_action, default_check,},
87 {S_SLEEP, default_trans, default_action, default_check,}
90 int (*pm_init_extention) (void *data);
91 void (*pm_exit_extention) (void);
93 static char state_string[5][10] =
94 { "S_START", "S_NORMAL", "S_LCDDIM", "S_LCDOFF", "S_SLEEP" };
96 static int trans_table[S_END][EVENT_END] = {
98 {S_START, S_START}, /* S_START */
99 {S_LCDDIM, S_NORMAL}, /* S_NORMAL */
100 {S_LCDOFF, S_NORMAL}, /* S_LCDDIM */
102 {S_LCDOFF, S_NORMAL}, /* S_LCDOFF */
104 {S_SLEEP, S_NORMAL}, /* S_LCDOFF */
106 {S_LCDOFF, S_NORMAL}, /* S_SLEEP, When wake up by devices, go lcd_off state */
109 #define SHIFT_UNLOCK 4
110 #define MASK_RESET_TIMEOUT 0x8 /* 1000 */
111 #define MASK_MARGIN_TIMEOUT (0x1 << 8)
112 #define SHIFT_CHANGE_STATE 7
113 #define CHANGE_STATE_BIT 0xF00 /* 1111 0000 0000 */
114 #define LOCK_SCREEN_TIMEOUT 5
115 #define SHIFT_HOLD_KEY_BLOCK 16
117 #define DEFAULT_NORMAL_TIMEOUT 30
118 #define DEFAULT_DIM_TIMEOUT 5
119 #define DEFAULT_OFF_TIMEOUT 5
120 #define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_HOLD_KEY_BLOCK) & 0x1)
122 static int received_sleep_cmd = 0;
124 typedef struct _node {
127 gboolean holdkey_block;
131 static Node *cond_head[S_END];
133 static int refresh_app_cond()
137 if (cond_head[S_LCDDIM] != NULL)
138 trans_condition = trans_condition | MASK_DIM;
139 if (cond_head[S_LCDOFF] != NULL)
140 trans_condition = trans_condition | MASK_OFF;
141 if (cond_head[S_SLEEP] != NULL)
142 trans_condition = trans_condition | MASK_SLP;
147 static Node *find_node(enum state_t s_index, pid_t pid)
149 Node *t = cond_head[s_index];
159 static Node *add_node(enum state_t s_index, pid_t pid, int timeout_id,
160 gboolean holdkey_block)
164 n = (Node *) malloc(sizeof(Node));
166 LOGERR("Not enough memory, add cond. fail");
171 n->timeout_id = timeout_id;
172 n->holdkey_block = holdkey_block;
173 n->next = cond_head[s_index];
174 cond_head[s_index] = n;
180 static int del_node(enum state_t s_index, Node *n)
188 t = cond_head[s_index];
193 prev->next = t->next;
195 cond_head[s_index] = cond_head[s_index]->next;
206 static gboolean del_dim_cond(gpointer data)
209 LOGINFO("delete prohibit dim condition by timeout\n");
211 tmp = find_node(S_LCDDIM, (pid_t) data);
212 del_node(S_LCDDIM, tmp);
214 if (timeout_src_id == 0)
215 states[cur_state].trans(EVENT_TIMEOUT);
220 static gboolean del_off_cond(gpointer data)
223 LOGINFO("delete prohibit off condition by timeout\n");
225 tmp = find_node(S_LCDOFF, (pid_t) data);
226 del_node(S_LCDOFF, tmp);
228 if (timeout_src_id == 0)
229 states[cur_state].trans(EVENT_TIMEOUT);
234 static gboolean del_sleep_cond(gpointer data)
237 LOGINFO("delete prohibit sleep condition by timeout\n");
239 tmp = find_node(S_SLEEP, (pid_t) data);
240 del_node(S_SLEEP, tmp);
242 if (timeout_src_id == 0)
243 states[cur_state].trans(EVENT_TIMEOUT);
245 sysman_inform_inactive((pid_t) data);
249 /* update transition condition for application requrements */
250 static int proc_condition(PMMsg *data)
253 unsigned int val = data->cond;
254 pid_t pid = data->pid;
255 int cond_timeout_id = -1;
256 gboolean holdkey_block = 0;
261 char pname[PATH_MAX];
264 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
265 fd_cmdline = open(buf, O_RDONLY);
266 if (fd_cmdline < 0) {
267 snprintf(pname, PATH_MAX,
268 "does not exist now(may be dead without unlock)");
270 read(fd_cmdline, pname, PATH_MAX);
274 if (val & MASK_DIM) {
275 if (data->timeout > 0) {
277 g_timeout_add_full(G_PRIORITY_DEFAULT,
279 (GSourceFunc) del_dim_cond,
280 (gpointer) pid, NULL);
282 holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
283 tmp = find_node(S_LCDDIM, pid);
285 add_node(S_LCDDIM, pid, cond_timeout_id, holdkey_block);
286 else if (tmp->timeout_id > 0) {
287 g_source_remove(tmp->timeout_id);
288 tmp->timeout_id = cond_timeout_id;
289 tmp->holdkey_block = holdkey_block;
292 LOGINFO("[%s] locked by pid %d - process %s\n", "S_NORMAL", pid,
295 if (val & MASK_OFF) {
296 if (data->timeout > 0) {
298 g_timeout_add_full(G_PRIORITY_DEFAULT,
300 (GSourceFunc) del_off_cond,
301 (gpointer) pid, NULL);
303 holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
304 tmp = find_node(S_LCDOFF, pid);
306 add_node(S_LCDOFF, pid, cond_timeout_id, holdkey_block);
307 else if (tmp->timeout_id > 0) {
308 g_source_remove(tmp->timeout_id);
309 tmp->timeout_id = cond_timeout_id;
310 tmp->holdkey_block = holdkey_block;
313 LOGINFO("[%s] locked by pid %d - process %s\n", "S_LCDDIM", pid,
316 if (val & MASK_SLP) {
317 if (data->timeout > 0) {
319 g_timeout_add_full(G_PRIORITY_DEFAULT,
321 (GSourceFunc) del_sleep_cond,
322 (gpointer) pid, NULL);
324 tmp = find_node(S_SLEEP, pid);
326 add_node(S_SLEEP, pid, cond_timeout_id, 0);
327 else if (tmp->timeout_id > 0) {
328 g_source_remove(tmp->timeout_id);
329 tmp->timeout_id = cond_timeout_id;
330 tmp->holdkey_block = 0;
332 sysman_inform_active(pid);
334 LOGINFO("[%s] locked by pid %d - process %s\n", "S_LCDOFF", pid,
338 /* UNLOCK(GRANT) condition processing */
339 val = val >> SHIFT_UNLOCK;
340 if (val & MASK_DIM) {
341 tmp = find_node(S_LCDDIM, pid);
342 del_node(S_LCDDIM, tmp);
343 LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LORMAL",
346 if (val & MASK_OFF) {
347 tmp = find_node(S_LCDOFF, pid);
348 del_node(S_LCDOFF, tmp);
349 LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LCDDIM",
352 if (val & MASK_SLP) {
353 tmp = find_node(S_SLEEP, pid);
354 del_node(S_SLEEP, tmp);
355 sysman_inform_inactive(pid);
356 LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LCDOFF",
362 reset_timeout(states[cur_state].timeout);
363 LOGINFO("reset timeout\n", "S_LCDOFF", pid, pname);
366 /* guard time for suspend */
367 if (cur_state == S_LCDOFF) {
369 LOGINFO("margin timeout (5 seconds)\n");
373 if (timeout_src_id == 0)
374 states[cur_state].trans(EVENT_TIMEOUT);
379 static int proc_change_state(unsigned int cond)
385 for (i = S_NORMAL; i < S_END; i++) {
386 if ((cond >> (SHIFT_CHANGE_STATE + i)) & 0x1) {
391 LOGINFO("Change State to %s", state_string[next_state]);
393 switch (next_state) {
397 /* state transition */
398 old_state = cur_state;
399 cur_state = next_state;
400 st = &states[cur_state];
404 st->action(st->timeout);
408 LOGINFO("Dangerous requests.");
409 /* at first LCD_OFF and then goto sleep */
410 /* state transition */
411 old_state = cur_state;
412 cur_state = S_LCDOFF;
413 st = &states[cur_state];
417 old_state = cur_state;
419 st = &states[cur_state];
432 /* If some changed, return 1 */
433 int check_processes(enum state_t prohibit_state)
435 Node *t = cond_head[prohibit_state];
440 if (kill(t->pid, 0) == -1) {
442 ("%d process does not exist, delete the REQ - prohibit state %d ",
443 t->pid, prohibit_state);
450 del_node(prohibit_state, tmp);
458 int check_holdkey_block(enum state_t state)
460 Node *t = cond_head[state];
463 LOGINFO("check holdkey block : state of %s", state_string[state]);
466 if(t->holdkey_block == true) {
468 LOGINFO("Hold key blocked by pid(%d)!", t->pid);
477 int delete_condition(enum state_t state)
479 Node *t = cond_head[state];
483 LOGINFO("delete condition : state of %s", state_string[state]);
486 if(t->timeout_id > 0) {
487 g_source_remove(t->timeout_id);
491 LOGINFO("delete node of pid(%d)", tmp->pid);
492 del_node(state, tmp);
498 /* SIGINT, SIGTERM, SIGQUIT signal handler */
499 static void sig_quit(int signo)
501 LOGINFO("received %d signal : stops a main loop", signo);
503 g_main_loop_quit(mainloop);
506 void print_info(int fd)
515 snprintf(buf, sizeof(buf),
516 "\n======================================================================\n");
517 write(fd, buf, strlen(buf));
518 snprintf(buf, sizeof(buf),"Timeout Info: Run[%d] Dim[%d] Off[%d]\n",
519 states[S_NORMAL].timeout,
520 states[S_LCDDIM].timeout, states[S_LCDOFF].timeout);
521 write(fd, buf, strlen(buf));
523 snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n",
524 (trans_condition & MASK_DIM) ? state_string[S_NORMAL] : "-",
525 (trans_condition & MASK_OFF) ? state_string[S_LCDDIM] : "-",
526 (trans_condition & MASK_SLP) ? state_string[S_LCDOFF] : "-");
527 write(fd, buf, strlen(buf));
529 snprintf(buf, sizeof(buf), "Current State: %s\n", state_string[cur_state]);
530 write(fd, buf, strlen(buf));
532 snprintf(buf, sizeof(buf), "Current Lock Conditions: \n");
533 write(fd, buf, strlen(buf));
535 for (s_index = S_NORMAL; s_index < S_END; s_index++) {
537 char pname[PATH_MAX];
539 t = cond_head[s_index];
542 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", t->pid);
543 fd_cmdline = open(buf, O_RDONLY);
544 if (fd_cmdline < 0) {
545 snprintf(pname, PATH_MAX,
546 "does not exist now(may be dead without unlock)");
548 read(fd_cmdline, pname, PATH_MAX);
551 snprintf(buf, sizeof(buf),
552 " %d: [%s] locked by pid %d - process %s\n",
553 i++, state_string[s_index - 1], t->pid, pname);
554 write(fd, buf, strlen(buf));
560 /* SIGHUP signal handler
561 * For debug... print info to syslog
563 static void sig_hup(int signo)
571 fd = open(PM_STATE_LOG_FILE, O_CREAT | O_WRONLY, 0644);
573 snprintf(buf, sizeof(buf), "\npm_state_log now-time : %d (s)\n\n",
575 write(fd, buf, strlen(buf));
577 snprintf(buf, sizeof(buf), "status_flag: %x\n", status_flag);
578 write(fd, buf, strlen(buf));
580 snprintf(buf, sizeof(buf), "received sleep cmd count : %d\n",
582 write(fd, buf, strlen(buf));
588 fd = open("/dev/console", O_WRONLY);
595 /* timeout handler */
596 gboolean timeout_handler(gpointer data)
598 LOGINFO("Time out state %s\n", state_string[cur_state]);
600 if (timeout_src_id != 0) {
601 g_source_remove(timeout_src_id);
605 if ((status_flag & VCALL_FLAG)
606 && (cur_state == S_LCDOFF || cur_state == S_SLEEP)) {
607 status_flag &= ~(VCALL_FLAG);
608 reset_timeout(TELEPHONY_SIGNAL_TIMEOUT);
611 states[cur_state].trans(EVENT_TIMEOUT);
615 static void reset_timeout(int timeout)
617 if (timeout_src_id != 0) {
618 g_source_remove(timeout_src_id);
622 timeout_src_id = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
630 static void sig_usr(int signo)
632 status_flag |= VCALL_FLAG;
635 static void sig_break_block(int signo)
637 LOGINFO("We got signal to break that pending checking in kernel\n");
641 * default transition function
644 * 3. call enter action function
646 static int default_trans(int evt)
648 struct state *st = &states[cur_state];
651 if(cur_state == S_NORMAL && st->timeout == 0) {
652 LOGINFO("LCD always on enabled!");
656 next_state = (enum state_t)trans_table[cur_state][evt];
658 /* check conditions */
659 while (st->check && !st->check(next_state)) {
660 /* There is a condition. */
661 LOGINFO("%s -> %s : check fail", state_string[cur_state],
662 state_string[next_state]);
663 if (!check_processes(next_state)) {
664 /* this is valid condition - the application that sent the condition is running now. */
669 /* state transition */
670 old_state = cur_state;
671 cur_state = next_state;
672 st = &states[cur_state];
676 st->action(st->timeout);
682 /* default enter action function */
683 static int default_action(int timeout)
686 int wakeup_count = -1;
688 char *pkgname = NULL;
691 struct itimerval val;
693 if (cur_state != old_state && cur_state != S_SLEEP)
694 set_setting_pmstate(cur_state);
698 /* normal state : backlight on and restore the previous brightness */
699 if (old_state == S_LCDOFF || old_state == S_SLEEP) {
700 if (pre_suspend_flag == true) {
701 system_post_resume();
702 pre_suspend_flag = false;
704 for (i = 0; i < 14; i++) {
705 vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
706 LOGERR("Idle lock check : %d, vonf : %d", i, lock_state);
711 #ifndef X86 /* Different with ARM FB driver, IA gfx driver is sensitive to the order. */
718 } else if (old_state == S_LCDDIM)
723 if (old_state == S_LCDOFF || old_state == S_SLEEP) {
726 /* lcd dim state : dim the brightness */
731 if (old_state != S_SLEEP && old_state != S_LCDOFF) {
732 /* lcd off state : turn off the backlight */
734 if (pre_suspend_flag == false) {
735 pre_suspend_flag = true;
736 system_pre_suspend();
743 * We can not always be blocked here because of that
744 * in-progress checking in kernel for wakeup count,
745 * if we cannot get the result within some time, then
746 * just give it up and then retry it in the next time,
747 * this method would not break that original expected
748 * 'aggresive suspend' idea, but at the same time make
749 * the system is 'always' responsible to some keypress
750 * actions like power button press.
752 val.it_value.tv_sec = TOLERANCE_SLOT;
753 val.it_value.tv_usec = 0;
754 val.it_interval.tv_sec = val.it_interval.tv_usec = 0;
755 setitimer(ITIMER_REAL, &val, NULL);
757 /* sleep state : set system mode to SUSPEND */
758 if (0 > device_get_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_COUNT, &wakeup_count))
759 LOGERR("wakeup count read error");
761 if (wakeup_count < 0) {
762 LOGINFO("Wakup Event! Can not enter suspend mode.");
766 if (0 > device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_COUNT, wakeup_count)) {
767 LOGERR("wakeup count write error");
774 /* set timer with current state timeout */
775 reset_timeout(timeout);
776 LOGINFO("timout set: %s state %d sec", state_string[cur_state], timeout);
782 LOGINFO("system wakeup!!");
783 system_wakeup_flag = true;
784 heynoti_publish(PM_WAKEUP_NOTI_NAME);
786 if (check_wakeup_src() == EVENT_DEVICE)
787 /* system waked up by devices */
788 states[cur_state].trans(EVENT_DEVICE);
790 /* system waked up by user input */
791 states[cur_state].trans(EVENT_INPUT);
795 heynoti_publish(PM_WAKEUP_NOTI_NAME);
797 states[cur_state].trans(EVENT_DEVICE);
802 * default check function
804 * 0 : can't transit, others : transitable
806 static int default_check(int next)
808 int trans_cond = trans_condition & MASK_BIT;
811 LOGINFO("trans_cond : %x", trans_cond);
813 vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
814 if(lock_state==VCONFKEY_IDLE_LOCK && next != S_SLEEP) {
815 LOGINFO("default_check : LOCK STATE, it's transitable");
821 trans_cond = trans_cond & MASK_DIM;
824 trans_cond = trans_cond & MASK_OFF;
827 trans_cond = trans_cond & MASK_SLP;
829 default: /* S_NORMAL is exceptional */
837 return 1; /* transitable */
840 /* get configurations from setting */
841 static int get_settings()
848 for (i = 0; i < S_END; i++) {
849 switch (states[i].state) {
851 ret = get_run_timeout(&val);
853 ret = get_env("PM_TO_NORMAL", buf, 255);
858 ret = get_dim_timeout(&val);
861 ret = get_off_timeout(&val);
864 /* This state doesn't need to set time out. */
868 if (ret == 0 || val < 0) {
869 states[i].timeout = val;
871 switch (states[i].state) {
873 states[i].timeout = DEFAULT_NORMAL_TIMEOUT;
876 states[i].timeout = DEFAULT_DIM_TIMEOUT;
879 states[i].timeout = DEFAULT_OFF_TIMEOUT;
882 states[i].timeout = 0;
886 LOGINFO("%s state : %d timeout", state_string[i], states[i].timeout);
892 static void default_saving_mode(int onoff)
895 status_flag |= PWRSV_FLAG;
897 status_flag &= ~PWRSV_FLAG;
899 if (cur_state == S_NORMAL)
903 static int poll_callback(int condition, PMMsg *data)
907 if (condition == INPUT_POLL_EVENT) {
908 if (cur_state == S_LCDOFF || cur_state == S_SLEEP)
909 LOGINFO("Power key input");
912 states[cur_state].trans(EVENT_INPUT);
915 } else if (condition == PM_CONTROL_EVENT) {
916 LOGINFO("process pid(%d) pm_control condition : %x ", data->pid,
919 if (data->cond & MASK_BIT
920 || (data->cond >> SHIFT_UNLOCK) & MASK_BIT)
921 proc_condition(data);
923 if (data->cond & CHANGE_STATE_BIT) {
925 LOGINFO("Change state by pid(%d) request.", data->pid);
926 proc_change_state(data->cond);
933 static int update_setting(int key_idx, int val)
937 int dim_timeout = -1;
938 int run_timeout = -1;
939 int power_saving_stat = -1;
940 int power_saving_display_stat = -1;
943 case SETTING_TO_NORMAL:
944 ret = get_dim_timeout(&dim_timeout);
945 if(ret < 0 || dim_timeout < 0) {
946 LOGERR("Can not get dim timeout. set default 5 seconds");
950 LOGERR("LCD timeout is wrong, set default 15 seconds");
954 states[S_NORMAL].timeout = 0;
955 } else if(val > dim_timeout) {
956 states[S_NORMAL].timeout = val - dim_timeout;
958 states[S_NORMAL].timeout = 1;
960 states[cur_state].trans(EVENT_INPUT);
962 case SETTING_LOW_BATT:
963 if (val < VCONFKEY_SYSMAN_BAT_WARNING_LOW) {
964 if (!(status_flag & CHRGR_FLAG))
965 power_saving_func(true);
966 status_flag |= LOWBT_FLAG;
968 if (status_flag & PWRSV_FLAG)
969 power_saving_func(false);
970 status_flag &= ~LOWBT_FLAG;
971 status_flag &= ~BRTCH_FLAG;
972 vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
976 case SETTING_CHARGING:
978 if (status_flag & LOWBT_FLAG) {
979 power_saving_func(false);
980 status_flag &= ~LOWBT_FLAG;
982 status_flag |= CHRGR_FLAG;
984 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
985 vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
986 if(bat_state < VCONFKEY_SYSMAN_BAT_NORMAL) {
987 power_saving_func(true);
988 status_flag |= LOWBT_FLAG;
990 status_flag &= ~CHRGR_FLAG;
993 case SETTING_BRT_LEVEL:
994 if (status_flag & PWRSV_FLAG) {
995 status_flag |= BRTCH_FLAG;
996 vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
998 LOGINFO("brightness changed in low battery, escape dim state");
1000 set_default_brt(val);
1001 snprintf(buf, sizeof(buf), "%s %d", SET_BRIGHTNESS_IN_BOOTLOADER, val);
1002 LOGINFO("Brightness set in bl : %d",val);
1005 case SETTING_LOCK_SCREEN:
1006 if (val == VCONFKEY_IDLE_LOCK) {
1007 states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
1008 LOGERR("LCD NORMAL timeout is set by %d seconds for lock screen", LOCK_SCREEN_TIMEOUT);
1010 get_run_timeout(&run_timeout);
1011 if(run_timeout < 0) {
1012 LOGERR("Can not get run timeout. set default 15 seconds(includes dim 5 seconds)");
1015 states[S_NORMAL].timeout = run_timeout;
1016 LOGINFO("LCD NORMAL timeout is set by %d seconds because phone is unlocked", run_timeout);
1018 if (cur_state == S_NORMAL) {
1019 states[cur_state].trans(EVENT_INPUT);
1022 case SETTING_POWER_SAVING:
1024 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, &power_saving_display_stat);
1025 if (power_saving_display_stat != 1)
1026 power_saving_display_stat = 0;
1027 device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_FRAME_RATE, power_saving_display_stat);
1028 backlight_restore();
1030 case SETTING_POWER_SAVING_DISPLAY:
1031 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
1032 if (power_saving_stat == 1) {
1034 power_saving_display_stat = 1;
1036 power_saving_display_stat = 0;
1037 device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_FRAME_RATE, power_saving_display_stat);
1038 backlight_restore();
1047 static void check_seed_status(void)
1051 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
1054 int lock_state = -1;
1056 /* Charging check */
1057 if ((get_charging_status(&tmp) == 0) && (tmp > 0)) {
1058 status_flag |= CHRGR_FLAG;
1061 ret = get_setting_brightness(&tmp);
1062 if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
1063 LOGINFO("fail to read vconf value for brightness");
1064 brt = PM_DEFAULT_BRIGHTNESS;
1065 if(tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)
1066 vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
1069 LOGINFO("Set brightness from Setting App. %d", tmp);
1070 set_default_brt(tmp);
1072 vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
1073 if (bat_state < VCONFKEY_SYSMAN_BAT_NORMAL) {
1074 if (!(status_flag & CHRGR_FLAG)) {
1075 power_saving_func(true);
1076 status_flag |= LOWBT_FLAG;
1079 backlight_restore();
1081 /* USB connection check
1082 * If connected, add sleep prohibit condition */
1083 if ((get_usb_status(&tmp) == 0) && (tmp > 0)) {
1084 tmp = readpid(USB_CON_PIDFILE);
1086 add_node(S_SLEEP, tmp, -1, 0);
1090 /* lock screen check */
1091 ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1092 if(lock_state == VCONFKEY_IDLE_LOCK) {
1093 states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
1094 LOGERR("LCD NORMAL timeout is set by %d seconds for lock screen", LOCK_SCREEN_TIMEOUT);
1108 static char *errMSG[INIT_END] = {
1109 [INIT_SETTING] = "setting init error",
1110 [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
1111 [INIT_POLL] = "input devices poll init error",
1112 [INIT_FIFO] = "FIFO poll init error",
1115 /* logging indev_list for debug */
1122 total=g_list_length(indev_list);
1123 LOGINFO("***** total list : %d *****",total);
1124 for(i=0;i<total;i++) {
1125 tmp=(indev*)(g_list_nth(indev_list, i)->data);
1126 LOGINFO("* %d | path:%s, gsource:%d, gfd:%d", i, tmp->dev_path, tmp->dev_src, tmp->dev_fd);
1127 if(i==total-1 && g_list_nth(indev_list, i)->next==NULL)
1130 LOGINFO("***************************\n");
1133 static GList *find_glist(GList *glist, char *path)
1139 total=g_list_length(indev_list);
1140 for(i=0;i<total;i++) {
1141 tmp=(indev*)(g_list_nth(indev_list, i)->data);
1142 if(!strcmp(tmp->dev_path, path)){
1143 LOGINFO("nth : %d, path:%s, gsource:%d, gfd:%d", i, tmp->dev_path, tmp->dev_src, tmp->dev_fd);
1144 return g_list_nth(indev_list, i);
1150 static void input_cb(void* data)
1153 char input_act[NAME_MAX], input_path[MAX_INPUT];
1154 char args[NAME_MAX + MAX_INPUT];
1156 GList *glist = NULL;
1158 fp = fopen((char *) data, "r");
1160 LOGERR("input file open fail");
1164 while (fgets(args, NAME_MAX + MAX_INPUT, fp) != NULL){
1165 if( args[strlen(args)-1] != '\n'){
1166 LOGERR("input file must be terminated with new line character\n");
1169 args[strlen(args) - 1] = '\0';
1170 for(i = 0; i< NAME_MAX + MAX_INPUT; i++){
1172 if( i >= NAME_MAX ){
1173 LOGERR("bsfile name is over the name_max(255)\n");
1176 strncpy(input_act, args, i < NAME_MAX ? i : NAME_MAX);
1178 strncpy(input_path, args + i + 1, MAX_INPUT);
1179 input_path[MAX_INPUT - 1] = '\0';
1181 if( !strcmp("add", input_act) ){
1182 LOGINFO("add input path:%s",input_path);
1184 ret=init_pm_poll_input(poll_callback, input_path);
1186 } else if ( !strcmp("remove", input_act) ){
1187 glist=find_glist(indev_list, input_path);
1189 LOGINFO("remove input dev");
1190 g_source_remove_poll(((indev*)(glist->data))->dev_src, ((indev*)(glist->data))->dev_fd);
1191 g_source_destroy(((indev*)(glist->data))->dev_src);
1192 close(((indev*)(glist->data))->dev_fd->fd);
1193 g_free(((indev*)(glist->data))->dev_fd);
1194 free(((indev*)(glist->data))->dev_path);
1195 indev_list=g_list_remove(indev_list, glist->data);
1211 fp = fopen((char *) data, "w");
1221 static int set_noti(int *noti_fd)
1226 fd = heynoti_init();
1228 LOGERR("heynoti_init error");
1232 if (heynoti_subscribe(fd, PM_EVENT_NOTI_NAME, input_cb, PM_EVENT_NOTI_PATH) < 0) {
1233 LOGERR("input file change noti add failed(%s). %s", buf, strerror(errno));
1236 LOGERR("input file change noti add ok");
1239 if (heynoti_attach_handler(fd) < 0) {
1240 LOGERR("heynoti_attach_handler error");
1248 static int unset_noti(int noti_fd)
1251 LOGINFO("set noti already failed. nothing to do in unset");
1255 if (heynoti_unsubscribe(noti_fd, PM_EVENT_NOTI_NAME, input_cb) < 0 || heynoti_detach_handler(noti_fd) < 0) {
1256 LOGERR("heynoti unsubsribe or detach error");
1263 * Power manager Main loop
1266 * @param[in] flags If the first bit of this is set, start managing without Start notification.
1267 * If the second bit of ths is set, use unified device manager functions.
1269 void start_main(unsigned int flags)
1273 LOGINFO("Start power manager daemon");
1275 signal(SIGINT, sig_quit);
1276 signal(SIGTERM, sig_quit);
1277 signal(SIGQUIT, sig_quit);
1278 signal(SIGHUP, sig_hup);
1279 signal(SIGCHLD, SIG_IGN);
1280 signal(SIGUSR1, sig_usr);
1281 signal(SIGALRM, sig_break_block);
1283 mainloop = g_main_loop_new(NULL, FALSE);
1284 power_saving_func = default_saving_mode;
1286 /* noti init for new input device like bt mouse */
1291 for (i = INIT_SETTING; i < INIT_END; i++) {
1294 ret = init_setting(update_setting);
1296 case INIT_INTERFACE:
1298 ret = init_sysfs(flags);
1301 LOGINFO("poll init");
1302 ret = init_pm_poll(poll_callback);
1311 if (i == INIT_END) {
1312 check_seed_status();
1314 if (pm_init_extention != NULL)
1315 pm_init_extention(NULL);
1317 if (flags & WITHOUT_STARTNOTI) { /* start without noti */
1318 LOGINFO("Start Power managing without noti");
1319 cur_state = S_NORMAL;
1320 set_setting_pmstate(cur_state);
1321 reset_timeout(states[S_NORMAL].timeout);
1323 if (start_battinfo_gathering(BATTERY_POLLING_PERIOD) < 0)
1324 LOGERR("Start Battery time info failed!");
1326 g_main_loop_run(mainloop);
1327 g_main_loop_unref(mainloop);
1330 end_battinfo_gathering();
1331 for (i = i - 1; i >= INIT_SETTING; i--) {
1336 case INIT_INTERFACE:
1340 unset_noti(noti_fd);
1346 if (pm_exit_extention != NULL)
1347 pm_exit_extention();
1349 LOGINFO("Terminate power manager daemon");