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 */
101 {S_SLEEP, S_NORMAL}, /* S_LCDOFF */
102 {S_LCDOFF, S_NORMAL}, /* S_SLEEP, When wake up by devices, go lcd_off state */
105 #define SHIFT_UNLOCK 4
106 #define MASK_RESET_TIMEOUT 0x8 /* 1000 */
107 #define MASK_MARGIN_TIMEOUT (0x1 << 8)
108 #define SHIFT_CHANGE_STATE 7
109 #define CHANGE_STATE_BIT 0xF00 /* 1111 0000 0000 */
110 #define LOCK_SCREEN_TIMEOUT 5
111 #define SHIFT_HOLD_KEY_BLOCK 16
113 #define DEFAULT_NORMAL_TIMEOUT 30
114 #define DEFAULT_DIM_TIMEOUT 5
115 #define DEFAULT_OFF_TIMEOUT 5
116 #define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_HOLD_KEY_BLOCK) & 0x1)
118 static int received_sleep_cmd = 0;
120 typedef struct _node {
123 gboolean holdkey_block;
127 static Node *cond_head[S_END];
129 static int refresh_app_cond()
133 if (cond_head[S_LCDDIM] != NULL)
134 trans_condition = trans_condition | MASK_DIM;
135 if (cond_head[S_LCDOFF] != NULL)
136 trans_condition = trans_condition | MASK_OFF;
137 if (cond_head[S_SLEEP] != NULL)
138 trans_condition = trans_condition | MASK_SLP;
143 static Node *find_node(enum state_t s_index, pid_t pid)
145 Node *t = cond_head[s_index];
155 static Node *add_node(enum state_t s_index, pid_t pid, int timeout_id,
156 gboolean holdkey_block)
160 n = (Node *) malloc(sizeof(Node));
162 LOGERR("Not enough memory, add cond. fail");
167 n->timeout_id = timeout_id;
168 n->holdkey_block = holdkey_block;
169 n->next = cond_head[s_index];
170 cond_head[s_index] = n;
176 static int del_node(enum state_t s_index, Node *n)
184 t = cond_head[s_index];
189 prev->next = t->next;
191 cond_head[s_index] = cond_head[s_index]->next;
202 static gboolean del_dim_cond(gpointer data)
205 LOGINFO("delete prohibit dim condition by timeout\n");
207 tmp = find_node(S_LCDDIM, (pid_t) data);
208 del_node(S_LCDDIM, tmp);
210 if (timeout_src_id == 0)
211 states[cur_state].trans(EVENT_TIMEOUT);
216 static gboolean del_off_cond(gpointer data)
219 LOGINFO("delete prohibit off condition by timeout\n");
221 tmp = find_node(S_LCDOFF, (pid_t) data);
222 del_node(S_LCDOFF, tmp);
224 if (timeout_src_id == 0)
225 states[cur_state].trans(EVENT_TIMEOUT);
230 static gboolean del_sleep_cond(gpointer data)
233 LOGINFO("delete prohibit sleep condition by timeout\n");
235 tmp = find_node(S_SLEEP, (pid_t) data);
236 del_node(S_SLEEP, tmp);
238 if (timeout_src_id == 0)
239 states[cur_state].trans(EVENT_TIMEOUT);
241 sysman_inform_inactive((pid_t) data);
245 /* update transition condition for application requrements */
246 static int proc_condition(PMMsg *data)
249 unsigned int val = data->cond;
250 pid_t pid = data->pid;
251 int cond_timeout_id = -1;
252 gboolean holdkey_block = 0;
257 char pname[PATH_MAX];
260 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
261 fd_cmdline = open(buf, O_RDONLY);
262 if (fd_cmdline < 0) {
263 snprintf(pname, PATH_MAX,
264 "does not exist now(may be dead without unlock)");
266 read(fd_cmdline, pname, PATH_MAX);
270 if (val & MASK_DIM) {
271 if (data->timeout > 0) {
273 g_timeout_add_full(G_PRIORITY_DEFAULT,
275 (GSourceFunc) del_dim_cond,
276 (gpointer) pid, NULL);
278 holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
279 tmp = find_node(S_LCDDIM, pid);
281 add_node(S_LCDDIM, pid, cond_timeout_id, holdkey_block);
282 else if (tmp->timeout_id > 0) {
283 g_source_remove(tmp->timeout_id);
284 tmp->timeout_id = cond_timeout_id;
285 tmp->holdkey_block = holdkey_block;
288 LOGINFO("[%s] locked by pid %d - process %s\n", "S_NORMAL", pid,
291 if (val & MASK_OFF) {
292 if (data->timeout > 0) {
294 g_timeout_add_full(G_PRIORITY_DEFAULT,
296 (GSourceFunc) del_off_cond,
297 (gpointer) pid, NULL);
299 holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
300 tmp = find_node(S_LCDOFF, pid);
302 add_node(S_LCDOFF, pid, cond_timeout_id, holdkey_block);
303 else if (tmp->timeout_id > 0) {
304 g_source_remove(tmp->timeout_id);
305 tmp->timeout_id = cond_timeout_id;
306 tmp->holdkey_block = holdkey_block;
309 LOGINFO("[%s] locked by pid %d - process %s\n", "S_LCDDIM", pid,
312 if (val & MASK_SLP) {
313 if (data->timeout > 0) {
315 g_timeout_add_full(G_PRIORITY_DEFAULT,
317 (GSourceFunc) del_sleep_cond,
318 (gpointer) pid, NULL);
320 tmp = find_node(S_SLEEP, pid);
322 add_node(S_SLEEP, pid, cond_timeout_id, 0);
323 else if (tmp->timeout_id > 0) {
324 g_source_remove(tmp->timeout_id);
325 tmp->timeout_id = cond_timeout_id;
326 tmp->holdkey_block = 0;
328 sysman_inform_active(pid);
330 LOGINFO("[%s] locked by pid %d - process %s\n", "S_LCDOFF", pid,
334 /* UNLOCK(GRANT) condition processing */
335 val = val >> SHIFT_UNLOCK;
336 if (val & MASK_DIM) {
337 tmp = find_node(S_LCDDIM, pid);
338 del_node(S_LCDDIM, tmp);
339 LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LORMAL",
342 if (val & MASK_OFF) {
343 tmp = find_node(S_LCDOFF, pid);
344 del_node(S_LCDOFF, tmp);
345 LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LCDDIM",
348 if (val & MASK_SLP) {
349 tmp = find_node(S_SLEEP, pid);
350 del_node(S_SLEEP, tmp);
351 sysman_inform_inactive(pid);
352 LOGINFO("[%s] unlocked by pid %d - process %s\n", "S_LCDOFF",
358 reset_timeout(states[cur_state].timeout);
359 LOGINFO("reset timeout\n", "S_LCDOFF", pid, pname);
362 /* guard time for suspend */
363 if (cur_state == S_LCDOFF) {
365 LOGINFO("margin timeout (5 seconds)\n");
369 if (timeout_src_id == 0)
370 states[cur_state].trans(EVENT_TIMEOUT);
375 static int proc_change_state(unsigned int cond)
381 for (i = S_NORMAL; i < S_END; i++) {
382 if ((cond >> (SHIFT_CHANGE_STATE + i)) & 0x1) {
387 LOGINFO("Change State to %s", state_string[next_state]);
389 switch (next_state) {
393 /* state transition */
394 old_state = cur_state;
395 cur_state = next_state;
396 st = &states[cur_state];
400 st->action(st->timeout);
404 LOGINFO("Dangerous requests.");
405 /* at first LCD_OFF and then goto sleep */
406 /* state transition */
407 old_state = cur_state;
408 cur_state = S_LCDOFF;
409 st = &states[cur_state];
413 old_state = cur_state;
415 st = &states[cur_state];
428 /* If some changed, return 1 */
429 int check_processes(enum state_t prohibit_state)
431 Node *t = cond_head[prohibit_state];
436 if (kill(t->pid, 0) == -1) {
438 ("%d process does not exist, delete the REQ - prohibit state %d ",
439 t->pid, prohibit_state);
446 del_node(prohibit_state, tmp);
454 int check_holdkey_block(enum state_t state)
456 Node *t = cond_head[state];
459 LOGINFO("check holdkey block : state of %s", state_string[state]);
462 if(t->holdkey_block == true) {
464 LOGINFO("Hold key blocked by pid(%d)!", t->pid);
473 int delete_condition(enum state_t state)
475 Node *t = cond_head[state];
479 LOGINFO("delete condition : state of %s", state_string[state]);
482 if(t->timeout_id > 0) {
483 g_source_remove(t->timeout_id);
487 LOGINFO("delete node of pid(%d)", tmp->pid);
488 del_node(state, tmp);
494 /* SIGINT, SIGTERM, SIGQUIT signal handler */
495 static void sig_quit(int signo)
497 LOGINFO("received %d signal : stops a main loop", signo);
499 g_main_loop_quit(mainloop);
502 void print_info(int fd)
511 snprintf(buf, sizeof(buf),
512 "\n======================================================================\n");
513 write(fd, buf, strlen(buf));
514 snprintf(buf, sizeof(buf),"Timeout Info: Run[%d] Dim[%d] Off[%d]\n",
515 states[S_NORMAL].timeout,
516 states[S_LCDDIM].timeout, states[S_LCDOFF].timeout);
517 write(fd, buf, strlen(buf));
519 snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n",
520 (trans_condition & MASK_DIM) ? state_string[S_NORMAL] : "-",
521 (trans_condition & MASK_OFF) ? state_string[S_LCDDIM] : "-",
522 (trans_condition & MASK_SLP) ? state_string[S_LCDOFF] : "-");
523 write(fd, buf, strlen(buf));
525 snprintf(buf, sizeof(buf), "Current State: %s\n", state_string[cur_state]);
526 write(fd, buf, strlen(buf));
528 snprintf(buf, sizeof(buf), "Current Lock Conditions: \n");
529 write(fd, buf, strlen(buf));
531 for (s_index = S_NORMAL; s_index < S_END; s_index++) {
533 char pname[PATH_MAX];
535 t = cond_head[s_index];
538 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", t->pid);
539 fd_cmdline = open(buf, O_RDONLY);
540 if (fd_cmdline < 0) {
541 snprintf(pname, PATH_MAX,
542 "does not exist now(may be dead without unlock)");
544 read(fd_cmdline, pname, PATH_MAX);
547 snprintf(buf, sizeof(buf),
548 " %d: [%s] locked by pid %d - process %s\n",
549 i++, state_string[s_index - 1], t->pid, pname);
550 write(fd, buf, strlen(buf));
556 /* SIGHUP signal handler
557 * For debug... print info to syslog
559 static void sig_hup(int signo)
567 fd = open(PM_STATE_LOG_FILE, O_CREAT | O_WRONLY, 0644);
569 snprintf(buf, sizeof(buf), "\npm_state_log now-time : %d (s)\n\n",
571 write(fd, buf, strlen(buf));
573 snprintf(buf, sizeof(buf), "status_flag: %x\n", status_flag);
574 write(fd, buf, strlen(buf));
576 snprintf(buf, sizeof(buf), "received sleep cmd count : %d\n",
578 write(fd, buf, strlen(buf));
584 fd = open("/dev/console", O_WRONLY);
591 /* timeout handler */
592 gboolean timeout_handler(gpointer data)
594 LOGINFO("Time out state %s\n", state_string[cur_state]);
596 if (timeout_src_id != 0) {
597 g_source_remove(timeout_src_id);
601 if ((status_flag & VCALL_FLAG)
602 && (cur_state == S_LCDOFF || cur_state == S_SLEEP)) {
603 status_flag &= ~(VCALL_FLAG);
604 reset_timeout(TELEPHONY_SIGNAL_TIMEOUT);
607 states[cur_state].trans(EVENT_TIMEOUT);
611 static void reset_timeout(int timeout)
613 if (timeout_src_id != 0) {
614 g_source_remove(timeout_src_id);
618 timeout_src_id = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
626 static void sig_usr(int signo)
628 status_flag |= VCALL_FLAG;
631 static void sig_break_block(int signo)
633 LOGINFO("We got signal to break that pending checking in kernel\n");
637 * default transition function
640 * 3. call enter action function
642 static int default_trans(int evt)
644 struct state *st = &states[cur_state];
647 if(cur_state == S_NORMAL && st->timeout == 0) {
648 LOGINFO("LCD always on enabled!");
652 next_state = (enum state_t)trans_table[cur_state][evt];
654 /* check conditions */
655 while (st->check && !st->check(next_state)) {
656 /* There is a condition. */
657 LOGINFO("%s -> %s : check fail", state_string[cur_state],
658 state_string[next_state]);
659 if (!check_processes(next_state)) {
660 /* this is valid condition - the application that sent the condition is running now. */
665 /* state transition */
666 old_state = cur_state;
667 cur_state = next_state;
668 st = &states[cur_state];
672 st->action(st->timeout);
678 /* default enter action function */
679 static int default_action(int timeout)
682 int wakeup_count = -1;
684 char *pkgname = NULL;
687 struct itimerval val;
689 if (cur_state != old_state && cur_state != S_SLEEP)
690 set_setting_pmstate(cur_state);
694 /* normal state : backlight on and restore the previous brightness */
695 if (old_state == S_LCDOFF || old_state == S_SLEEP) {
696 if (pre_suspend_flag == true) {
697 system_post_resume();
698 pre_suspend_flag = false;
700 for (i = 0; i < 14; i++) {
701 vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
702 LOGERR("Idle lock check : %d, vonf : %d", i, lock_state);
707 #ifndef X86 /* Different with ARM FB driver, IA gfx driver is sensitive to the order. */
714 } else if (old_state == S_LCDDIM)
719 if (old_state == S_LCDOFF || old_state == S_SLEEP) {
722 /* lcd dim state : dim the brightness */
727 if (old_state != S_SLEEP && old_state != S_LCDOFF) {
728 /* lcd off state : turn off the backlight */
730 if (pre_suspend_flag == false) {
731 pre_suspend_flag = true;
732 system_pre_suspend();
739 * We can not always be blocked here because of that
740 * in-progress checking in kernel for wakeup count,
741 * if we cannot get the result within some time, then
742 * just give it up and then retry it in the next time,
743 * this method would not break that original expected
744 * 'aggresive suspend' idea, but at the same time make
745 * the system is 'always' responsible to some keypress
746 * actions like power button press.
748 val.it_value.tv_sec = TOLERANCE_SLOT;
749 val.it_value.tv_usec = 0;
750 val.it_interval.tv_sec = val.it_interval.tv_usec = 0;
751 setitimer(ITIMER_REAL, &val, NULL);
753 /* sleep state : set system mode to SUSPEND */
754 if (0 > device_get_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_COUNT, &wakeup_count))
755 LOGERR("wakeup count read error");
757 if (wakeup_count < 0) {
758 LOGINFO("Wakup Event! Can not enter suspend mode.");
762 if (0 > device_set_property(DEVICE_TYPE_POWER, PROP_POWER_WAKEUP_COUNT, wakeup_count)) {
763 LOGERR("wakeup count write error");
770 /* set timer with current state timeout */
771 reset_timeout(timeout);
772 LOGINFO("timout set: %s state %d sec", state_string[cur_state], timeout);
778 LOGINFO("system wakeup!!");
779 system_wakeup_flag = true;
780 heynoti_publish(PM_WAKEUP_NOTI_NAME);
782 if (check_wakeup_src() == EVENT_DEVICE)
783 /* system waked up by devices */
784 states[cur_state].trans(EVENT_DEVICE);
786 /* system waked up by user input */
787 states[cur_state].trans(EVENT_INPUT);
791 heynoti_publish(PM_WAKEUP_NOTI_NAME);
793 states[cur_state].trans(EVENT_DEVICE);
798 * default check function
800 * 0 : can't transit, others : transitable
802 static int default_check(int next)
804 int trans_cond = trans_condition & MASK_BIT;
807 LOGINFO("trans_cond : %x", trans_cond);
809 vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
810 if(lock_state==VCONFKEY_IDLE_LOCK && next != S_SLEEP) {
811 LOGINFO("default_check : LOCK STATE, it's transitable");
817 trans_cond = trans_cond & MASK_DIM;
820 trans_cond = trans_cond & MASK_OFF;
823 trans_cond = trans_cond & MASK_SLP;
825 default: /* S_NORMAL is exceptional */
833 return 1; /* transitable */
836 /* get configurations from setting */
837 static int get_settings()
844 for (i = 0; i < S_END; i++) {
845 switch (states[i].state) {
847 ret = get_run_timeout(&val);
849 ret = get_env("PM_TO_NORMAL", buf, 255);
854 ret = get_dim_timeout(&val);
857 ret = get_off_timeout(&val);
860 /* This state doesn't need to set time out. */
864 if (ret == 0 || val < 0) {
865 states[i].timeout = val;
867 switch (states[i].state) {
869 states[i].timeout = DEFAULT_NORMAL_TIMEOUT;
872 states[i].timeout = DEFAULT_DIM_TIMEOUT;
875 states[i].timeout = DEFAULT_OFF_TIMEOUT;
878 states[i].timeout = 0;
882 LOGINFO("%s state : %d timeout", state_string[i], states[i].timeout);
888 static void default_saving_mode(int onoff)
891 status_flag |= PWRSV_FLAG;
893 status_flag &= ~PWRSV_FLAG;
895 if (cur_state == S_NORMAL)
899 static int poll_callback(int condition, PMMsg *data)
903 if (condition == INPUT_POLL_EVENT) {
904 if (cur_state == S_LCDOFF || cur_state == S_SLEEP)
905 LOGINFO("Power key input");
908 states[cur_state].trans(EVENT_INPUT);
911 } else if (condition == PM_CONTROL_EVENT) {
912 LOGINFO("process pid(%d) pm_control condition : %x ", data->pid,
915 if (data->cond & MASK_BIT
916 || (data->cond >> SHIFT_UNLOCK) & MASK_BIT)
917 proc_condition(data);
919 if (data->cond & CHANGE_STATE_BIT) {
921 LOGINFO("Change state by pid(%d) request.", data->pid);
922 proc_change_state(data->cond);
929 static int update_setting(int key_idx, int val)
933 int dim_timeout = -1;
934 int run_timeout = -1;
935 int power_saving_stat = -1;
936 int power_saving_display_stat = -1;
939 case SETTING_TO_NORMAL:
940 ret = get_dim_timeout(&dim_timeout);
941 if(ret < 0 || dim_timeout < 0) {
942 LOGERR("Can not get dim timeout. set default 5 seconds");
946 LOGERR("LCD timeout is wrong, set default 15 seconds");
950 states[S_NORMAL].timeout = 0;
951 } else if(val > dim_timeout) {
952 states[S_NORMAL].timeout = val - dim_timeout;
954 states[S_NORMAL].timeout = 1;
956 states[cur_state].trans(EVENT_INPUT);
958 case SETTING_LOW_BATT:
959 if (val < VCONFKEY_SYSMAN_BAT_WARNING_LOW) {
960 if (!(status_flag & CHRGR_FLAG))
961 power_saving_func(true);
962 status_flag |= LOWBT_FLAG;
964 if (status_flag & PWRSV_FLAG)
965 power_saving_func(false);
966 status_flag &= ~LOWBT_FLAG;
967 status_flag &= ~BRTCH_FLAG;
968 vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
972 case SETTING_CHARGING:
974 if (status_flag & LOWBT_FLAG) {
975 power_saving_func(false);
976 status_flag &= ~LOWBT_FLAG;
978 status_flag |= CHRGR_FLAG;
980 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
981 vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
982 if(bat_state < VCONFKEY_SYSMAN_BAT_NORMAL) {
983 power_saving_func(true);
984 status_flag |= LOWBT_FLAG;
986 status_flag &= ~CHRGR_FLAG;
989 case SETTING_BRT_LEVEL:
990 if (status_flag & PWRSV_FLAG) {
991 status_flag |= BRTCH_FLAG;
992 vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
994 LOGINFO("brightness changed in low battery, escape dim state");
996 set_default_brt(val);
997 snprintf(buf, sizeof(buf), "%s %d", SET_BRIGHTNESS_IN_BOOTLOADER, val);
998 LOGINFO("Brightness set in bl : %d",val);
1001 case SETTING_LOCK_SCREEN:
1002 if (val == VCONFKEY_IDLE_LOCK) {
1003 states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
1004 LOGERR("LCD NORMAL timeout is set by %d seconds for lock screen", LOCK_SCREEN_TIMEOUT);
1006 get_run_timeout(&run_timeout);
1007 if(run_timeout < 0) {
1008 LOGERR("Can not get run timeout. set default 15 seconds(includes dim 5 seconds)");
1011 states[S_NORMAL].timeout = run_timeout;
1012 LOGINFO("LCD NORMAL timeout is set by %d seconds because phone is unlocked", run_timeout);
1014 if (cur_state == S_NORMAL) {
1015 states[cur_state].trans(EVENT_INPUT);
1018 case SETTING_POWER_SAVING:
1020 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_CUSTMODE_DISPLAY, &power_saving_display_stat);
1021 if (power_saving_display_stat != 1)
1022 power_saving_display_stat = 0;
1023 device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_FRAME_RATE, power_saving_display_stat);
1024 backlight_restore();
1026 case SETTING_POWER_SAVING_DISPLAY:
1027 vconf_get_bool(VCONFKEY_SETAPPL_PWRSV_SYSMODE_STATUS, &power_saving_stat);
1028 if (power_saving_stat == 1) {
1030 power_saving_display_stat = 1;
1032 power_saving_display_stat = 0;
1033 device_set_property(DEVICE_TYPE_DISPLAY, PROP_DISPLAY_FRAME_RATE, power_saving_display_stat);
1034 backlight_restore();
1043 static void check_seed_status(void)
1047 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
1050 int lock_state = -1;
1052 /* Charging check */
1053 if ((get_charging_status(&tmp) == 0) && (tmp > 0)) {
1054 status_flag |= CHRGR_FLAG;
1057 ret = get_setting_brightness(&tmp);
1058 if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
1059 LOGINFO("fail to read vconf value for brightness");
1060 brt = PM_DEFAULT_BRIGHTNESS;
1061 if(tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)
1062 vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
1065 LOGINFO("Set brightness from Setting App. %d", tmp);
1066 set_default_brt(tmp);
1068 vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
1069 if (bat_state < VCONFKEY_SYSMAN_BAT_NORMAL) {
1070 if (!(status_flag & CHRGR_FLAG)) {
1071 power_saving_func(true);
1072 status_flag |= LOWBT_FLAG;
1075 backlight_restore();
1077 /* USB connection check
1078 * If connected, add sleep prohibit condition */
1079 if ((get_usb_status(&tmp) == 0) && (tmp > 0)) {
1080 tmp = readpid(USB_CON_PIDFILE);
1082 add_node(S_SLEEP, tmp, -1, 0);
1086 /* lock screen check */
1087 ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1088 if(lock_state == VCONFKEY_IDLE_LOCK) {
1089 states[S_NORMAL].timeout = LOCK_SCREEN_TIMEOUT;
1090 LOGERR("LCD NORMAL timeout is set by %d seconds for lock screen", LOCK_SCREEN_TIMEOUT);
1104 static char *errMSG[INIT_END] = {
1105 [INIT_SETTING] = "setting init error",
1106 [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
1107 [INIT_POLL] = "input devices poll init error",
1108 [INIT_FIFO] = "FIFO poll init error",
1111 /* logging indev_list for debug */
1118 total=g_list_length(indev_list);
1119 LOGINFO("***** total list : %d *****",total);
1120 for(i=0;i<total;i++) {
1121 tmp=(indev*)(g_list_nth(indev_list, i)->data);
1122 LOGINFO("* %d | path:%s, gsource:%d, gfd:%d", i, tmp->dev_path, tmp->dev_src, tmp->dev_fd);
1123 if(i==total-1 && g_list_nth(indev_list, i)->next==NULL)
1126 LOGINFO("***************************\n");
1129 static GList *find_glist(GList *glist, char *path)
1135 total=g_list_length(indev_list);
1136 for(i=0;i<total;i++) {
1137 tmp=(indev*)(g_list_nth(indev_list, i)->data);
1138 if(!strcmp(tmp->dev_path, path)){
1139 LOGINFO("nth : %d, path:%s, gsource:%d, gfd:%d", i, tmp->dev_path, tmp->dev_src, tmp->dev_fd);
1140 return g_list_nth(indev_list, i);
1146 static void input_cb(void* data)
1149 char input_act[NAME_MAX], input_path[MAX_INPUT];
1150 char args[NAME_MAX + MAX_INPUT];
1152 GList *glist = NULL;
1154 fp = fopen((char *) data, "r");
1156 LOGERR("input file open fail");
1160 while (fgets(args, NAME_MAX + MAX_INPUT, fp) != NULL){
1161 if( args[strlen(args)-1] != '\n'){
1162 LOGERR("input file must be terminated with new line character\n");
1165 args[strlen(args) - 1] = '\0';
1166 for(i = 0; i< NAME_MAX + MAX_INPUT; i++){
1168 if( i >= NAME_MAX ){
1169 LOGERR("bsfile name is over the name_max(255)\n");
1172 strncpy(input_act, args, i < NAME_MAX ? i : NAME_MAX);
1174 strncpy(input_path, args + i + 1, MAX_INPUT);
1175 input_path[MAX_INPUT - 1] = '\0';
1177 if( !strcmp("add", input_act) ){
1178 LOGINFO("add input path:%s",input_path);
1180 ret=init_pm_poll_input(poll_callback, input_path);
1182 } else if ( !strcmp("remove", input_act) ){
1183 glist=find_glist(indev_list, input_path);
1185 LOGINFO("remove input dev");
1186 g_source_remove_poll(((indev*)(glist->data))->dev_src, ((indev*)(glist->data))->dev_fd);
1187 g_source_destroy(((indev*)(glist->data))->dev_src);
1188 close(((indev*)(glist->data))->dev_fd->fd);
1189 g_free(((indev*)(glist->data))->dev_fd);
1190 free(((indev*)(glist->data))->dev_path);
1191 indev_list=g_list_remove(indev_list, glist->data);
1207 fp = fopen((char *) data, "w");
1217 static int set_noti(int *noti_fd)
1222 fd = heynoti_init();
1224 LOGERR("heynoti_init error");
1228 if (heynoti_subscribe(fd, PM_EVENT_NOTI_NAME, input_cb, PM_EVENT_NOTI_PATH) < 0) {
1229 LOGERR("input file change noti add failed(%s). %s", buf, strerror(errno));
1232 LOGERR("input file change noti add ok");
1235 if (heynoti_attach_handler(fd) < 0) {
1236 LOGERR("heynoti_attach_handler error");
1244 static int unset_noti(int noti_fd)
1247 LOGINFO("set noti already failed. nothing to do in unset");
1251 if (heynoti_unsubscribe(noti_fd, PM_EVENT_NOTI_NAME, input_cb) < 0 || heynoti_detach_handler(noti_fd) < 0) {
1252 LOGERR("heynoti unsubsribe or detach error");
1259 * Power manager Main loop
1262 * @param[in] flags If the first bit of this is set, start managing without Start notification.
1263 * If the second bit of ths is set, use unified device manager functions.
1265 void start_main(unsigned int flags)
1269 LOGINFO("Start power manager daemon");
1271 signal(SIGINT, sig_quit);
1272 signal(SIGTERM, sig_quit);
1273 signal(SIGQUIT, sig_quit);
1274 signal(SIGHUP, sig_hup);
1275 signal(SIGCHLD, SIG_IGN);
1276 signal(SIGUSR1, sig_usr);
1277 signal(SIGALRM, sig_break_block);
1279 mainloop = g_main_loop_new(NULL, FALSE);
1280 power_saving_func = default_saving_mode;
1282 /* noti init for new input device like bt mouse */
1287 for (i = INIT_SETTING; i < INIT_END; i++) {
1290 ret = init_setting(update_setting);
1292 case INIT_INTERFACE:
1294 ret = init_sysfs(flags);
1297 LOGINFO("poll init");
1298 ret = init_pm_poll(poll_callback);
1307 if (i == INIT_END) {
1308 check_seed_status();
1310 if (pm_init_extention != NULL)
1311 pm_init_extention(NULL);
1313 if (flags & WITHOUT_STARTNOTI) { /* start without noti */
1314 LOGINFO("Start Power managing without noti");
1315 cur_state = S_NORMAL;
1316 set_setting_pmstate(cur_state);
1317 reset_timeout(states[S_NORMAL].timeout);
1319 if (start_battinfo_gathering(BATTERY_POLLING_PERIOD) < 0)
1320 LOGERR("Start Battery time info failed!");
1322 g_main_loop_run(mainloop);
1323 g_main_loop_unref(mainloop);
1326 end_battinfo_gathering();
1327 for (i = i - 1; i >= INIT_SETTING; i--) {
1332 case INIT_INTERFACE:
1336 unset_noti(noti_fd);
1342 if (pm_exit_extention != NULL)
1343 pm_exit_extention();
1345 LOGINFO("Terminate power manager daemon");