4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * @brief Power manager main loop.
24 * This file includes Main loop, the FSM, signal processing.
35 #include <sys/types.h>
38 #include <vconf-keys.h>
43 #include "device-node.h"
44 #include "lock-detector.h"
45 #include "display-ops.h"
46 #include "core/devices.h"
47 #include "core/device-notifier.h"
48 #include "core/device-handler.h"
49 #include "core/udev.h"
50 #include "core/list.h"
51 #include "core/common.h"
52 #include "core/edbus-handler.h"
53 #include "core/config-parser.h"
54 #include "dd-display.h"
57 #define PM_STATE_LOG_FILE "/var/log/pm_state.log"
58 #define DISPLAY_CONF_FILE "/etc/deviced/display.conf"
61 * @addtogroup POWER_MANAGER
65 #define SET_BRIGHTNESS_IN_BOOTLOADER "/usr/bin/save_blenv SLP_LCD_BRIGHT"
66 #define LOCK_SCREEN_INPUT_TIMEOUT 10000
67 #define LOCK_SCREEN_CONTROL_TIMEOUT 5000
68 #define DD_LCDOFF_INPUT_TIMEOUT 3000
69 #define ALWAYS_ON_TIMEOUT 3600000
71 #define GESTURE_STR "gesture"
72 #define POWER_KEY_STR "powerkey"
73 #define TOUCH_STR "touch"
74 #define EVENT_STR "event"
75 #define UNKNOWN_STR "unknown"
77 unsigned int pm_status_flag;
79 static void (*power_saving_func) (int onoff);
80 static enum device_ops_status status = DEVICE_OPS_STATUS_UNINIT;
84 Ecore_Timer *timeout_src_id;
85 static int pre_suspend_flag = false;
86 int system_wakeup_flag = false;
87 static unsigned int custom_normal_timeout = 0;
88 static unsigned int custom_dim_timeout = 0;
89 static int custom_holdkey_block = false;
90 static int custom_change_pid = -1;
91 static char *custom_change_name;
92 static int standby_mode = false;
93 static int standby_state = false;
94 static Eina_List *standby_mode_list = NULL;
95 static int (*basic_action) (int);
96 static bool hallic_open = true;
97 static Ecore_Timer *lock_timeout_id;
98 static int lock_screen_timeout = LOCK_SCREEN_INPUT_TIMEOUT;
99 static int hdmi_state = 0;
100 static int tts_state = false;
101 static struct timeval lcdon_tv;
102 static int lcd_paneloff_mode = false;
103 static int stay_touchscreen_off = false;
104 static Eina_List *lcdon_ops = NULL;
105 static bool lcdon_broadcast = false;
107 /* default transition, action fuctions */
108 static int default_trans(int evt);
109 static int default_action(int timeout);
110 static int default_check(int next);
112 struct state states[S_END] = {
113 {S_START, default_trans, default_action, default_check,},
114 {S_NORMAL, default_trans, default_action, default_check,},
115 {S_LCDDIM, default_trans, default_action, default_check,},
116 {S_LCDOFF, default_trans, default_action, default_check,},
117 {S_SLEEP, default_trans, default_action, default_check,}
120 static const char state_string[5][10] =
121 { "S_START", "S_NORMAL", "S_LCDDIM", "S_LCDOFF", "S_SLEEP" };
123 static int trans_table[S_END][EVENT_END] = {
124 /* Timeout , Input */
125 {S_START, S_START}, /* S_START */
126 {S_LCDDIM, S_NORMAL}, /* S_NORMAL */
127 {S_LCDOFF, S_NORMAL}, /* S_LCDDIM */
128 {S_SLEEP, S_NORMAL}, /* S_LCDOFF */
129 {S_LCDOFF, S_NORMAL}, /* S_SLEEP */
132 #define SHIFT_UNLOCK 4
133 #define MASK_RESET_TIMEOUT 0x8 /* 1000 */
134 #define MASK_MARGIN_TIMEOUT (0x1 << 8)
135 #define SHIFT_CHANGE_STATE 7
136 #define CHANGE_STATE_BIT 0xF00 /* 1111 0000 0000 */
137 #define SHIFT_LOCK_FLAG 16
138 #define SHIFT_CHANGE_TIMEOUT 20
139 #define CUSTOM_TIMEOUT_BIT 0x1
140 #define CUSTOM_HOLDKEY_BIT 0x2
141 #define HOLD_KEY_BLOCK_BIT 0x1
142 #define STANDBY_MODE_BIT 0x2
143 #define TIMEOUT_NONE (-1)
145 #define S_COVER_TIMEOUT 8000
146 #define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_LOCK_FLAG) & HOLD_KEY_BLOCK_BIT)
147 #define GET_STANDBY_MODE_STATE(x) ((x >> SHIFT_LOCK_FLAG) & STANDBY_MODE_BIT)
148 #define MASK32 0xffffffff
149 #define BOOTING_DONE_WATING_TIME 60000 /* 1 minute */
150 #define LOCK_TIME_WARNING 60 /* 60 seconds */
151 #define ALPM_CLOCK_WAITING_TIME 3000 /* 3 seconds */
153 #define ACTIVE_ACT "active"
154 #define INACTIVE_ACT "inactive"
155 #define SIGNAL_LCD_ON "LCDOn"
156 #define SIGNAL_LCD_OFF "LCDOff"
158 #define LOCK_SCREEN_WATING_TIME 0.3 /* 0.3 second */
159 #define LONG_PRESS_INTERVAL 2 /* 2 seconds */
160 #define SAMPLING_INTERVAL 1 /* 1 sec */
161 #define BRIGHTNESS_CHANGE_STEP 10
162 #define HBM_LUX_THRESHOLD 32768 /* lux */
163 #define LCD_ALWAYS_ON 0
164 #define ACCEL_SENSOR_ON 1
165 #define CONTINUOUS_SAMPLING 1
166 #define LCDOFF_TIMEOUT 500 /* milli second */
168 #define DIFF_TIMEVAL_MS(a, b) \
169 (((a.tv_sec * 1000000 + a.tv_usec) - \
170 (b.tv_sec * 1000000 + b.tv_usec)) \
173 struct display_config display_conf = {
174 .lock_wait_time = LOCK_SCREEN_WATING_TIME,
175 .longpress_interval = LONG_PRESS_INTERVAL,
176 .lightsensor_interval = SAMPLING_INTERVAL,
177 .lcdoff_timeout = LCDOFF_TIMEOUT,
178 .brightness_change_step = BRIGHTNESS_CHANGE_STEP,
179 .hbm_lux_threshold = HBM_LUX_THRESHOLD,
180 .lcd_always_on = LCD_ALWAYS_ON,
181 .framerate_app = {0,0,0,0},
182 .control_display = 0,
183 .powerkey_doublepress = 0,
185 .accel_sensor_on = ACCEL_SENSOR_ON,
186 .continuous_sampling = CONTINUOUS_SAMPLING,
189 struct display_function_info display_info = {
190 .update_auto_brightness = NULL,
191 .set_autobrightness_min = NULL,
192 .reset_autobrightness_min = NULL,
193 .face_detection = NULL,
196 typedef struct _pm_lock_node {
198 Ecore_Timer *timeout_id;
201 struct _pm_lock_node *next;
204 static PmLockNode *cond_head[S_END];
206 static void set_process_active(bool flag, pid_t pid)
212 if (pid >= INTERNAL_LOCK_BASE)
215 sprintf(str, "%d", (int)pid);
217 arr[0] = (flag ? ACTIVE_ACT : INACTIVE_ACT);
220 /* Send dbug to resourced */
221 ret = broadcast_edbus_signal(RESOURCED_PATH_PROCESS,
222 RESOURCED_INTERFACE_PROCESS, RESOURCED_METHOD_ACTIVE, "si", arr);
224 _E("Fail to send dbus signal to resourced!!");
227 bool check_lock_state(int state)
229 if (cond_head[state] != NULL)
235 int get_standby_state(void)
237 return standby_state;
240 static inline void set_standby_state(bool state)
242 if (standby_state != state)
243 standby_state = state;
246 void broadcast_lcd_on(enum device_flags flags)
250 if (flags & LCD_ON_BY_GESTURE)
251 arr[0] = GESTURE_STR;
252 else if (flags & LCD_ON_BY_POWER_KEY)
253 arr[0] = POWER_KEY_STR;
254 else if (flags & LCD_ON_BY_EVENT)
256 else if (flags & LCD_ON_BY_TOUCH)
259 arr[0] = UNKNOWN_STR;
261 broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
262 SIGNAL_LCD_ON, "s", arr);
265 void broadcast_lcd_off(void)
267 broadcast_edbus_signal(DEVICED_PATH_DISPLAY, DEVICED_INTERFACE_DISPLAY,
268 SIGNAL_LCD_OFF, NULL, NULL);
271 void tts_lcd_off(void)
275 ret = dbus_method_sync(POPUP_BUS_NAME, POPUP_PATH_SERVANT,
276 POPUP_IFACE_SERVANT, POPUP_METHOD_SCREENOFF_TTS, NULL, NULL);
279 _E("Failed to tts(%d)", ret);
282 static unsigned long get_lcd_on_flags(void)
284 unsigned long flags = NORMAL_MODE;
286 if (lcd_paneloff_mode)
287 flags |= LCD_PANEL_OFF_MODE;
289 if (stay_touchscreen_off)
290 flags |= TOUCH_SCREEN_OFF_MODE;
292 if (get_ambient_mode != NULL &&
293 get_ambient_mode() == true) {
294 flags |= AMBIENT_MODE;
295 flags |= LCD_PHASED_TRANSIT_MODE;
300 void lcd_on_procedure(int state, enum device_flags flag)
303 const struct device_ops *ops = NULL;
304 unsigned long flags = get_lcd_on_flags();
307 /* send LCDOn dbus signal */
308 if (!lcdon_broadcast) {
309 broadcast_lcd_on(flags);
310 lcdon_broadcast = true;
313 if (flags & AMBIENT_MODE &&
314 check_alpm_lcdon_ready != NULL)
315 check_alpm_lcdon_ready();
317 /* AMOLED Low Power Mode off */
318 if (flags & AMBIENT_MODE) {
319 pm_unlock_internal(INTERNAL_LOCK_ALPM, LCD_OFF,
322 if (alpm_get_state != NULL &&
323 alpm_get_state() == false &&
324 backlight_ops.get_lcd_power() == PM_LCD_POWER_ON)
326 if (alpm_set_state != NULL &&
327 alpm_set_state(false) < 0)
328 _E("Failed to ALPM off");
331 if (!(flags & LCD_PHASED_TRANSIT_MODE)) {
332 /* Update brightness level */
333 if (state == LCD_DIM)
335 else if (state == LCD_NORMAL)
336 backlight_ops.update();
339 if (flags & AMBIENT_MODE) {
340 if (state == LCD_DIM)
341 set_setting_pmstate(S_LCDDIM);
342 else if (state == LCD_NORMAL)
343 set_setting_pmstate(S_NORMAL);
346 EINA_LIST_FOREACH(lcdon_ops, l, ops)
349 if (CHECK_OPS(keyfilter_ops, backlight_enable))
350 keyfilter_ops->backlight_enable(true);
353 static inline unsigned long get_lcd_off_flags(void)
355 unsigned long flags = NORMAL_MODE;
357 if (get_ambient_mode != NULL &&
358 get_ambient_mode() == true)
359 flags |= AMBIENT_MODE;
361 if (flags & AMBIENT_MODE)
362 flags |= LCD_PHASED_TRANSIT_MODE;
367 inline void lcd_off_procedure(void)
370 const struct device_ops *ops = NULL;
371 unsigned long flags = get_lcd_off_flags();
374 _D("standby mode! lcd off logic is skipped");
377 /* AMOLED Low Power Mode on */
378 if (flags & AMBIENT_MODE) {
379 if (alpm_get_state != NULL &&
380 alpm_get_state() == true)
382 if (alpm_set_state != NULL &&
383 alpm_set_state(true) < 0)
384 _E("Failed to ALPM on!");
386 pm_lock_internal(INTERNAL_LOCK_ALPM, LCD_OFF,
387 STAY_CUR_STATE, ALPM_CLOCK_WAITING_TIME);
390 if (lcdon_broadcast) {
392 lcdon_broadcast = false;
394 if (CHECK_OPS(keyfilter_ops, backlight_enable))
395 keyfilter_ops->backlight_enable(false);
397 if (flags & AMBIENT_MODE)
398 set_setting_pmstate(S_LCDOFF);
400 EINA_LIST_REVERSE_FOREACH(lcdon_ops, l, ops)
407 void set_stay_touchscreen_off(int val)
409 _D("stay touch screen off : %d", val);
410 stay_touchscreen_off = val;
412 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
413 set_setting_pmstate(LCD_NORMAL);
416 void set_lcd_paneloff_mode(int val)
418 _D("lcd paneloff mode : %d", val);
419 lcd_paneloff_mode = val;
421 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
422 set_setting_pmstate(LCD_NORMAL);
425 int low_battery_state(int val)
428 case VCONFKEY_SYSMAN_BAT_POWER_OFF:
429 case VCONFKEY_SYSMAN_BAT_CRITICAL_LOW:
430 case VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF:
436 int get_hallic_open(void)
441 static int refresh_app_cond()
445 if (cond_head[S_LCDDIM] != NULL)
446 trans_condition = trans_condition | MASK_DIM;
447 if (cond_head[S_LCDOFF] != NULL)
448 trans_condition = trans_condition | MASK_OFF;
449 if (cond_head[S_SLEEP] != NULL)
450 trans_condition = trans_condition | MASK_SLP;
455 static PmLockNode *find_node(enum state_t s_index, pid_t pid)
457 PmLockNode *t = cond_head[s_index];
467 static PmLockNode *add_node(enum state_t s_index, pid_t pid, Ecore_Timer *timeout_id,
473 n = (PmLockNode *) malloc(sizeof(PmLockNode));
475 _E("Not enough memory, add cond. fail");
481 n->timeout_id = timeout_id;
483 n->holdkey_block = holdkey_block;
484 n->next = cond_head[s_index];
485 cond_head[s_index] = n;
491 static int del_node(enum state_t s_index, PmLockNode *n)
499 t = cond_head[s_index];
504 prev->next = t->next;
506 cond_head[s_index] = cond_head[s_index]->next;
509 ecore_timer_del(t->timeout_id);
520 static void print_node(int next)
527 if (next <= S_START || next >= S_END)
533 diff = difftime(now, n->time);
534 ctime_r(&n->time, buf);
536 if (diff > LOCK_TIME_WARNING)
537 _W("over %.0f s, pid: %5d, lock time: %s", diff, n->pid, buf);
539 _I("pid: %5d, lock time: %s", n->pid, buf);
545 void get_pname(pid_t pid, char *pname)
550 if (pid >= INTERNAL_LOCK_BASE)
551 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", getpid());
553 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
555 cmdline = open(buf, O_RDONLY);
558 _E("%d does not exist now(may be dead without unlock)", pid);
562 r = read(cmdline, pname, PATH_MAX);
563 if ((r >= 0) && (r < PATH_MAX))
571 static Eina_Bool del_dim_cond(void *data)
573 PmLockNode *tmp = NULL;
574 char pname[PATH_MAX];
575 pid_t pid = (pid_t)data;
577 _I("delete prohibit dim condition by timeout (%d)", pid);
579 tmp = find_node(S_LCDDIM, pid);
580 del_node(S_LCDDIM, tmp);
581 get_pname(pid, pname);
582 set_unlock_time(pname, S_NORMAL);
585 states[pm_cur_state].trans(EVENT_TIMEOUT);
590 static Eina_Bool del_off_cond(void *data)
592 PmLockNode *tmp = NULL;
593 char pname[PATH_MAX];
594 pid_t pid = (pid_t)data;
596 _I("delete prohibit off condition by timeout (%d)", pid);
598 tmp = find_node(S_LCDOFF, pid);
599 del_node(S_LCDOFF, tmp);
600 get_pname(pid, pname);
601 set_unlock_time(pname, S_LCDDIM);
604 states[pm_cur_state].trans(EVENT_TIMEOUT);
609 static Eina_Bool del_sleep_cond(void *data)
611 PmLockNode *tmp = NULL;
612 char pname[PATH_MAX];
613 pid_t pid = (pid_t)data;
615 _I("delete prohibit sleep condition by timeout (%d)", pid);
617 if (pid == INTERNAL_LOCK_ALPM &&
618 check_alpm_invalid_state != NULL)
619 check_alpm_invalid_state();
621 tmp = find_node(S_SLEEP, pid);
622 del_node(S_SLEEP, tmp);
623 get_pname(pid, pname);
624 set_unlock_time(pname, S_LCDOFF);
627 states[pm_cur_state].trans(EVENT_TIMEOUT);
629 set_process_active(EINA_FALSE, (pid_t)data);
634 /* timeout handler */
635 Eina_Bool timeout_handler(void *data)
637 _I("Time out state %s\n", state_string[pm_cur_state]);
639 if (timeout_src_id) {
640 ecore_timer_del(timeout_src_id);
641 timeout_src_id = NULL;
644 states[pm_cur_state].trans(EVENT_TIMEOUT);
648 void reset_timeout(int timeout)
650 if (timeout_src_id != 0) {
651 ecore_timer_del(timeout_src_id);
652 timeout_src_id = NULL;
655 timeout_src_id = ecore_timer_add(MSEC_TO_SEC((double)timeout),
656 (Ecore_Task_Cb)timeout_handler, NULL);
657 else if (timeout == 0)
658 states[pm_cur_state].trans(EVENT_TIMEOUT);
661 /* get configurations from setting */
662 static int get_lcd_timeout_from_settings(void)
669 for (i = 0; i < S_END; i++) {
670 switch (states[i].state) {
672 ret = get_run_timeout(&val);
674 buf = getenv("PM_TO_NORMAL");
675 val = (buf ? atoi(buf) : DEFAULT_NORMAL_TIMEOUT);
679 get_dim_timeout(&val);
682 val = display_conf.lcdoff_timeout;
685 /* This state doesn't need to set time out. */
690 states[i].timeout = val;
692 _I("%s state : %d ms timeout", state_string[i],
699 static void update_display_time(void)
701 int ret, run_timeout, val;
703 /* first priority : s cover */
705 states[S_NORMAL].timeout = S_COVER_TIMEOUT;
706 _I("S cover closed : timeout is set by normal(%d ms)",
711 /* second priority : custom timeout */
712 if (custom_normal_timeout > 0) {
713 states[S_NORMAL].timeout = custom_normal_timeout;
714 states[S_LCDDIM].timeout = custom_dim_timeout;
715 _I("CUSTOM : timeout is set by normal(%d ms), dim(%d ms)",
716 custom_normal_timeout, custom_dim_timeout);
720 /* third priority : lock state */
721 if ((get_lock_screen_state() == VCONFKEY_IDLE_LOCK) &&
722 !get_lock_screen_bg_state()) {
723 if (pm_status_flag & SMAST_FLAG) {
724 /* smart stay is on, timeout is always 5 seconds. */
725 states[S_NORMAL].timeout = LOCK_SCREEN_CONTROL_TIMEOUT;
726 _I("LOCK : timeout is set, smart stay timeout(%d ms)",
727 LOCK_SCREEN_CONTROL_TIMEOUT);
729 /* timeout is different according to key or event. */
730 states[S_NORMAL].timeout = lock_screen_timeout;
731 _I("LOCK : timeout is set by normal(%d ms)",
732 lock_screen_timeout);
737 /* default setting */
738 ret = get_run_timeout(&run_timeout);
739 if (ret < 0 || run_timeout < 0) {
740 _E("Can not get run timeout. set default %d ms",
741 DEFAULT_NORMAL_TIMEOUT);
742 run_timeout = DEFAULT_NORMAL_TIMEOUT;
746 * if the run_timeout is zero, it regards AlwaysOn state
748 if (run_timeout == 0) {
749 trans_table[S_NORMAL][EVENT_TIMEOUT] = S_NORMAL;
750 run_timeout = ALWAYS_ON_TIMEOUT;
753 trans_table[S_NORMAL][EVENT_TIMEOUT] = S_LCDDIM;
755 states[S_NORMAL].timeout = run_timeout;
757 get_dim_timeout(&val);
758 states[S_LCDDIM].timeout = val;
760 _I("Normal: NORMAL timeout is set by %d ms", states[S_NORMAL].timeout);
761 _I("Normal: DIM timeout is set by %d ms", states[S_LCDDIM].timeout);
764 static void update_display_locktime(int time)
766 lock_screen_timeout = time;
767 update_display_time();
771 void set_dim_state(bool on)
773 _I("dim state is %d", on);
774 update_display_time();
775 states[pm_cur_state].trans(EVENT_INPUT);
779 void lcd_on_direct(enum device_flags flags)
783 if (power_ops.get_power_lock_support()
784 && pm_cur_state == S_SLEEP)
785 power_ops.power_lock();
787 if (pre_suspend_flag == true) {
788 power_ops.post_resume();
789 pre_suspend_flag = false;
792 _D("lcd is on directly");
793 gettimeofday(&lcdon_tv, NULL);
794 if (hbm_check_timeout != NULL)
796 lcd_on_procedure(LCD_NORMAL, flags);
797 reset_timeout(DD_LCDOFF_INPUT_TIMEOUT);
799 ret = vconf_get_int(VCONFKEY_CALL_STATE, &call_state);
800 if ((ret >= 0 && call_state != VCONFKEY_CALL_OFF) ||
801 (get_lock_screen_state() == VCONFKEY_IDLE_LOCK)) {
802 _D("LOCK state, lcd is on directly");
803 lcd_on_procedure(LCD_NORMAL, flags);
805 reset_timeout(display_conf.lcdoff_timeout);
807 update_display_locktime(LOCK_SCREEN_INPUT_TIMEOUT);
810 static inline bool check_lcd_on(void)
812 if (backlight_ops.get_lcd_power() != PM_LCD_POWER_ON)
815 if (alpm_get_state != NULL && alpm_get_state() == true)
821 int custom_lcdon(int timeout)
828 if (check_lcd_on() == true)
829 lcd_on_direct(LCD_ON_BY_GESTURE);
831 _I("custom lcd on %d ms", timeout);
832 if (set_custom_lcdon_timeout(timeout) == true)
833 update_display_time();
835 /* state transition */
836 pm_old_state = pm_cur_state;
837 pm_cur_state = S_NORMAL;
838 st = &states[pm_cur_state];
842 st->action(st->timeout);
848 static int proc_change_state(unsigned int cond, pid_t pid)
853 char pname[PATH_MAX];
855 for (i = S_NORMAL; i < S_END; i++) {
856 if ((cond >> (SHIFT_CHANGE_STATE + i)) & 0x1) {
862 get_pname(pid, pname);
864 _I("Change State to %s (%d)", state_string[next_state], pid);
866 if (next_state == S_NORMAL) {
867 if (check_lcd_on() == true)
868 lcd_on_direct(LCD_ON_BY_EVENT);
869 } else if (next_state == S_LCDOFF) {
870 if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF)
874 if (next_state == S_LCDOFF)
875 if (set_custom_lcdon_timeout(0) == true)
876 update_display_time();
878 switch (next_state) {
880 update_display_locktime(LOCK_SCREEN_CONTROL_TIMEOUT);
885 /* state transition */
886 pm_old_state = pm_cur_state;
887 pm_cur_state = next_state;
888 st = &states[pm_cur_state];
890 /* pm state is updated to dim because of standby mode */
891 if (standby_mode && (pm_cur_state == S_LCDOFF))
892 set_setting_pmstate(S_LCDDIM);
896 st->action(st->timeout);
900 _I("Dangerous requests.");
901 /* at first LCD_OFF and then goto sleep */
902 /* state transition */
903 pm_old_state = pm_cur_state;
904 pm_cur_state = S_LCDOFF;
905 st = &states[pm_cur_state];
907 st->action(TIMEOUT_NONE);
909 delete_condition(S_SLEEP);
910 pm_old_state = pm_cur_state;
911 pm_cur_state = S_SLEEP;
912 st = &states[pm_cur_state];
914 st->action(TIMEOUT_NONE);
925 static int standby_action(int timeout)
927 const struct device_ops *ops = NULL;
929 if (backlight_ops.standby(false) < 0) {
930 _E("Fail to start standby mode!");
933 if (CHECK_OPS(keyfilter_ops, backlight_enable))
934 keyfilter_ops->backlight_enable(false);
936 ops = find_device("touchkey");
937 if (!check_default(ops))
938 ops->stop(NORMAL_MODE);
940 ops = find_device("touchscreen");
941 if (!check_default(ops))
942 ops->stop(NORMAL_MODE);
944 set_standby_state(true);
946 _I("standby mode (only LCD OFF, But phone is working normal)");
947 reset_timeout(timeout);
952 static void set_standby_mode(pid_t pid, int enable)
955 Eina_List *l_next = NULL;
959 EINA_LIST_FOREACH(standby_mode_list, l, data)
960 if (pid == (int) data) {
961 _E("%d already acquired standby mode", pid);
964 EINA_LIST_APPEND(standby_mode_list, (void *)pid);
965 _I("%d acquire standby mode", pid);
969 basic_action = states[S_LCDOFF].action;
970 states[S_LCDOFF].action = standby_action;
971 trans_table[S_LCDOFF][EVENT_TIMEOUT] = S_LCDOFF;
972 _I("Standby mode is enabled!");
976 EINA_LIST_FOREACH_SAFE(standby_mode_list, l, l_next, data)
977 if (pid == (int) data) {
978 standby_mode_list = eina_list_remove_list(
979 standby_mode_list, l);
980 _I("%d release standby mode", pid);
982 if (standby_mode_list != NULL)
984 set_standby_state(false);
985 standby_mode = false;
986 if (basic_action != NULL) {
987 states[S_LCDOFF].action = basic_action;
989 trans_table[S_LCDOFF][EVENT_TIMEOUT] = S_SLEEP;
990 proc_change_state(S_NORMAL << (SHIFT_CHANGE_STATE + S_NORMAL),
992 _I("Standby mode is disabled!");
996 /* update transition condition for application requrements */
997 static int proc_condition(PMMsg *data)
999 PmLockNode *tmp = NULL;
1000 unsigned int val = data->cond;
1001 pid_t pid = data->pid;
1002 Ecore_Timer *cond_timeout_id = NULL;
1003 bool holdkey_block = 0;
1009 char pname[PATH_MAX];
1012 get_pname(pid, pname);
1013 val_timeout = val >> SHIFT_CHANGE_TIMEOUT;
1014 if (val_timeout & (CUSTOM_TIMEOUT_BIT | CUSTOM_HOLDKEY_BIT)) {
1015 if (data->timeout == 0 && data->timeout2 == 0) {
1016 _I("LCD timeout changed : default setting");
1017 get_lcd_timeout_from_settings();
1018 if (get_lock_screen_state() == VCONFKEY_IDLE_LOCK) {
1019 _I("LOCK state : setting lock timeout!");
1020 states[S_NORMAL].timeout = lock_screen_timeout;
1022 custom_normal_timeout = custom_dim_timeout = 0;
1023 if (!(val_timeout & CUSTOM_HOLDKEY_BIT))
1024 custom_change_pid = -1;
1026 _I("LCD timeout changed : normal(%d s), dim(%d s)",
1027 data->timeout, data->timeout2);
1028 custom_normal_timeout = SEC_TO_MSEC(data->timeout);
1029 states[S_NORMAL].timeout = custom_normal_timeout;
1030 custom_dim_timeout = SEC_TO_MSEC(data->timeout2);
1031 states[S_LCDDIM].timeout = custom_dim_timeout;
1032 custom_change_pid = pid;
1035 if (val_timeout & CUSTOM_HOLDKEY_BIT) {
1036 custom_holdkey_block = true;
1037 custom_change_pid = pid;
1038 _I("hold key disabled !");
1040 custom_holdkey_block = false;
1041 _I("hold key enabled !");
1045 if (val & MASK_DIM) {
1046 if (data->timeout > 0) {
1048 ecore_timer_add(MSEC_TO_SEC(data->timeout),
1049 (Ecore_Task_Cb)del_dim_cond, (void*)pid);
1051 holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
1052 tmp = find_node(S_LCDDIM, pid);
1054 add_node(S_LCDDIM, pid, cond_timeout_id, holdkey_block);
1056 if (data->timeout > 0) {
1060 if (tmp->timeout_id) {
1061 ecore_timer_del(tmp->timeout_id);
1062 tmp->timeout_id = cond_timeout_id;
1064 tmp->holdkey_block = holdkey_block;
1067 _SD("[%s] locked by pid %d - process %s holdkeyblock %d\n",
1068 "S_NORMAL", pid, pname, holdkey_block);
1069 set_lock_time(pname, S_NORMAL);
1071 if (val & MASK_OFF) {
1072 if (data->timeout > 0) {
1074 ecore_timer_add(MSEC_TO_SEC(data->timeout),
1075 (Ecore_Task_Cb)del_off_cond, (void*)pid);
1077 holdkey_block = GET_HOLDKEY_BLOCK_STATE(val);
1078 tmp = find_node(S_LCDOFF, pid);
1080 add_node(S_LCDOFF, pid, cond_timeout_id, holdkey_block);
1082 if (data->timeout > 0) {
1086 if (tmp->timeout_id) {
1087 ecore_timer_del(tmp->timeout_id);
1088 tmp->timeout_id = cond_timeout_id;
1090 tmp->holdkey_block = holdkey_block;
1093 _SD("[%s] locked by pid %d - process %s holdkeyblock %d\n",
1094 "S_LCDDIM", pid, pname, holdkey_block);
1095 set_lock_time(pname, S_LCDDIM);
1097 if (val & MASK_SLP) {
1099 * pm-state must be changed to LCDOFF,
1100 * to guarantee of LCDOFF-lock
1101 * when system resumes from suspend state.
1103 if (pm_cur_state == S_SLEEP)
1104 proc_change_state(S_LCDOFF <<
1105 (SHIFT_CHANGE_STATE + S_LCDOFF), getpid());
1106 if (data->timeout > 0) {
1108 ecore_timer_add(MSEC_TO_SEC(data->timeout),
1109 (Ecore_Task_Cb)del_sleep_cond, (void*)pid);
1111 if (GET_STANDBY_MODE_STATE(val))
1112 set_standby_mode(pid, true);
1113 tmp = find_node(S_SLEEP, pid);
1115 add_node(S_SLEEP, pid, cond_timeout_id, 0);
1117 if (data->timeout > 0) {
1121 if (tmp->timeout_id) {
1122 ecore_timer_del(tmp->timeout_id);
1123 tmp->timeout_id = cond_timeout_id;
1125 tmp->holdkey_block = 0;
1127 set_process_active(EINA_TRUE, pid);
1130 _SD("[%s] locked by pid %d - process %s\n", "S_LCDOFF", pid,
1132 set_lock_time(pname, S_LCDOFF);
1135 /* UNLOCK(GRANT) condition processing */
1136 val = val >> SHIFT_UNLOCK;
1137 if (val & MASK_DIM) {
1138 tmp = find_node(S_LCDDIM, pid);
1139 del_node(S_LCDDIM, tmp);
1140 _SD("[%s] unlocked by pid %d - process %s\n", "S_NORMAL",
1142 set_unlock_time(pname, S_NORMAL);
1144 if (val & MASK_OFF) {
1145 tmp = find_node(S_LCDOFF, pid);
1146 del_node(S_LCDOFF, tmp);
1147 _SD("[%s] unlocked by pid %d - process %s\n", "S_LCDDIM",
1149 set_unlock_time(pname, S_LCDDIM);
1151 if (val & MASK_SLP) {
1152 tmp = find_node(S_SLEEP, pid);
1153 del_node(S_SLEEP, tmp);
1155 set_standby_mode(pid, false);
1156 set_process_active(EINA_FALSE, pid);
1158 _SD("[%s] unlocked by pid %d - process %s\n", "S_LCDOFF",
1160 set_unlock_time(pname, S_LCDOFF);
1162 if (check_suspend_direct != NULL && check_suspend_direct(pid))
1168 reset_timeout(states[pm_cur_state].timeout);
1169 _I("reset timeout (%d ms)",
1170 states[pm_cur_state].timeout);
1173 /* guard time for suspend */
1174 if (pm_cur_state == S_LCDOFF) {
1175 reset_timeout(states[S_LCDOFF].timeout);
1176 _I("margin timeout (%d ms)",
1177 states[S_LCDOFF].timeout);
1181 if (timeout_src_id == 0)
1182 states[pm_cur_state].trans(EVENT_TIMEOUT);
1187 /* If some changed, return 1 */
1188 int check_processes(enum state_t prohibit_state)
1190 PmLockNode *t = cond_head[prohibit_state];
1191 PmLockNode *tmp = NULL;
1195 if (t->pid < INTERNAL_LOCK_BASE && kill(t->pid, 0) == -1) {
1196 _E("%d process does not exist, delete the REQ"
1197 " - prohibit state %d ",
1198 t->pid, prohibit_state);
1199 if (t->pid == custom_change_pid) {
1200 get_lcd_timeout_from_settings();
1201 custom_normal_timeout = custom_dim_timeout = 0;
1202 custom_change_pid = -1;
1205 set_standby_mode(t->pid, false);
1212 del_node(prohibit_state, tmp);
1220 int check_holdkey_block(enum state_t state)
1222 PmLockNode *t = cond_head[state];
1225 _I("check holdkey block : state of %s", state_string[state]);
1227 if (custom_holdkey_block == true) {
1228 _I("custom hold key blocked by pid(%d)",
1234 if (t->holdkey_block == true) {
1236 _I("Hold key blocked by pid(%d)!", t->pid);
1245 int delete_condition(enum state_t state)
1247 PmLockNode *t = cond_head[state];
1249 PmLockNode *tmp = NULL;
1251 char pname[PATH_MAX];
1253 _I("delete condition : state of %s", state_string[state]);
1256 if (t->timeout_id > 0) {
1257 ecore_timer_del(t->timeout_id);
1258 t->timeout_id = NULL;
1263 if (state == S_SLEEP)
1264 set_process_active(EINA_FALSE, pid);
1265 _I("delete node of pid(%d)", pid);
1266 del_node(state, tmp);
1267 get_pname(pid, pname);
1268 set_unlock_time(pname, state-1);
1274 void update_lcdoff_source(int source)
1280 case VCONFKEY_PM_LCDOFF_BY_TIMEOUT:
1281 _I("LCD OFF by timeout");
1283 case VCONFKEY_PM_LCDOFF_BY_POWERKEY:
1284 _I("LCD OFF by powerkey");
1287 _E("Invalid value(%d)", source);
1290 vconf_set_int(VCONFKEY_PM_LCDOFF_SOURCE, source);
1293 #ifdef ENABLE_PM_LOG
1295 typedef struct _pm_history {
1297 enum pm_log_type log_type;
1301 static int max_history_count = MAX_LOG_COUNT;
1302 static pm_history pm_history_log[MAX_LOG_COUNT] = {0,};
1303 static int history_count = 0;
1305 static const char history_string[PM_LOG_MAX][15] =
1306 {"PRESS", "LONG PRESS", "RELEASE", "LCD ON", "LCD ON FAIL",
1307 "LCD DIM", "LCD DIM FAIL", "LCD OFF", "LCD OFF FAIL", "SLEEP"};
1309 void pm_history_init()
1311 memset(pm_history_log, 0x0, sizeof(pm_history_log));
1313 max_history_count = MAX_LOG_COUNT;
1316 void pm_history_save(enum pm_log_type log_type, int code)
1321 pm_history_log[history_count].time = now;
1322 pm_history_log[history_count].log_type = log_type;
1323 pm_history_log[history_count].keycode = code;
1326 if (history_count >= max_history_count)
1330 void pm_history_print(int fd, int count)
1332 int start_index, index, i;
1336 if (count <= 0 || count > max_history_count)
1339 start_index = (history_count - count + max_history_count)
1340 % max_history_count;
1342 for (i = 0; i < count; i++) {
1343 index = (start_index + i) % max_history_count;
1345 if (pm_history_log[index].time == 0)
1348 if (pm_history_log[index].log_type < PM_LOG_MIN ||
1349 pm_history_log[index].log_type >= PM_LOG_MAX)
1351 ctime_r(&pm_history_log[index].time, time_buf);
1352 snprintf(buf, sizeof(buf), "[%3d] %15s %3d %s",
1354 history_string[pm_history_log[index].log_type],
1355 pm_history_log[index].keycode,
1357 write(fd, buf, strlen(buf));
1362 /* logging indev_list for debug */
1363 void print_dev_list(int fd)
1366 unsigned int total = 0;
1369 total = eina_list_count(indev_list);
1370 _I("***** total list : %d *****", total);
1371 for (i = 0; i < total; i++) {
1372 tmp = (indev*)eina_list_nth(indev_list, i);
1373 _I("* %d | path:%s, fd:%d, dev_fd:%d",
1374 i, tmp->dev_path, tmp->fd, tmp->dev_fd);
1377 snprintf(buf, sizeof(buf), " %2d| path:%s, fd:%d, dev_fd:%d\n",
1378 i, tmp->dev_path, tmp->fd, tmp->dev_fd);
1379 write(fd, buf, strlen(buf));
1382 _I("***************************\n");
1385 void print_info(int fd)
1390 Eina_List *l = NULL;
1392 char pname[PATH_MAX];
1397 snprintf(buf, sizeof(buf),
1398 "\n==========================================="
1399 "===========================\n");
1400 write(fd, buf, strlen(buf));
1401 snprintf(buf, sizeof(buf),"Timeout Info: Run[%dms] Dim[%dms] Off[%dms]\n",
1402 states[S_NORMAL].timeout,
1403 states[S_LCDDIM].timeout, states[S_LCDOFF].timeout);
1404 write(fd, buf, strlen(buf));
1406 snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n",
1407 (trans_condition & MASK_DIM) ? state_string[S_NORMAL] : "-",
1408 (trans_condition & MASK_OFF) ? state_string[S_LCDDIM] : "-",
1409 (trans_condition & MASK_SLP) ? state_string[S_LCDOFF] : "-");
1410 write(fd, buf, strlen(buf));
1412 snprintf(buf, sizeof(buf), "Current State: %s\n",
1413 state_string[pm_cur_state]);
1414 write(fd, buf, strlen(buf));
1416 snprintf(buf, sizeof(buf), "Current Lock Conditions: \n");
1417 write(fd, buf, strlen(buf));
1419 for (s_index = S_NORMAL; s_index < S_END; s_index++) {
1422 t = cond_head[s_index];
1425 get_pname((pid_t)t->pid, pname);
1426 ctime_r(&t->time, time_buf);
1427 snprintf(buf, sizeof(buf),
1428 " %d: [%s] locked by pid %d %s %s",
1429 i++, state_string[s_index - 1], t->pid, pname, time_buf);
1430 write(fd, buf, strlen(buf));
1438 snprintf(buf, sizeof(buf), "\n\nstandby mode is on\n");
1439 write(fd, buf, strlen(buf));
1441 EINA_LIST_FOREACH(standby_mode_list, l, data) {
1442 get_pname((pid_t)data, pname);
1443 snprintf(buf, sizeof(buf),
1444 " standby mode acquired by pid %d"
1445 " - process %s\n", data, pname);
1446 write(fd, buf, strlen(buf));
1449 print_lock_info_list(fd);
1451 #ifdef ENABLE_PM_LOG
1452 pm_history_print(fd, 250);
1456 void save_display_log(void)
1463 _D("internal state is saved!");
1466 ctime_r(&now_time, time_buf);
1468 fd = open(PM_STATE_LOG_FILE, O_CREAT | O_TRUNC | O_WRONLY, 0644);
1470 snprintf(buf, sizeof(buf),
1471 "\npm_state_log now-time : %d(s) %s\n\n",
1472 (int)now_time, time_buf);
1473 write(fd, buf, strlen(buf));
1475 snprintf(buf, sizeof(buf), "pm_status_flag: %x\n", pm_status_flag);
1476 write(fd, buf, strlen(buf));
1478 snprintf(buf, sizeof(buf), "screen lock status : %d\n",
1479 get_lock_screen_state());
1480 write(fd, buf, strlen(buf));
1486 fd = open("/dev/console", O_WRONLY);
1493 /* SIGHUP signal handler
1494 * For debug... print info to syslog
1496 static void sig_hup(int signo)
1501 static void sig_usr(int signo)
1503 pm_status_flag |= VCALL_FLAG;
1506 int check_lcdoff_direct(void)
1508 int ret, lock, cradle;
1510 if (pm_old_state != S_NORMAL)
1513 if (pm_cur_state != S_LCDDIM)
1517 * goto lcd dim state when battery health is bad
1518 * and abnormal popup shows
1520 if ((pm_status_flag & DIMSTAY_FLAG) &&
1521 (check_abnormal_popup() == HEALTH_BAD))
1525 * LCD on -> off directly in ambient mode
1527 if (get_ambient_mode != NULL &&
1528 get_ambient_mode() == true &&
1529 check_lock_state(S_LCDOFF) == false) {
1536 lock = get_lock_screen_state();
1537 if (lock != VCONFKEY_IDLE_LOCK && hallic_open)
1543 ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle);
1544 if (ret >= 0 && cradle == DOCK_SOUND)
1547 _D("Goto LCDOFF direct(%d,%d,%d)", lock, hdmi_state, cradle);
1552 int check_lcdoff_lock_state(void)
1554 if (cond_head[S_SLEEP] != NULL)
1561 * default transition function
1564 * 3. call enter action function
1566 static int default_trans(int evt)
1568 struct state *st = &states[pm_cur_state];
1571 next_state = (enum state_t)trans_table[pm_cur_state][evt];
1573 /* check conditions */
1574 while (st->check && !st->check(next_state)) {
1575 /* There is a condition. */
1577 _D("standby mode, goto next_state %s",
1578 state_string[next_state]);
1581 _I("%s -> %s : check fail", state_string[pm_cur_state],
1582 state_string[next_state]);
1583 if (!check_processes(next_state)) {
1584 /* this is valid condition - the application that sent the condition is running now. */
1590 if (display_info.face_detection &&
1591 (pm_status_flag & SMAST_FLAG) && hallic_open) {
1592 if (display_info.face_detection(evt, pm_cur_state, next_state))
1596 /* state transition */
1597 pm_old_state = pm_cur_state;
1598 pm_cur_state = next_state;
1599 st = &states[pm_cur_state];
1603 if (pm_cur_state == S_LCDOFF)
1604 update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT);
1606 if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDOFF)
1607 if (set_custom_lcdon_timeout(0) == true)
1608 update_display_time();
1610 if (check_lcdoff_direct() == true) {
1611 /* enter next state directly */
1612 states[pm_cur_state].trans(EVENT_TIMEOUT);
1615 st->action(st->timeout);
1622 static Eina_Bool lcd_on_expired(void *data)
1624 int lock_state, ret;
1626 if (lock_timeout_id)
1627 lock_timeout_id = NULL;
1629 /* check state of lock */
1630 ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1632 if (ret > 0 && lock_state == VCONFKEY_IDLE_LOCK)
1635 /* lock screen is not launched yet, but lcd is on */
1636 if (check_lcd_on() == true)
1637 lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
1642 static inline void stop_lock_timer(void)
1644 if (lock_timeout_id) {
1645 ecore_timer_del(lock_timeout_id);
1646 lock_timeout_id = NULL;
1650 static void check_lock_screen(void)
1652 int lock_setting, lock_state, app_state, ret;
1656 ret = vconf_get_int(VCONFKEY_CALL_STATE, &app_state);
1657 if (ret >= 0 && app_state != VCONFKEY_CALL_OFF)
1660 /* check setting of lock screen is enabled. */
1661 ret = vconf_get_int(VCONFKEY_SETAPPL_SCREEN_LOCK_TYPE_INT,
1664 if (ret < 0 || lock_setting == SETTING_SCREEN_LOCK_TYPE_NONE)
1667 /* check state of lock */
1668 ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1670 if (ret < 0 || lock_state == VCONFKEY_IDLE_LOCK)
1673 /* Use time to check lock is done. */
1674 lock_timeout_id = ecore_timer_add(display_conf.lock_wait_time,
1675 (Ecore_Task_Cb)lcd_on_expired, (void*)NULL);
1680 if (check_lcd_on() == true)
1681 lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
1684 /* default enter action function */
1685 static int default_action(int timeout)
1688 int wakeup_count = -1;
1690 char *pkgname = NULL;
1692 int lock_state = -1;
1696 static time_t last_update_time = 0;
1697 static int last_timeout = 0;
1698 struct timeval now_tv;
1700 if (status != DEVICE_OPS_STATUS_START) {
1701 _E("display is not started!");
1705 if (pm_cur_state != S_SLEEP) {
1706 if (pm_cur_state == S_NORMAL &&
1707 lcdon_tv.tv_sec != 0) {
1708 gettimeofday(&now_tv, NULL);
1709 timeout -= DIFF_TIMEVAL_MS(now_tv, lcdon_tv);
1710 lcdon_tv.tv_sec = 0;
1712 /* set timer with current state timeout */
1713 reset_timeout(timeout);
1715 if (pm_cur_state == S_NORMAL) {
1716 time(&last_update_time);
1717 last_timeout = timeout;
1719 _I("timout set: %s state %d ms",
1720 state_string[pm_cur_state], timeout);
1724 if (pm_cur_state != pm_old_state && pm_cur_state != S_SLEEP) {
1725 if (power_ops.get_power_lock_support())
1726 power_ops.power_lock();
1727 if (pm_cur_state != S_LCDOFF &&
1728 (get_ambient_mode == NULL ||
1729 get_ambient_mode() == false))
1730 set_setting_pmstate(pm_cur_state);
1731 device_notify(DEVICE_NOTIFIER_LCD, (void *)pm_cur_state);
1734 if (pm_old_state == S_NORMAL && pm_cur_state != S_NORMAL) {
1736 diff = difftime(now, last_update_time);
1737 _I("S_NORMAL is changed to %s [%d ms, %.0f s]",
1738 state_string[pm_cur_state], last_timeout, diff);
1741 switch (pm_cur_state) {
1744 * normal state : backlight on and restore
1745 * the previous brightness
1747 if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP) {
1748 if (pre_suspend_flag == true) {
1749 power_ops.post_resume();
1750 pre_suspend_flag = false;
1752 check_lock_screen();
1753 } else if (pm_old_state == S_LCDDIM)
1754 backlight_ops.update();
1756 if (check_lcd_on() == true)
1757 lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
1758 set_standby_state(false);
1762 if (pm_old_state == S_NORMAL &&
1763 backlight_ops.get_custom_status())
1764 backlight_ops.save_custom_brightness();
1765 /* lcd dim state : dim the brightness */
1766 backlight_ops.dim();
1768 if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP)
1769 lcd_on_procedure(LCD_DIM, NORMAL_MODE);
1770 set_standby_state(false);
1774 if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF) {
1776 /* lcd off state : turn off the backlight */
1777 if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF)
1778 lcd_off_procedure();
1780 if (get_ambient_mode == NULL ||
1781 get_ambient_mode() == false)
1782 set_setting_pmstate(pm_cur_state);
1784 if (pre_suspend_flag == false) {
1785 pre_suspend_flag = true;
1786 power_ops.pre_suspend();
1790 if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF
1791 || lcd_paneloff_mode)
1792 lcd_off_procedure();
1796 if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF)
1799 if (backlight_ops.get_lcd_power() != PM_LCD_POWER_OFF)
1800 lcd_off_procedure();
1802 if (!power_ops.get_power_lock_support()) {
1803 /* sleep state : set system mode to SUSPEND */
1804 if (device_get_property(DEVICE_TYPE_POWER,
1805 PROP_POWER_WAKEUP_COUNT, &wakeup_count) < 0)
1806 _E("wakeup count read error");
1808 if (wakeup_count < 0) {
1809 _I("Wakup Event! Can not enter suspend mode.");
1813 if (device_set_property(DEVICE_TYPE_POWER,
1814 PROP_POWER_WAKEUP_COUNT, wakeup_count) < 0) {
1815 _E("wakeup count write error");
1825 #ifdef ENABLE_PM_LOG
1826 pm_history_save(PM_LOG_SLEEP, pm_cur_state);
1828 if (power_ops.get_power_lock_support()) {
1829 if (power_ops.power_unlock() < 0)
1830 _E("power unlock state error!");
1832 power_ops.suspend();
1833 _I("system wakeup!!");
1834 system_wakeup_flag = true;
1836 if (power_ops.check_wakeup_src() == EVENT_DEVICE)
1837 /* system waked up by devices */
1838 states[pm_cur_state].trans(EVENT_DEVICE);
1840 /* system waked up by user input */
1841 states[pm_cur_state].trans(EVENT_INPUT);
1846 if (!power_ops.get_power_lock_support()) {
1848 states[pm_cur_state].trans(EVENT_DEVICE);
1854 * default check function
1856 * 0 : can't transit, others : transitable
1858 static int default_check(int next)
1860 int trans_cond = trans_condition & MASK_BIT;
1861 int lock_state = -1;
1864 vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1865 if (lock_state==VCONFKEY_IDLE_LOCK && next != S_SLEEP) {
1867 vconf_get_int(VCONFKEY_CALL_STATE, &app_state);
1868 if (app_state != VCONFKEY_CALL_OFF)
1870 vconf_get_bool(VCONFKEY_ALARM_RINGING, &app_state);
1871 if (app_state == EINA_TRUE)
1873 _I("default_check:LOCK STATE, it's transitable");
1880 trans_cond = trans_cond & MASK_DIM;
1883 trans_cond = trans_cond & MASK_OFF;
1886 trans_cond = trans_cond & MASK_SLP;
1888 default: /* S_NORMAL is exceptional */
1893 if (trans_cond != 0) {
1898 return 1; /* transitable */
1901 static void default_saving_mode(int onoff)
1904 pm_status_flag |= PWRSV_FLAG;
1905 /* off hbm state, it's power saving mode */
1906 if (hbm_get_state != NULL &&
1907 hbm_get_state() == true)
1908 hbm_set_state_with_timeout(false, 0);
1910 pm_status_flag &= ~PWRSV_FLAG;
1912 if (pm_cur_state == S_NORMAL)
1913 backlight_ops.update();
1916 static int poll_callback(int condition, PMMsg *data)
1918 static time_t last_t;
1921 if (status != DEVICE_OPS_STATUS_START) {
1922 _E("display logic is not started!");
1926 if (condition == INPUT_POLL_EVENT) {
1927 if (pm_cur_state == S_LCDOFF || pm_cur_state == S_SLEEP)
1928 _I("Power key input");
1930 if (last_t != now ||
1931 pm_cur_state == S_LCDOFF ||
1932 pm_cur_state == S_SLEEP) {
1933 states[pm_cur_state].trans(EVENT_INPUT);
1936 } else if (condition == PM_CONTROL_EVENT) {
1937 if (data->cond & MASK_BIT
1938 || ((data->cond >> SHIFT_UNLOCK) & MASK_BIT)
1939 || (data->cond >> SHIFT_CHANGE_TIMEOUT))
1940 proc_condition(data);
1942 if (data->cond & CHANGE_STATE_BIT)
1943 proc_change_state(data->cond, data->pid);
1949 static int update_setting(int key_idx, int val)
1953 int run_timeout = -1;
1956 case SETTING_TO_NORMAL:
1957 update_display_time();
1958 states[pm_cur_state].trans(EVENT_INPUT);
1960 case SETTING_HALLIC_OPEN:
1962 update_display_time();
1963 if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDDIM)
1964 states[pm_cur_state].trans(EVENT_INPUT);
1965 else if (pm_cur_state == S_SLEEP && hallic_open)
1966 proc_change_state(S_LCDOFF <<
1967 (SHIFT_CHANGE_STATE + S_LCDOFF), getpid());
1969 case SETTING_LOW_BATT:
1970 if (low_battery_state(val)) {
1971 if (!(pm_status_flag & CHRGR_FLAG))
1972 power_saving_func(true);
1973 pm_status_flag |= LOWBT_FLAG;
1975 if (pm_status_flag & PWRSV_FLAG)
1976 power_saving_func(false);
1977 pm_status_flag &= ~LOWBT_FLAG;
1978 pm_status_flag &= ~BRTCH_FLAG;
1979 vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
1983 case SETTING_CHARGING:
1985 if (pm_status_flag & LOWBT_FLAG) {
1986 power_saving_func(false);
1987 pm_status_flag &= ~LOWBT_FLAG;
1989 pm_status_flag |= CHRGR_FLAG;
1991 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
1992 vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
1994 if (low_battery_state(bat_state)) {
1995 power_saving_func(true);
1996 pm_status_flag |= LOWBT_FLAG;
1998 pm_status_flag &= ~CHRGR_FLAG;
2001 case SETTING_BRT_LEVEL:
2002 if (pm_status_flag & PWRSV_FLAG) {
2003 pm_status_flag |= BRTCH_FLAG;
2004 vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM,
2006 _I("brightness changed in low battery,"
2007 "escape dim state");
2009 backlight_ops.set_default_brt(val);
2010 snprintf(buf, sizeof(buf), "%d", val);
2011 _D("Brightness set in bl : %d",val);
2012 launch_evenif_exist(SET_BRIGHTNESS_IN_BOOTLOADER, buf);
2014 case SETTING_LOCK_SCREEN:
2015 set_lock_screen_state(val);
2016 if (val == VCONFKEY_IDLE_UNLOCK) {
2017 if (CHECK_OPS(keyfilter_ops, backlight_enable))
2018 keyfilter_ops->backlight_enable(false);
2021 /* LCD on if lock screen show before waiting time */
2022 if (pm_cur_state == S_NORMAL &&
2023 val == VCONFKEY_IDLE_LOCK &&
2024 backlight_ops.get_lcd_power() != PM_LCD_POWER_ON)
2025 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
2027 update_display_time();
2028 if (pm_cur_state == S_NORMAL) {
2029 states[pm_cur_state].trans(EVENT_INPUT);
2032 case SETTING_LOCK_SCREEN_BG:
2033 set_lock_screen_bg_state(val);
2034 update_display_time();
2035 if (pm_cur_state == S_NORMAL) {
2036 states[pm_cur_state].trans(EVENT_INPUT);
2039 case SETTING_SMART_STAY:
2041 pm_status_flag &= ~SMAST_FLAG;
2042 _I("Smart Stay Feature off");
2044 pm_status_flag |= SMAST_FLAG;
2045 _I("Smart Stay Feature on");
2048 case SETTING_POWEROFF:
2050 case VCONFKEY_SYSMAN_POWER_OFF_NONE:
2051 case VCONFKEY_SYSMAN_POWER_OFF_POPUP:
2052 pm_status_flag &= ~PWROFF_FLAG;
2054 case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
2055 case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
2056 pm_status_flag |= PWROFF_FLAG;
2060 case SETTING_BOOT_POWER_ON_STATUS:
2062 * Unlock lcd off after booting is done.
2063 * deviced guarantees all booting script is executing.
2064 * Last script of booting unlocks this suspend blocking state.
2066 if (val == VCONFKEY_DEVICED_BOOT_POWER_ON_DONE) {
2068 pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
2071 case SETTING_POWER_CUSTOM_BRIGHTNESS:
2072 if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON)
2073 backlight_ops.set_custom_status(true);
2075 backlight_ops.set_custom_status(false);
2077 case SETTING_ACCESSIBILITY_TTS:
2079 _I("TTS is %s", (val ? "ON" : "OFF"));
2088 static void check_seed_status(void)
2092 int bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
2095 int lock_state = -1;
2096 int smart_stay_on = 0;
2098 /* Charging check */
2099 if ((get_charging_status(&tmp) == 0) && (tmp > 0)) {
2100 pm_status_flag |= CHRGR_FLAG;
2103 ret = get_setting_brightness(&tmp);
2104 if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
2105 _I("fail to read vconf value for brightness");
2106 brt = PM_DEFAULT_BRIGHTNESS;
2107 if (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)
2108 vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
2111 _I("Set brightness from Setting App. %d", tmp);
2112 backlight_ops.set_default_brt(tmp);
2114 vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
2115 if (low_battery_state(bat_state)) {
2116 if (!(pm_status_flag & CHRGR_FLAG)) {
2117 power_saving_func(true);
2118 pm_status_flag |= LOWBT_FLAG;
2121 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
2123 /* lock screen check */
2124 ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
2125 set_lock_screen_state(lock_state);
2126 if (lock_state == VCONFKEY_IDLE_LOCK) {
2127 states[S_NORMAL].timeout = lock_screen_timeout;
2128 _I("LCD NORMAL timeout is set by %d ms"
2129 " for lock screen", lock_screen_timeout);
2132 /* Smart stay status */
2133 vconf_get_int(VCONFKEY_SETAPPL_SMARTSCREEN_SMARTSTAY_STATUS, &smart_stay_on);
2134 if (!smart_stay_on) {
2135 _I("Smart Stay Feature off");
2137 _I("Smart Stay Feature on");
2138 pm_status_flag |= SMAST_FLAG;
2142 ret = vconf_get_bool(VCONFKEY_SETAPPL_ACCESSIBILITY_TTS, &tts_state);
2144 _E("Failed to get TTS setting! (%d)", ret);
2145 _I("TTS is %s", (tts_state ? "ON" : "OFF"));
2150 static void init_lcd_operation(void)
2152 const struct device_ops *ops = NULL;
2154 ops = find_device("display");
2155 if (!check_default(ops))
2156 EINA_LIST_APPEND(lcdon_ops, ops);
2158 ops = find_device("touchscreen");
2159 if (!check_default(ops))
2160 EINA_LIST_APPEND(lcdon_ops, ops);
2162 ops = find_device("touchkey");
2163 if (!check_default(ops))
2164 EINA_LIST_APPEND(lcdon_ops, ops);
2167 static void exit_lcd_operation(void)
2169 Eina_List *l = NULL;
2170 Eina_List *l_next = NULL;
2171 const struct device_ops *ops = NULL;
2173 EINA_LIST_FOREACH_SAFE(lcdon_ops, l, l_next, ops)
2174 EINA_LIST_REMOVE_LIST(lcdon_ops, l);
2186 static const char *errMSG[INIT_END] = {
2187 [INIT_SETTING] = "setting init error",
2188 [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
2189 [INIT_POLL] = "input devices poll init error",
2190 [INIT_FIFO] = "FIFO poll init error",
2191 [INIT_DBUS] = "d-bus init error",
2194 static void esd_action()
2198 if (pm_cur_state == S_NORMAL) {
2199 backlight_ops.off(NORMAL_MODE);
2200 backlight_ops.on(NORMAL_MODE);
2201 } else if (pm_cur_state == S_LCDDIM) {
2202 backlight_ops.off(NORMAL_MODE);
2203 backlight_ops.dim();
2204 } else if (alpm_get_state != NULL &&
2205 alpm_get_state() == true) {
2206 proc_change_state(S_NORMAL <<
2207 (SHIFT_CHANGE_STATE + S_NORMAL), getpid());
2208 backlight_ops.off(NORMAL_MODE);
2209 backlight_ops.on(NORMAL_MODE);
2213 static int input_action(char* input_act, char* input_path)
2216 Eina_List *l = NULL;
2217 Eina_List *l_next = NULL;
2220 if (!strcmp("add", input_act)) {
2221 _I("add input path : %s", input_path);
2222 ret = init_pm_poll_input(poll_callback, input_path);
2223 } else if (!strcmp("remove", input_act)) {
2224 EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data)
2225 if (!strcmp(input_path, data->dev_path)) {
2226 _I("remove %s", input_path);
2227 ecore_main_fd_handler_del(data->dev_fd);
2229 free(data->dev_path);
2231 indev_list = eina_list_remove_list(indev_list, l);
2233 } else if (!strcmp("change", input_act)) {
2234 if (!strcmp("ESD", input_path))
2242 int set_lcd_timeout(int on, int dim, int holdkey_block, char *name)
2244 if (on == 0 && dim == 0) {
2245 _I("LCD timeout changed : default setting");
2246 custom_normal_timeout = custom_dim_timeout = 0;
2247 } else if (on < 0 || dim < 0) {
2248 _E("fail to set value (%d,%d)", on, dim);
2251 _I("LCD timeout changed : on(%ds), dim(%ds)", on, dim);
2252 custom_normal_timeout = SEC_TO_MSEC(on);
2253 custom_dim_timeout = SEC_TO_MSEC(dim);
2255 /* Apply new backlight time */
2256 update_display_time();
2257 if (pm_cur_state == S_NORMAL)
2258 states[pm_cur_state].trans(EVENT_INPUT);
2260 if (holdkey_block) {
2261 custom_holdkey_block = true;
2262 _I("hold key disabled !");
2264 custom_holdkey_block = false;
2265 _I("hold key enabled !");
2268 if (custom_change_name) {
2269 free(custom_change_name);
2270 custom_change_name = 0;
2273 if (custom_normal_timeout == 0 &&
2274 custom_dim_timeout == 0 &&
2278 custom_change_name = strndup(name, strlen(name));
2279 if (!custom_change_name) {
2280 _E("Malloc falied!");
2281 custom_normal_timeout = custom_dim_timeout = 0;
2282 custom_holdkey_block = false;
2289 int reset_lcd_timeout(char *name, enum watch_id id)
2294 if (!custom_change_name)
2297 if (strcmp(name, custom_change_name))
2300 _I("reset lcd timeout %s: set default timeout", name);
2302 free(custom_change_name);
2303 custom_change_name = 0;
2304 custom_normal_timeout = custom_dim_timeout = 0;
2305 custom_holdkey_block = false;
2307 update_display_time();
2308 if (pm_cur_state == S_NORMAL) {
2309 states[pm_cur_state].trans(EVENT_INPUT);
2315 int get_hdmi_state(void)
2320 static int hdmi_changed(void *data)
2322 hdmi_state = (int)data;
2327 static int hall_ic_open(void *data)
2329 int open = (int)data;
2331 update_pm_setting(SETTING_HALLIC_OPEN, open);
2333 if (display_info.update_auto_brightness)
2334 display_info.update_auto_brightness(false);
2339 static int input_device_add(void *data)
2341 char *path = (char *)data;
2346 input_action(UDEV_ADD, path);
2351 static int input_device_remove(void *data)
2353 char *path = (char *)data;
2358 input_action(UDEV_REMOVE, path);
2363 static int booting_done(void *data)
2365 static bool done = false;
2370 _I("booting done, unlock LCD_OFF");
2371 pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
2377 static int lcd_esd(void *data)
2384 input_action(UDEV_CHANGE, path);
2389 static int battery_health_changed(void *data)
2391 int health = (int)data;
2393 if (health == HEALTH_GOOD) {
2394 _D("battery health good");
2395 pm_status_flag &= ~DIMSTAY_FLAG;
2397 } else if (health == HEALTH_BAD) {
2398 _D("battery health bad");
2399 pm_status_flag |= DIMSTAY_FLAG;
2405 static int display_load_config(struct parse_result *result, void *user_data)
2407 struct display_config *c = user_data;
2409 _D("%s,%s,%s", result->section, result->name, result->value);
2414 if (!MATCH(result->section, "Display"))
2417 if (MATCH(result->name, "LockScreenWaitingTime")) {
2418 SET_CONF(c->lock_wait_time, atof(result->value));
2419 _D("lock wait time is %.3f", c->lock_wait_time);
2420 } else if (MATCH(result->name, "LongPressInterval")) {
2421 SET_CONF(c->longpress_interval, atof(result->value));
2422 _D("long press interval is %.3f", c->longpress_interval);
2423 } else if (MATCH(result->name, "LightSensorSamplingInterval")) {
2424 SET_CONF(c->lightsensor_interval, atof(result->value));
2425 _D("lightsensor interval is %.3f", c->lightsensor_interval);
2426 } else if (MATCH(result->name, "LCDOffTimeout")) {
2427 SET_CONF(c->lcdoff_timeout, atoi(result->value));
2428 _D("lcdoff timeout is %d ms", c->lcdoff_timeout);
2429 } else if (MATCH(result->name, "BrightnessChangeStep")) {
2430 SET_CONF(c->brightness_change_step, atoi(result->value));
2431 _D("brightness change step is %d", c->brightness_change_step);
2432 } else if (MATCH(result->name, "HBMLuxThreshold")) {
2433 SET_CONF(c->hbm_lux_threshold, atoi(result->value));
2434 _D("HBM lux threshold is %d", c->hbm_lux_threshold);
2435 } else if (MATCH(result->name, "LCDAlwaysOn")) {
2436 c->lcd_always_on = (MATCH(result->value, "yes") ? 1 : 0);
2437 _D("LCD always on is %d", c->lcd_always_on);
2438 } else if (MATCH(result->name, "ChangedFrameRateAllowed")) {
2439 if (strstr(result->value, "setting")) {
2440 c->framerate_app[REFRESH_SETTING] = 1;
2441 _D("framerate app is Setting");
2443 if (strstr(result->value, "all")) {
2444 memset(c->framerate_app, 1, sizeof(c->framerate_app));
2445 _D("framerate app is All");
2447 } else if (MATCH(result->name, "ControlDisplay")) {
2448 c->control_display = (MATCH(result->value, "yes") ? 1 : 0);
2449 _D("ControlDisplay is %d", c->control_display);
2450 } else if (MATCH(result->name, "PowerKeyDoublePressSupport")) {
2451 c->powerkey_doublepress = (MATCH(result->value, "yes") ? 1 : 0);
2452 _D("PowerKeyDoublePressSupport is %d", c->powerkey_doublepress);
2453 } else if (MATCH(result->name, "UseALPM")) {
2454 c->alpm_on = (MATCH(result->value, "yes") ? 1 : 0);
2455 _D("UseALPM is %d", c->alpm_on);
2456 } else if (MATCH(result->name, "AccelSensorOn")) {
2457 c->accel_sensor_on = (MATCH(result->value, "yes") ? 1 : 0);
2458 _D("AccelSensorOn is %d", c->accel_sensor_on);
2459 } else if (MATCH(result->name, "ContinuousSampling")) {
2460 c->continuous_sampling = (MATCH(result->value, "yes") ? 1 : 0);
2461 _D("ContinuousSampling is %d", c->continuous_sampling);
2468 * Power manager Main
2471 static void display_init(void *data)
2474 unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS);
2477 _I("Start power manager");
2479 signal(SIGHUP, sig_hup);
2481 power_saving_func = default_saving_mode;
2482 /* noti init for new input device like bt mouse */
2485 /* load configutation */
2486 ret = config_parse(DISPLAY_CONF_FILE, display_load_config, &display_conf);
2488 _W("Failed to load %s, %s Use default value!",
2489 DISPLAY_CONF_FILE, ret);
2491 register_notifier(DEVICE_NOTIFIER_HALLIC_OPEN, hall_ic_open);
2492 register_notifier(DEVICE_NOTIFIER_INPUT_ADD, input_device_add);
2493 register_notifier(DEVICE_NOTIFIER_INPUT_REMOVE, input_device_remove);
2494 register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
2495 register_notifier(DEVICE_NOTIFIER_LCD_ESD, lcd_esd);
2496 register_notifier(DEVICE_NOTIFIER_HDMI, hdmi_changed);
2497 register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed);
2499 for (i = INIT_SETTING; i < INIT_END; i++) {
2502 ret = init_setting(update_setting);
2504 case INIT_INTERFACE:
2505 get_lcd_timeout_from_settings();
2506 ret = init_sysfs(flags);
2510 ret = init_pm_poll(poll_callback);
2514 ret = init_pm_dbus();
2518 _E("%s", errMSG[i]);
2523 if (i == INIT_END) {
2524 display_ops_init(NULL);
2525 #ifdef ENABLE_PM_LOG
2528 init_lcd_operation();
2529 check_seed_status();
2531 if (display_conf.lcd_always_on) {
2532 _D("LCD always on!");
2533 trans_table[S_NORMAL][EVENT_TIMEOUT] = S_NORMAL;
2536 if (flags & WITHOUT_STARTNOTI) { /* start without noti */
2537 _I("Start Power managing without noti");
2538 pm_cur_state = S_NORMAL;
2539 set_setting_pmstate(pm_cur_state);
2541 timeout = states[S_NORMAL].timeout;
2542 /* check minimun lcd on time */
2543 if (timeout < DEFAULT_NORMAL_TIMEOUT)
2544 timeout = DEFAULT_NORMAL_TIMEOUT;
2546 reset_timeout(timeout);
2547 status = DEVICE_OPS_STATUS_START;
2549 * Lock lcd off until booting is done.
2550 * deviced guarantees all booting script is executing.
2551 * Last script of booting unlocks this suspend blocking state.
2553 pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF,
2554 STAY_CUR_STATE, BOOTING_DONE_WATING_TIME);
2556 if (CHECK_OPS(keyfilter_ops, init))
2557 keyfilter_ops->init();
2561 static void display_exit(void *data)
2565 status = DEVICE_OPS_STATUS_STOP;
2567 /* Set current state to S_NORMAL */
2568 pm_cur_state = S_NORMAL;
2569 set_setting_pmstate(pm_cur_state);
2570 /* timeout is not needed */
2571 reset_timeout(TIMEOUT_NONE);
2573 if (CHECK_OPS(keyfilter_ops, exit))
2574 keyfilter_ops->exit();
2576 display_ops_exit(NULL);
2578 for (i = i - 1; i >= INIT_SETTING; i--) {
2583 case INIT_INTERFACE:
2587 unregister_notifier(DEVICE_NOTIFIER_HALLIC_OPEN, hall_ic_open);
2588 unregister_notifier(DEVICE_NOTIFIER_INPUT_ADD,
2590 unregister_notifier(DEVICE_NOTIFIER_INPUT_REMOVE,
2591 input_device_remove);
2592 unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE,
2594 unregister_notifier(DEVICE_NOTIFIER_LCD_ESD, lcd_esd);
2595 unregister_notifier(DEVICE_NOTIFIER_HDMI, hdmi_changed);
2596 unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH,
2597 battery_health_changed);
2604 exit_lcd_operation();
2605 free_lock_info_list();
2607 _I("Stop power manager");
2610 static int display_start(enum device_flags flags)
2613 if (flags & NORMAL_MODE) {
2614 if (flags & LCD_PANEL_OFF_MODE)
2616 backlight_ops.standby(true);
2619 backlight_ops.on(flags);
2623 /* CORE LOGIC MODE */
2624 if (!(flags & CORE_LOGIC_MODE))
2627 if (status == DEVICE_OPS_STATUS_START)
2635 static int display_stop(enum device_flags flags)
2638 if (flags & NORMAL_MODE) {
2639 backlight_ops.off(flags);
2643 /* CORE LOGIC MODE */
2644 if (!(flags & CORE_LOGIC_MODE))
2647 if (status == DEVICE_OPS_STATUS_STOP)
2655 static int display_status(void)
2660 static const struct device_ops display_device_ops = {
2661 .priority = DEVICE_PRIORITY_HIGH,
2663 .init = display_init,
2664 .exit = display_exit,
2665 .start = display_start,
2666 .stop = display_stop,
2667 .status = display_status,
2670 DEVICE_OPS_REGISTER(&display_device_ops)