83d4672abcf0f4e373ae4dcb0267263de2501514
[platform/core/system/deviced.git] / plugins / mobile / display / core.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19
20 /**
21  * @file        core.c
22  * @brief       Power manager main loop.
23  *
24  * This file includes Main loop, the FSM, signal processing.
25  */
26 #include <signal.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <limits.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <stdbool.h>
34 #include <time.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <dlfcn.h>
39 #include <fnmatch.h>
40 #include <vconf-keys.h>
41 #include <sys/time.h>
42 #include <libsyscommon/list.h>
43 #include <hal/device/hal-device-power.h>
44
45 #include "ambient-mode.h"
46 #include "util.h"
47 #include "core.h"
48 #include "lock-detector.h"
49 #include "display-ops.h"
50 #include "shared/devices.h"
51 #include "shared/device-notifier.h"
52 #include "core/udev.h"
53 #include "shared/common.h"
54 #include "shared/apps.h"
55 #include "extcon/extcon.h"
56 #include "battery/power-supply.h"
57 #include "power/power.h"
58 #include "power/power-off.h"
59 #include "power/power-suspend.h"
60 #include "power/power-boot.h"
61 #include "power/power-doze.h"
62 #include "display/display-dpms.h"
63 #include "proximity.h"
64 #include "display-info.h"
65 #include "display-signal.h"
66 #include "display-lock.h"
67 #include "shared/plugin.h"
68
69 #define DISPLAY_CONF_FILE    "/etc/deviced/display.conf"
70
71 /**
72  * @addtogroup POWER_MANAGER
73  * @{
74  */
75
76 #define LOCK_SCREEN_INPUT_TIMEOUT       10000
77 #define LOCK_SCREEN_CONTROL_TIMEOUT     5000
78 #define ALWAYS_ON_TIMEOUT               360000000
79 #define LATE_LCD_TRANSIT                1
80
81 #define GESTURE_STR             "gesture"
82 #define POWER_KEY_STR           "powerkey"
83 #define TOUCH_STR               "touch"
84 #define EVENT_STR               "event"
85 #define TIMEOUT_STR             "timeout"
86 #define PROXI_STR               "proximity"
87 #define PALM_STR                "palm"
88 #define UNKNOWN_STR             "unknown"
89
90 extern void init_pm_internal();
91 extern void init_save_userlock(void);
92
93 static struct display_plugin *disp_plgn;
94 static struct _backlight_ops *backlight_ops;
95 static struct battery_plugin *battery_plgn;
96 static int (*fp_get_charging_status) (int *val);
97
98 static void (*power_saving_func) (int onoff);
99 static enum device_ops_status status = DEVICE_OPS_STATUS_UNINIT;
100
101 static guint timeout_src_id;
102 static int system_wakeup_flag = false;
103 static unsigned int custom_normal_timeout = 0;
104 static unsigned int custom_dim_timeout = 0;
105 int custom_holdkey_block = false;
106 static char *custom_change_name;
107 static bool hallic_open = true;
108 static guint lock_timeout_id;
109 static guint transit_timer;
110 static int lock_screen_timeout = LOCK_SCREEN_INPUT_TIMEOUT;
111 static struct timeval lcdon_tv;
112 static int lcd_paneloff_mode = false;
113 static int stay_touchscreen_off = false;
114 GList *lcdon_ops;
115 /*
116  * The two variables(lcdon_broadcast, pmstate_suspend) must be set initial
117  * state because it should be sent from previous state at booting time.
118  */
119 static bool lcdon_broadcast = true;
120
121 static bool touch_blocked = false;
122
123 /* default transition, action fuctions */
124 static int default_trans(int evt);
125 static int default_action(int timeout);
126 static int default_check(int curr, int next);
127
128 static gboolean del_normal_cond(void *data);
129 static gboolean del_dim_cond(void *data);
130 static gboolean del_off_cond(void *data);
131
132 static int default_proc_change_state(unsigned int cond, pid_t pid);
133 static int (*proc_change_state)(unsigned int cond, pid_t pid) = default_proc_change_state;
134
135 static struct state states[S_END] = {
136         { S_START,    "S_START",    NULL,          NULL,           NULL,          NULL            },
137         { S_NORMAL,   "S_NORMAL",   default_trans, default_action, default_check, del_normal_cond },
138         { S_LCDDIM,   "S_LCDDIM",   default_trans, default_action, default_check, del_dim_cond    },
139         { S_LCDOFF,   "S_LCDOFF",   default_trans, default_action, default_check, del_off_cond    },
140         { S_STANDBY,  "S_STANDBY",  NULL,          NULL,           NULL,          NULL            },
141         { S_SLEEP,    "S_SLEEP",    default_trans, default_action, default_check, NULL            },
142         { S_POWEROFF, "S_POWEROFF", NULL,          NULL,           NULL,          NULL            },
143 };
144
145 static int trans_table[S_END][EVENT_END] = {
146         /* Timeout,   Input */
147         { S_START,    S_START    }, /* S_START */
148         { S_LCDDIM,   S_NORMAL   }, /* S_NORMAL */
149         { S_LCDOFF,   S_NORMAL   }, /* S_LCDDIM */
150         { S_SLEEP,    S_NORMAL   }, /* S_LCDOFF */
151         { S_SLEEP,    S_STANDBY  }, /* S_STANDBY */
152         { S_LCDOFF,   S_NORMAL   }, /* S_SLEEP */
153         { S_POWEROFF, S_POWEROFF }, /* S_POWEROFF */
154 };
155
156 #define SHIFT_UNLOCK            4
157 #define SHIFT_CHANGE_STATE      7
158 #define CHANGE_STATE_BIT        0xF00   /* 1111 0000 0000 */
159 #define SHIFT_LOCK_FLAG 16
160 #define SHIFT_CHANGE_TIMEOUT    20
161 #define CUSTOM_TIMEOUT_BIT      0x1
162 #define CUSTOM_HOLDKEY_BIT      0x2
163 #define HOLD_KEY_BLOCK_BIT      0x1
164 #define TIMEOUT_NONE            (-1)
165
166 #define S_COVER_TIMEOUT                 8000
167 #define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_LOCK_FLAG) & HOLD_KEY_BLOCK_BIT)
168 #define DELAYED_INIT_WATING_TIME        60000   /* 1 minute */
169
170 #define LOCK_SCREEN_WATING_TIME         300     /* 0.3 second */
171 #define LONG_PRESS_INTERVAL             400       /* 0.4 seconds */
172 #define SAMPLING_INTERVAL               1       /* 1 sec */
173 #define BRIGHTNESS_CHANGE_STEP          10
174 #define LCD_ALWAYS_ON                   0
175 #define ACCEL_SENSOR_ON                 1
176 #define CONTINUOUS_SAMPLING             1
177 #define LCDOFF_TIMEOUT                  300     /* milli second */
178
179 #define DIFF_TIMEVAL_MS(a, b) \
180         (((a.tv_sec * 1000000 + a.tv_usec) - \
181         (b.tv_sec * 1000000 + b.tv_usec)) \
182         / 1000)
183
184 static struct display_config display_conf = {
185         .lock_wait_time         = LOCK_SCREEN_WATING_TIME,
186         .longpress_interval     = LONG_PRESS_INTERVAL,
187         .lightsensor_interval   = SAMPLING_INTERVAL,
188         .lcdoff_timeout         = LCDOFF_TIMEOUT,
189         .pm_default_brightness = 80,
190         .brightness_change_step = BRIGHTNESS_CHANGE_STEP,
191         .lcd_always_on          = LCD_ALWAYS_ON,
192         .dimming                = 1,
193         .framerate_app          = {0, 0, 0, 0},
194         .control_display        = 0,
195         .powerkey_doublepress   = 0,
196         .accel_sensor_on        = ACCEL_SENSOR_ON,
197         .continuous_sampling    = CONTINUOUS_SAMPLING,
198         .timeout_enable         = true,
199         .input_support          = true,
200         .lockcheck_timeout      = 600,
201         .display_init_direction = DISPLAY_INIT_DIRECTION_HORIZONTAL,
202         .aod_enter_level        = 40,
203         .aod_tsp                = true,
204         .touch_wakeup           = false,
205         .display_on_usb_conn_changed = true,
206         .display_dpms_type      = DISPLAY_DPMS_TYPE_WINDOW_MANAGER,
207 };
208
209 struct display_function_info display_info = {
210         .update_auto_brightness         = NULL,
211         .set_autobrightness_min         = NULL,
212         .reset_autobrightness_min       = NULL,
213         .face_detection                 = NULL,
214 };
215
216 inline const struct display_config* get_var_display_config()
217 {
218         return &display_conf;
219 }
220
221 inline struct state* state_st(enum state_t state)
222 {
223         return &states[state];
224 }
225
226 guint get_transition_timer(void)
227 {
228         return timeout_src_id;
229 }
230
231 void change_state_action(enum state_t state, int (*func)(int timeout))
232 {
233         _I("[%s] 'action' is changed.", states[state].name);
234         states[state].action = func;
235 }
236
237 void change_state_trans(enum state_t state, int (*func)(int evt))
238 {
239         _I("[%s] 'trans' is changed.", states[state].name);
240         states[state].trans = func;
241 }
242
243 void change_state_check(enum state_t state, int (*func)(int curr, int next))
244 {
245         _I("[%s] 'check' is changed.", states[state].name);
246         states[state].check = func;
247 }
248
249 void change_state_name(enum state_t state, const char *name)
250 {
251         _I("[%s] 'name' is changed.", states[state].name);
252         states[state].name = name;
253 }
254
255 void change_trans_table(enum state_t state, enum state_t next)
256 {
257         _I("[%s] 'timeout trans table' is changed.", states[state].name);
258         trans_table[state][EVENT_TIMEOUT] = next;
259 }
260
261 void change_proc_change_state(int (*func)(unsigned int cond, pid_t pid))
262 {
263         _I("'proc change state' is changed.");
264         proc_change_state = func;
265 }
266
267 static int display_brightness_changed(void *data)
268 {
269         int brt, ret;
270
271         brt = DATA_VALUE_INT(data);
272
273         ret = gdbus_signal_emit(NULL,
274                                                         DEVICED_PATH_DISPLAY,
275                                                         DEVICED_INTERFACE_DISPLAY,
276                                                         "Brightness",
277                                                         g_variant_new("(i)", brt));
278         if (ret < 0)
279                 _E("Failed to send dbus signal Brightness.");
280
281         return 0;
282 }
283
284 static int display_auto_brightness_sensing(void *data)
285 {
286         if (!transit_timer)
287                 return 0;
288
289         g_source_remove(transit_timer);
290         transit_timer = 0;
291
292         return 0;
293 }
294
295 static const char* __device_flags_to_string(enum device_flags flags)
296 {
297
298         if (flags & (LCD_ON_BY_GESTURE | LCD_OFF_BY_GESTURE))
299                 return GESTURE_STR;
300         else if (flags & (LCD_ON_BY_POWER_KEY | LCD_OFF_BY_POWER_KEY))
301                 return POWER_KEY_STR;
302         else if (flags & (LCD_ON_BY_EVENT | LCD_OFF_BY_EVENT))
303                 return EVENT_STR;
304         else if (flags & LCD_ON_BY_TOUCH)
305                 return TOUCH_STR;
306         else if (flags & LCD_OFF_BY_TIMEOUT)
307                 return TIMEOUT_STR;
308         else if (flags & LCD_OFF_BY_PROXIMITY)
309                 return PROXI_STR;
310         else if (flags & LCD_OFF_BY_PALM)
311                 return PALM_STR;
312         else
313                 return UNKNOWN_STR;
314 }
315
316 static unsigned long get_lcd_on_flags(void)
317 {
318         unsigned long flags = NORMAL_MODE;
319
320         if (lcd_paneloff_mode)
321                 flags |= LCD_PANEL_OFF_MODE;
322
323         if (ambient_get_condition() == true) {
324                 flags |= AMBIENT_MODE;
325                 flags |= LCD_PHASED_TRANSIT_MODE;
326         }
327
328         return flags;
329 }
330
331 bool touch_event_blocked(void)
332 {
333         return touch_blocked;
334 }
335
336 static gboolean late_transit_on(void *data)
337 {
338         if (!transit_timer)
339                 return G_SOURCE_REMOVE;
340
341         g_source_remove(transit_timer);
342         transit_timer = 0;
343
344         backlight_ops->transit_state(DPMS_ON);
345         return G_SOURCE_REMOVE;
346 }
347
348 void lcd_on_procedure(int state, enum device_flags flag)
349 {
350         GList *l = NULL;
351         const struct device_ops *ops = NULL;
352         unsigned long flags = get_lcd_on_flags();
353         enum hal_device_power_transition_reason reason;
354         flags |= flag;
355
356         /*
357          * Display on procedure
358          * step 1. change power state to normal
359          * step 2. leave doze
360          * step 3. broadcast lcd on signal with cause
361          * step 4. set brightness
362          * step 5. set pmstate of vconf
363          * step 6. display on operate
364          *  - a. display on
365          *  - b. TSP(touch screen) and touchkey enable
366          * step 7. broadcast lcd on complete signal
367          * step 8. key backlight enable
368          */
369
370         if (flags & LCD_ON_BY_POWER_KEY)
371                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_POWER_KEY;
372         else if (flags & LCD_ON_BY_TOUCH)
373                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_TOUCH_SCREEN;
374         else
375                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN;
376
377         power_request_change_state_strict(DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL, reason, NULL);
378         leave_doze();
379
380         _I("[lcdstep] 0x%lx", flags);
381
382         if (flags & AMBIENT_MODE) {
383                 if (ambient_get_state() == false && backlight_ops->get_lcd_power() == DPMS_ON)
384                         return;
385                 ambient_set_state(false);
386         }
387
388         /* send LCDOn dbus signal */
389         if (!lcdon_broadcast)
390                 broadcast_lcd_on(SIGNAL_PRE, flags);
391
392         if (!(flags & LCD_PHASED_TRANSIT_MODE)) {
393                 /* Update brightness level */
394                 if (state == LCD_DIM)
395                         backlight_ops->dim();
396                 else if (state == LCD_NORMAL)
397                         backlight_ops->update();
398         }
399
400         if (state == LCD_NORMAL)
401                 set_setting_pmstate(S_NORMAL);
402         else if (state == LCD_DIM)
403                 set_setting_pmstate(S_LCDDIM);
404
405         SYS_G_LIST_FOREACH(lcdon_ops, l, ops)
406                 ops->start(flags);
407
408         if (!lcdon_broadcast) {
409         broadcast_lcd_on(SIGNAL_POST, flags);
410                 if (flags & LCD_PHASED_TRANSIT_MODE)
411                         transit_timer = g_timeout_add_seconds(LATE_LCD_TRANSIT,
412                                         late_transit_on, NULL);
413                 lcdon_broadcast = true;
414         }
415
416         if (CHECK_OPS(keyfilter_ops, backlight_enable))
417                 keyfilter_ops->backlight_enable(true);
418
419         touch_blocked = false;
420 }
421
422 static unsigned long get_lcd_off_flags(void)
423 {
424         unsigned long flags = NORMAL_MODE;
425
426         if (ambient_get_condition() == true) {
427                 flags |= AMBIENT_MODE;
428                 flags |= LCD_PHASED_TRANSIT_MODE;
429         }
430
431         if (stay_touchscreen_off)
432                 flags |= TOUCH_SCREEN_OFF_MODE;
433
434         return flags;
435 }
436
437 inline void lcd_off_procedure(enum device_flags flag)
438 {
439         GList *l = NULL;
440         const struct device_ops *ops = NULL;
441         unsigned long flags = get_lcd_off_flags();
442         flags |= flag;
443
444         /*
445          * Display off procedure
446          * step 0. enhance mode off using nofity (e.g mdnie, HBM, LBM)
447          * step 1. broadcast lcd off signal with cause
448          * step 2. set pmstate of vconf
449          * step 3. display off operate
450          *  - a. display off
451          *  - b. TSP(touch screen) and touchkey disable
452          * step 4. broadcast lcd off complete siganl
453          * step 5. enter doze mode if it is enabled
454          */
455         _I("[lcdstep] 0x%lx", flags);
456
457         /* notification */
458
459         device_notify(DEVICE_NOTIFIER_LCD_OFF, NULL);
460
461         if (lcdon_broadcast) {
462                 broadcast_lcd_off(SIGNAL_PRE, flags);
463                 lcdon_broadcast = false;
464         }
465
466         /* operation */
467
468         touch_blocked = true;
469
470         set_setting_pmstate(S_LCDOFF);
471
472         if (CHECK_OPS(keyfilter_ops, backlight_enable))
473                 keyfilter_ops->backlight_enable(false);
474
475         if (transit_timer) {
476                 g_source_remove(transit_timer);
477                 transit_timer = 0;
478         }
479
480         if (flags & LCD_PHASED_TRANSIT_MODE)
481                 backlight_ops->transit_state(DPMS_OFF);
482
483         SYS_G_LIST_FOREACH(lcdon_ops, l, ops)
484                 ops->stop(flags);
485
486         if (flags & AMBIENT_MODE) {
487                 broadcast_lcd_off_late(flags);
488         } else {
489                 broadcast_lcd_off(SIGNAL_POST, flags);
490                 device_notify(DEVICE_NOTIFIER_LCD_OFF_COMPLETE, NULL);
491         }
492
493         enter_doze();
494 }
495
496 void set_stay_touchscreen_off(int val)
497 {
498         _I("Stay touch screen off: %d", val);
499         stay_touchscreen_off = val;
500
501         if (disp_plgn->pm_change_internal)
502                 disp_plgn->pm_change_internal(INTERNAL_LOCK_PM, LCD_NORMAL);
503 }
504
505 void set_lcd_paneloff_mode(int val)
506 {
507         _I("Lcd paneloff mode: %d", val);
508         lcd_paneloff_mode = val;
509
510         if (disp_plgn->pm_change_internal)
511                 disp_plgn->pm_change_internal(INTERNAL_LOCK_PM, LCD_NORMAL);
512 }
513
514 int low_battery_state(int val)
515 {
516         switch (val) {
517         case VCONFKEY_SYSMAN_BAT_POWER_OFF:
518         case VCONFKEY_SYSMAN_BAT_CRITICAL_LOW:
519         case VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF:
520                 return true;
521         }
522         return false;
523 }
524
525 int get_hallic_open(void)
526 {
527         return hallic_open;
528 }
529
530 void get_pname(pid_t pid, char *pname)
531 {
532         char buf[PATH_MAX];
533         int cmdline, r;
534
535         if (pid >= INTERNAL_LOCK_BASE)
536                 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", getpid());
537         else
538                 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
539
540         cmdline = open(buf, O_RDONLY);
541         if (cmdline < 0) {
542                 pname[0] = '\0';
543                 _E("Process(%d) does not exist now(may be dead without unlock).", pid);
544                 return;
545         }
546
547         r = read(cmdline, pname, PATH_MAX);
548         if ((r >= 0) && (r < PATH_MAX))
549                 pname[r] = '\0';
550         else
551                 pname[0] = '\0';
552
553         close(cmdline);
554 }
555
556 static void del_state_cond(void *data, enum state_t state)
557 {
558         PmLockNode *tmp = NULL;
559         pid_t pid;
560
561         if (!data)
562                 return;
563
564         /* A passed data is a pid_t type data, not a 64bit data. */
565         pid = (pid_t)((intptr_t)data);
566         _I("delete prohibit %s condition by timeout (%d)", states[state].name, pid);
567
568         if (pid == INTERNAL_LOCK_AMBIENT)
569                 ambient_check_invalid_state(pid);
570
571         tmp = find_node(state, pid);
572         del_node(state, tmp);
573         set_unlock_time(pid, state);
574
575         /* Change state only when the two conditions below are satisfied.
576          *   1. There should be no running state-transition timer
577          *   2. Released lock is one of the pm_cur_state's lock
578          * This emulates already expired transition timer */
579         if (!timeout_src_id && get_pm_cur_state() == state)
580                 states[get_pm_cur_state()].trans(EVENT_TIMEOUT);
581
582         if (state == S_LCDOFF)
583                 set_process_active(false, pid);
584 }
585
586 static gboolean del_normal_cond(void *data)
587 {
588         del_state_cond(data, S_NORMAL);
589         return G_SOURCE_REMOVE;
590 }
591
592 static gboolean del_dim_cond(void *data)
593 {
594         del_state_cond(data, S_LCDDIM);
595         return G_SOURCE_REMOVE;
596 }
597
598 static gboolean del_off_cond(void *data)
599 {
600         del_state_cond(data, S_LCDOFF);
601         return G_SOURCE_REMOVE;
602 }
603
604 /* timeout handler  */
605 gboolean timeout_handler(void *data)
606 {
607         _I("Time out state %s", states[get_pm_cur_state()].name);
608
609         if (timeout_src_id) {
610                 g_source_remove(timeout_src_id);
611                 timeout_src_id = 0;
612         }
613
614         states[get_pm_cur_state()].trans(EVENT_TIMEOUT);
615         return G_SOURCE_REMOVE;
616 }
617
618 void reset_timeout(int timeout)
619 {
620         if (!display_conf.timeout_enable)
621                 return;
622
623         if ((get_pm_cur_state() == S_LCDOFF)
624         && (is_emulator() == true || timeout_sleep_support == false))
625                 return;
626
627         _I("Reset timeout(%d ms).", timeout);
628         if (timeout_src_id != 0) {
629                 g_source_remove(timeout_src_id);
630                 timeout_src_id = 0;
631         }
632
633         if (trans_table[get_pm_cur_state()][EVENT_TIMEOUT] == get_pm_cur_state())
634                 return;
635
636         if (timeout > 0)
637                 timeout_src_id = g_timeout_add(timeout,
638                     timeout_handler, NULL);
639         else if (timeout == 0)
640                 states[get_pm_cur_state()].trans(EVENT_TIMEOUT);
641 }
642
643 /* get configurations from setting */
644 static int get_lcd_timeout_from_settings(void)
645 {
646         int i;
647         int val = 0;
648
649         for (i = 0; i < S_END; i++) {
650                 switch (states[i].state) {
651                 case S_NORMAL:
652                         get_run_timeout(&val);
653                         break;
654                 case S_LCDDIM:
655                         get_dim_timeout(&val);
656                         break;
657                 case S_LCDOFF:
658                         val = display_conf.lcdoff_timeout;
659                         break;
660                 default:
661                         /* This state doesn't need to set time out. */
662                         val = 0;
663                         break;
664                 }
665                 if (val > 0)
666                         states[i].timeout = val;
667
668                 _I("State(%s) timeout(%d) ms", states[i].name,
669                         states[i].timeout);
670         }
671
672         return 0;
673 }
674
675 static void update_display_time(void)
676 {
677         int run_timeout, val;
678
679         /* first priority : s cover */
680         if (!hallic_open) {
681                 states[S_NORMAL].timeout = S_COVER_TIMEOUT;
682                 _I("S cover closed: Timeout(%d ms) is set by normal.",
683                     S_COVER_TIMEOUT);
684                 return;
685         }
686
687         /* second priority : custom timeout */
688         if (custom_normal_timeout > 0) {
689                 states[S_NORMAL].timeout = custom_normal_timeout;
690                 states[S_LCDDIM].timeout = custom_dim_timeout;
691                 _I("CUSTOM : timeout is set by normal(%d ms), dim(%d ms)",
692                     custom_normal_timeout, custom_dim_timeout);
693                 return;
694         }
695
696         /* third priority : lock state */
697         if ((__get_lock_screen_state() == VCONFKEY_IDLE_LOCK) &&
698             !get_lock_screen_bg_state()) {
699                 /* timeout is different according to key or event. */
700                 states[S_NORMAL].timeout = lock_screen_timeout;
701                 _I("LOCK: Timeout(%d ms) is set by normal.",
702                     lock_screen_timeout);
703                 return;
704         }
705
706         /* default setting */
707         get_run_timeout(&run_timeout);
708
709         /* for sdk
710          * if the run_timeout is zero, it regards AlwaysOn state
711          */
712         if (run_timeout == 0 || display_conf.lcd_always_on) {
713                 run_timeout = ALWAYS_ON_TIMEOUT;
714                 _I("LCD always on.");
715         }
716
717         states[S_NORMAL].timeout = run_timeout;
718
719         get_dim_timeout(&val);
720         states[S_LCDDIM].timeout = val;
721
722         _I("Normal: NORMAL timeout is set by %d ms", states[S_NORMAL].timeout);
723         _I("Normal: DIM timeout is set by %d ms", states[S_LCDDIM].timeout);
724 }
725
726 static void update_display_locktime(int time)
727 {
728         lock_screen_timeout = time;
729         update_display_time();
730 }
731
732 void set_dim_state(bool on)
733 {
734         _I("Dim state is %d.", on);
735         update_display_time();
736         states[get_pm_cur_state()].trans(EVENT_INPUT);
737 }
738
739 void lcd_on_direct(enum device_flags flags)
740 {
741         set_pm_cur_state(S_NORMAL);
742
743         _D("lcd is on directly");
744         gettimeofday(&lcdon_tv, NULL);
745         lcd_on_procedure(LCD_NORMAL, flags);
746
747         update_display_locktime(LOCK_SCREEN_INPUT_TIMEOUT);
748 }
749
750 static inline bool check_lcd_is_on(void)
751 {
752         if (backlight_ops->get_lcd_power() != DPMS_ON)
753                 return false;
754
755         return true;
756 }
757
758 static gboolean timer_refresh_cb(gpointer data)
759 {
760         struct state *st;
761
762         /* state transition */
763         set_pm_old_state(get_pm_cur_state());
764         set_pm_cur_state(S_NORMAL);
765         st = &states[get_pm_cur_state()];
766
767         if (st->action)
768                 st->action(st->timeout);
769
770         return 0;
771 }
772
773 int custom_lcdon(int timeout)
774 {
775         struct state *st;
776
777         if (timeout <= 0)
778                 return -EINVAL;
779
780         if (check_lcd_is_on() == false)
781                 lcd_on_direct(LCD_ON_BY_GESTURE);
782
783         _I("Custom lcd on timeout(%d ms).", timeout);
784         if (set_custom_lcdon_timeout(timeout) == true)
785                 update_display_time();
786
787         /* state transition */
788         set_pm_old_state(get_pm_cur_state());
789         set_pm_cur_state(S_NORMAL);
790         st = &states[get_pm_cur_state()];
791
792         /* enter action */
793         if (st->action)
794                 st->action(st->timeout);
795
796         g_idle_add(timer_refresh_cb, NULL);
797
798         return 0;
799 }
800
801 int custom_lcdoff(enum device_flags flag)
802 {
803         struct state *st;
804
805         check_processes(S_NORMAL);
806         check_processes(S_LCDDIM);
807
808         /* check holdkey block flag in lock node */
809         if (check_lock_condition(S_NORMAL) || check_lock_condition(S_LCDDIM)) {
810                 /*
811                  * When another proccess is normal lock, device is received call then,
812                  * call app can be changed to lcd state by proximity.
813                  * If proximity is near then normal lock will be unlocked.
814                  */
815                 if (flag & LCD_OFF_BY_PROXIMITY) {
816                         _I("custom lcd off by proximity, delete normal lock");
817                         delete_condition(S_NORMAL);
818                 } else {
819                         _I("skip custom lcd off");
820                         return -ECANCELED;
821                 }
822         }
823
824         _I("custom lcd off by flag(%d)", flag);
825         if (backlight_ops->get_lcd_power() == DPMS_ON)
826                 lcd_off_procedure(flag);
827
828         if (set_custom_lcdon_timeout(0) == true)
829                 update_display_time();
830
831         /* state transition */
832         set_pm_old_state(get_pm_cur_state());
833         set_pm_cur_state(S_LCDOFF);
834         st = &states[get_pm_cur_state()];
835
836         /* enter action */
837         if (st->action)
838                 st->action(st->timeout);
839
840         return 0;
841 }
842
843 int display_on_by_reason(const char *reason, int timeout)
844 {
845         struct state *st;
846         int flag;
847         int str_len;
848
849         str_len = strlen(reason);
850
851         if (!strncmp(reason, GESTURE_STR, str_len))
852                 flag = LCD_ON_BY_GESTURE;
853         else if (!strncmp(reason, EVENT_STR, str_len))
854                 flag = LCD_ON_BY_EVENT;
855         else {
856                 _E("Reason is unknown(%s)", reason);
857                 return -EINVAL;
858         }
859
860         if (timeout <= 0) {
861                 _E("Cannot setting timeout %d", timeout);
862                 return -EINVAL;
863         }
864
865         if (check_lcd_is_on() == false)
866                 lcd_on_direct(flag);
867
868         _I("platform lcd on by %s (%d ms)", reason, timeout);
869         if (set_custom_lcdon_timeout(timeout) == true)
870                 update_display_time();
871
872         /* state transition */
873         set_pm_old_state(get_pm_cur_state());
874         set_pm_cur_state(S_NORMAL);
875         st = &states[get_pm_cur_state()];
876
877         /* enter action */
878         if (st->action)
879                 st->action(st->timeout);
880
881         return 0;
882 }
883
884 int display_off_by_reason(const char *reason)
885 {
886         struct state *st;
887         int flag;
888         int str_len;
889
890         str_len = strlen(reason);
891
892         if (!strncmp(reason, GESTURE_STR, str_len)) {
893                 check_processes(S_NORMAL);
894                 check_processes(S_LCDDIM);
895
896                 /* check holdkey block flag in lock node */
897                 if (check_lock_condition(S_NORMAL) || check_lock_condition(S_LCDDIM)) {
898                         _I("skip platform lcd off by gesture");
899                         return -ECANCELED;
900                 }
901                 flag = LCD_OFF_BY_GESTURE;
902         } else if (!strncmp(reason, PALM_STR, str_len)) {
903                 delete_condition(S_NORMAL);
904                 delete_condition(S_LCDDIM);
905
906                 flag = LCD_OFF_BY_PALM;
907         } else {
908                 _E("Reason is unknown(%s)", reason);
909                 return -EINVAL;
910         }
911
912         _I("platform lcd off by %s", reason);
913         if (backlight_ops->get_lcd_power() == DPMS_ON)
914                 lcd_off_procedure(flag);
915
916         /* state transition */
917         set_pm_old_state(get_pm_cur_state());
918         set_pm_cur_state(S_LCDOFF);
919         st = &states[get_pm_cur_state()];
920
921         /* enter action */
922         if (st->action)
923                 st->action(st->timeout);
924
925         return 0;
926 }
927
928 static void default_proc_change_state_action(enum state_t next, int timeout)
929 {
930         struct state *st;
931
932         set_pm_old_state(get_pm_cur_state());
933         set_pm_cur_state(next);
934
935         st = &states[get_pm_cur_state()];
936
937         if (st && st->action) {
938                 if (timeout < 0)
939                         st->action(st->timeout);
940                 else
941                         st->action(timeout);
942         }
943 }
944
945 static int default_proc_change_state(unsigned int cond, pid_t pid)
946 {
947         enum state_t next;
948
949         next = GET_COND_STATE(cond);
950         _I("Change process(%d) state to %s.", pid, states[next].name);
951
952         switch (next) {
953         case S_NORMAL:
954                 if (check_lcd_is_on() == false)
955                         lcd_on_direct(LCD_ON_BY_EVENT);
956                 update_display_locktime(LOCK_SCREEN_CONTROL_TIMEOUT);
957                 default_proc_change_state_action(next, -1);
958                 break;
959         case S_LCDDIM:
960                 default_proc_change_state_action(next, -1);
961                 break;
962         case S_LCDOFF:
963                 if (backlight_ops->get_lcd_power() == DPMS_ON) {
964                         if (get_proximity_state() == SENSOR_PROXIMITY_NEAR)
965                                 lcd_off_procedure(LCD_OFF_BY_PROXIMITY);
966                         else
967                         lcd_off_procedure(LCD_OFF_BY_EVENT);
968                 }
969                 if (set_custom_lcdon_timeout(0))
970                         update_display_time();
971                 default_proc_change_state_action(next, -1);
972                 break;
973         case S_SLEEP:
974                 _I("Dangerous requests.");
975                 /* at first LCD_OFF and then goto sleep */
976                 /* state transition */
977                 default_proc_change_state_action(S_LCDOFF, TIMEOUT_NONE);
978                 delete_condition(S_NORMAL);
979                 delete_condition(S_LCDDIM);
980                 delete_condition(S_LCDOFF);
981                 if (lcdon_broadcast) {
982                         _I("broadcast lcd off signal at non-lcd device");
983                         broadcast_lcd_off(SIGNAL_PRE, 0);
984                         broadcast_lcd_off(SIGNAL_POST, 0);
985                 }
986                 default_proc_change_state_action(S_SLEEP, TIMEOUT_NONE);
987                 break;
988
989         default:
990                 return -EINVAL;
991         }
992
993         return 0;
994 }
995
996 static void proc_condition_lock(PMMsg *data)
997 {
998         PmLockNode *tmp;
999         guint cond_timeout_id = 0;
1000         char pname[PATH_MAX];
1001         pid_t pid = data->pid;
1002         enum state_t state;
1003         int holdkey_block, ret;
1004         bool value = true;
1005         unsigned int flags;
1006         const char *lock_type = NULL;
1007
1008         state = GET_COND_STATE(data->cond);
1009         if (state == S_START)
1010                 return;
1011
1012         flags = GET_COND_FLAG(data->cond);
1013         get_pname(pid, pname);
1014
1015         if ((state == S_LCDOFF) && (get_pm_cur_state() == S_SLEEP) &&
1016             (pm_get_power_lock() == POWER_UNLOCK)) {
1017                 /**
1018                  * To escape from display state S_SLEEP,
1019                  * it must precede that change power state from SLEEP to NORAML
1020                  */
1021                 power_request_change_state_strict(DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL, 0, NULL);
1022                 proc_change_state(data->cond, INTERNAL_LOCK_PM);
1023         }
1024
1025         if (data->timeout > 0) {
1026                 /* To pass a pid_t data through the timer infrastructure
1027                  * without memory allocation, a pid_t data becomes typecast
1028                  * to intptr_t and void *(64bit) type. */
1029                 cond_timeout_id = g_timeout_add(
1030                                 data->timeout,
1031                                 states[state].timeout_cb,
1032                                 (void*)((intptr_t)pid));
1033                 if (!cond_timeout_id)
1034                         _E("Failed to register display timer.");
1035         }
1036
1037         holdkey_block = GET_COND_FLAG(data->cond) & PM_FLAG_BLOCK_HOLDKEY;
1038
1039         tmp = find_node(state, pid);
1040         if (!tmp) {
1041                 tmp = add_node(state, pid, cond_timeout_id, holdkey_block);
1042                 if (!tmp) {
1043                         _E("Failed to acquire lock, state: %d, pid: %d.", state, pid);
1044                         return;
1045                 }
1046         } else {
1047                 update_lock_timer(data, tmp, cond_timeout_id);
1048                 tmp->holdkey_block = holdkey_block;
1049         }
1050
1051         if (state == S_LCDOFF)
1052                 set_process_active(true, pid);
1053
1054         _I("[%s] locked by %5d with %u ms", states[state].name, pid, data->timeout);
1055
1056         if (pid < INTERNAL_LOCK_BASE) {
1057                 /* for debug */
1058                 if (state == S_LCDOFF)
1059                         lock_type = PM_LCDOFF_STR;
1060                 else if (state == S_LCDDIM)
1061                         lock_type = PM_LCDDIM_STR;
1062                 else if (state == S_NORMAL)
1063                         lock_type = PM_LCDON_STR;
1064
1065                 if (lock_type) {
1066                         /* power lock signal */
1067                         ret = gdbus_signal_emit(NULL,
1068                                         DEVICED_PATH_DISPLAY,
1069                                         DEVICED_INTERFACE_DISPLAY,
1070                                         "PowerLock",
1071                                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
1072                         if (ret < 0)
1073                                 _E("Failed to send dbus signal PowerLock.");
1074                 }
1075         }
1076         _SD("be requested LOCK info pname(%s), holdkeyblock(%d) flags(%d)",
1077             pname, holdkey_block, flags);
1078         set_lock_time(pid, pname, state);
1079
1080         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
1081 }
1082
1083 static void proc_condition_unlock(PMMsg *data)
1084 {
1085         pid_t pid = data->pid;
1086         enum state_t state;
1087         PmLockNode *tmp;
1088         char pname[PATH_MAX];
1089         bool value = false;
1090         unsigned int flags;
1091         int ret;
1092         const char *lock_type = NULL;
1093
1094         state = GET_COND_STATE(data->cond);
1095         if (!state)
1096                 return;
1097
1098         flags = GET_COND_FLAG(data->cond);
1099         get_pname(pid, pname);
1100
1101         tmp = find_node(state, pid);
1102         del_node(state, tmp);
1103
1104         if (state == S_LCDOFF)
1105                 set_process_active(false, pid);
1106
1107         _I("[%s] unlocked by %5d", states[state].name, pid);
1108
1109         if (pid < INTERNAL_LOCK_BASE) {
1110                 /* for debug */
1111                 if (state == S_LCDOFF)
1112                         lock_type =  PM_LCDOFF_STR;
1113                 else if (state == S_LCDDIM)
1114                         lock_type = PM_LCDDIM_STR;
1115                 else if (state == S_NORMAL)
1116                         lock_type = PM_LCDON_STR;
1117
1118                 if (lock_type) {
1119                         /* power unlock signal */
1120                         ret = gdbus_signal_emit(NULL,
1121                                         DEVICED_PATH_DISPLAY,
1122                                         DEVICED_INTERFACE_DISPLAY,
1123                                         "PowerUnlock",
1124                                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
1125                         if (ret < 0)
1126                                 _E("Failed to send dbus signal PowerUnlock.");
1127                 }
1128         }
1129
1130         _SD("be requested UNLOCK info pname(%s) flag(%d)", pname, flags);
1131         set_unlock_time(pid, state);
1132
1133         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
1134 }
1135
1136 static int proc_condition(PMMsg *data)
1137 {
1138         unsigned int flags;
1139
1140         if (IS_COND_REQUEST_LOCK(data->cond))
1141                 proc_condition_lock(data);
1142
1143         if (IS_COND_REQUEST_UNLOCK(data->cond))
1144                 proc_condition_unlock(data);
1145
1146         if (!display_conf.timeout_enable)
1147                 return 0;
1148
1149         flags = GET_COND_FLAG(data->cond);
1150         if (flags == 0) {
1151                 /* guard time for suspend */
1152                 if (get_pm_cur_state() == S_LCDOFF)
1153                         reset_timeout(states[S_LCDOFF].timeout);
1154         } else {
1155                 if (flags & PM_FLAG_RESET_TIMER)
1156                         reset_timeout(states[get_pm_cur_state()].timeout);
1157         }
1158
1159         if (!timeout_src_id)
1160                 states[get_pm_cur_state()].trans(EVENT_TIMEOUT);
1161
1162         return 0;
1163 }
1164
1165 void update_lcdoff_source(int source)
1166 {
1167         int ret;
1168
1169         switch (source) {
1170         case VCONFKEY_PM_LCDOFF_BY_TIMEOUT:
1171                 _I("LCD OFF by timeout.");
1172                 break;
1173         case VCONFKEY_PM_LCDOFF_BY_POWERKEY:
1174                 _I("LCD OFF by powerkey.");
1175                 break;
1176         default:
1177                 _E("Invalid value(%d).", source);
1178                 return;
1179         }
1180         ret = vconf_set_int(VCONFKEY_PM_LCDOFF_SOURCE, source);
1181         if (ret < 0)
1182                 _E("Failed to set vconf value for lcd off source: %d", vconf_get_ext_errno());
1183 }
1184
1185 void print_info(int fd)
1186 {
1187         int s_index = 0;
1188         char buf[PATH_MAX + 255];
1189         int i = 1;
1190         int ret;
1191         char pname[PATH_MAX];
1192         PmLockNode *t;
1193         GList *elem;
1194         char time_buf[30];
1195
1196         if (fd < 0)
1197                 return;
1198
1199         snprintf(buf, sizeof(buf),
1200                 "\n==========================================="
1201                 "===========================\n");
1202         ret = write(fd, buf, strlen(buf));
1203         if (ret < 0)
1204                 _E("Write() failed: %d", errno);
1205         snprintf(buf, sizeof(buf), "Timeout Info: Run[%dms] Dim[%dms] Off[%dms]\n",
1206                  states[S_NORMAL].timeout,
1207                  states[S_LCDDIM].timeout, states[S_LCDOFF].timeout);
1208         ret = write(fd, buf, strlen(buf));
1209         if (ret < 0)
1210                 _E("Write() failed: %d", errno);
1211
1212         snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n",
1213                  (get_trans_condition() & MASK_NORMAL) ? states[S_NORMAL].name : "-",
1214                  (get_trans_condition() & MASK_DIM) ? states[S_LCDDIM].name : "-",
1215                  (get_trans_condition() & MASK_OFF) ? states[S_LCDOFF].name : "-");
1216         ret = write(fd, buf, strlen(buf));
1217         if (ret < 0)
1218                 _E("Write() failed: %d", errno);
1219
1220         snprintf(buf, sizeof(buf), "Current State: %s\n",
1221                 states[get_pm_cur_state()].name);
1222         ret = write(fd, buf, strlen(buf));
1223         if (ret < 0)
1224                 _E("Write() failed: %d", errno);
1225
1226         snprintf(buf, sizeof(buf), "Current Lock Conditions: \n");
1227         ret = write(fd, buf, strlen(buf));
1228         if (ret < 0)
1229                 _E("Write() failed: %d", errno);
1230
1231         for (s_index = S_NORMAL; s_index < S_END; s_index++) {
1232                 SYS_G_LIST_FOREACH(get_cond_head(s_index), elem, t) {
1233                         get_pname((pid_t)t->pid, pname);
1234                         ctime_r(&t->time, time_buf);
1235                         time_buf[strlen(time_buf) - 1] = 0;
1236                         snprintf(buf, sizeof(buf),
1237                                  " %d: [%s] locked by pid %d %s %s\n",
1238                                  i++, states[s_index].name, t->pid, pname, time_buf);
1239                         ret = write(fd, buf, strlen(buf));
1240                         if (ret < 0)
1241                                 _E("Write() failed: %d", errno);
1242                 }
1243         }
1244
1245         print_lock_info_list(fd);
1246
1247 #ifdef ENABLE_PM_LOG
1248         pm_history_print(fd, 250);
1249 #endif
1250 }
1251
1252 void save_display_log(const char *path)
1253 {
1254         int fd, ret;
1255         char buf[255];
1256         time_t now_time;
1257         char time_buf[30];
1258
1259         _D("internal state is saved!");
1260
1261         time(&now_time);
1262         ctime_r(&now_time, time_buf);
1263         time_buf[strlen(time_buf) - 1] = 0;
1264
1265         fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0644);
1266         if (fd != -1) {
1267                 snprintf(buf, sizeof(buf),
1268                         "\npm_state_log now-time : %d(s) %s\n\n",
1269                         (int)now_time, time_buf);
1270                 ret = write(fd, buf, strlen(buf));
1271                 if (ret < 0)
1272                         _E("write() failed (%d)", errno);
1273
1274                 snprintf(buf, sizeof(buf), "pm_status_flag: %#x\n", get_pm_status_flag());
1275                 ret = write(fd, buf, strlen(buf));
1276                 if (ret < 0)
1277                         _E("write() failed (%d)", errno);
1278
1279                 if (disp_plgn->get_lock_screen_state ) {
1280                         snprintf(buf, sizeof(buf), "screen lock status : %d\n",
1281                                 disp_plgn->get_lock_screen_state());
1282                         ret = write(fd, buf, strlen(buf));
1283                         if (ret < 0)
1284                                 _E("write() failed (%d)", errno);
1285                 }
1286                 print_info(fd);
1287                 close(fd);
1288         }
1289
1290         fd = open("/dev/console", O_WRONLY);
1291         if (fd != -1) {
1292                 print_info(fd);
1293                 close(fd);
1294         }
1295 }
1296
1297 /* SIGHUP signal handler
1298  * For debug... print info to syslog
1299  */
1300 static void sig_hup(int signo)
1301 {
1302         _I("received sig hub %d", signo);
1303
1304         pm_save_logdump();
1305 }
1306
1307 int check_lcdoff_direct(void)
1308 {
1309         int ret, lock, cradle;
1310         int hdmi_state;
1311
1312         if (get_pm_old_state() != S_NORMAL)
1313                 return false;
1314
1315         if (get_pm_cur_state() != S_LCDDIM)
1316                 return false;
1317
1318         if (!display_conf.dimming)
1319                 return true;
1320
1321         lock = __get_lock_screen_state();
1322         if (lock != VCONFKEY_IDLE_LOCK && hallic_open)
1323                 return false;
1324
1325         hdmi_state = extcon_get_status(EXTCON_CABLE_HDMI);
1326         if (hdmi_state)
1327                 return false;
1328
1329         ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle);
1330         if (ret >= 0 && cradle == DOCK_SOUND)
1331                 return false;
1332         else if (ret < 0)
1333                 _E("Failed to get vconf value for cradle status: %d", vconf_get_ext_errno());
1334
1335         _D("Goto LCDOFF direct: lock(%d) hdmi(%d) cradle(%d).", lock, hdmi_state, cradle);
1336
1337         return true;
1338 }
1339
1340 /*
1341  * default transition function
1342  *   1. call check
1343  *   2. transition
1344  *   3. call enter action function
1345  */
1346 static int default_trans(int evt)
1347 {
1348         struct state *st = &states[get_pm_cur_state()];
1349         int next_state;
1350
1351         next_state = (enum state_t)trans_table[get_pm_cur_state()][evt];
1352
1353         /* check conditions */
1354         if (st->check && !st->check(get_pm_cur_state(), next_state)) {
1355                 /* There is a condition. */
1356                 _I("%s locked. Trans to %s failed.", states[get_pm_cur_state()].name,
1357                        states[next_state].name);
1358                 return -1;
1359         }
1360
1361         /* state transition */
1362         set_pm_old_state(get_pm_cur_state());
1363         set_pm_cur_state(next_state);
1364         st = &states[get_pm_cur_state()];
1365
1366         /* enter action */
1367         if (st->action) {
1368                 if (get_pm_cur_state() == S_LCDOFF)
1369                         update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT);
1370
1371                 if ((get_pm_cur_state() == S_NORMAL) || (get_pm_cur_state() == S_LCDOFF))
1372                         if (set_custom_lcdon_timeout(0) == true)
1373                                 update_display_time();
1374
1375                 if (check_lcdoff_direct() == true) {
1376                         /* enter next state directly */
1377                         states[get_pm_cur_state()].trans(EVENT_TIMEOUT);
1378                 } else {
1379                         if ((get_pm_cur_state() == S_SLEEP)
1380                         && (is_emulator() == true || timeout_sleep_support == false))
1381                                 return 0;
1382
1383                         st->action(st->timeout);
1384                 }
1385         }
1386
1387         return 0;
1388 }
1389
1390 static gboolean lcd_on_expired(void *data)
1391 {
1392         int lock_state, ret;
1393
1394         if (lock_timeout_id)
1395                 lock_timeout_id = 0;
1396
1397         /* check state of lock */
1398         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1399         if (ret > 0 && lock_state == VCONFKEY_IDLE_LOCK)
1400                 return G_SOURCE_REMOVE;
1401         else if (ret < 0)
1402                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
1403
1404         /* lock screen is not launched yet, but lcd is on */
1405         if (check_lcd_is_on() == false)
1406                 lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
1407
1408         return G_SOURCE_REMOVE;
1409 }
1410
1411 static inline void stop_lock_timer(void)
1412 {
1413         if (lock_timeout_id) {
1414                 g_source_remove(lock_timeout_id);
1415                 lock_timeout_id = 0;
1416         }
1417 }
1418
1419 static void check_lock_screen(void)
1420 {
1421         int lock_state, ret;
1422
1423         stop_lock_timer();
1424
1425         /* check state of lock */
1426         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1427         if (ret < 0 || lock_state == VCONFKEY_IDLE_LOCK)
1428                 return;
1429
1430         /* Use time to check lock is done. */
1431         lock_timeout_id = g_timeout_add(display_conf.lock_wait_time,
1432             lcd_on_expired, NULL);
1433 }
1434
1435 /* default enter action function */
1436 static int default_action(int timeout)
1437 {
1438         int wakeup_count = -1, pm_cur_state;
1439         time_t now;
1440         double diff;
1441         static time_t last_update_time = 0;
1442         static int last_timeout = 0;
1443         struct timeval now_tv;
1444
1445         if (status != DEVICE_OPS_STATUS_START) {
1446                 _E("Display is not started.");
1447                 return -EINVAL;
1448         }
1449
1450         if (get_pm_cur_state() != S_SLEEP) {
1451                 if ((get_pm_cur_state() == S_NORMAL) &&
1452                     lcdon_tv.tv_sec != 0) {
1453                         gettimeofday(&now_tv, NULL);
1454                         timeout -= DIFF_TIMEVAL_MS(now_tv, lcdon_tv);
1455                         lcdon_tv.tv_sec = 0;
1456                 }
1457                 /* set timer with current state timeout */
1458                 reset_timeout(timeout);
1459
1460                 if (get_pm_cur_state() == S_NORMAL) {
1461                         time(&last_update_time);
1462                         last_timeout = timeout;
1463                 } else {
1464                         _I("Timout set: %s state %d ms",
1465                             states[get_pm_cur_state()].name, timeout);
1466                 }
1467         }
1468
1469         if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) {
1470                 set_setting_pmstate(get_pm_cur_state());
1471                 pm_cur_state = get_pm_cur_state();
1472                 device_notify(DEVICE_NOTIFIER_LCD, (void *)&pm_cur_state);
1473         }
1474
1475         if ((get_pm_old_state() == S_NORMAL) && (get_pm_cur_state() != S_NORMAL)) {
1476                 time(&now);
1477                 diff = difftime(now, last_update_time);
1478                 _I("S_NORMAL is changed to %s (timeout=%d ms diff=%.0f s).",
1479                     states[get_pm_cur_state()].name, last_timeout, diff);
1480         }
1481
1482         switch (get_pm_cur_state()) {
1483         case S_NORMAL:
1484                 /*
1485                  * normal state : backlight on and restore
1486                  * the previous brightness
1487                  */
1488                 if ((get_pm_old_state() == S_LCDOFF) || (get_pm_old_state() == S_SLEEP))
1489                         check_lock_screen();
1490                 else if (get_pm_old_state() == S_LCDDIM)
1491                         backlight_ops->update();
1492
1493                 if (check_lcd_is_on() == false)
1494                         lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
1495                 break;
1496
1497         case S_LCDDIM:
1498                 if ((get_pm_old_state() == S_NORMAL) &&
1499                     backlight_ops->get_custom_status())
1500                         backlight_ops->save_custom_brightness();
1501                 /* lcd dim state : dim the brightness */
1502                 backlight_ops->dim();
1503
1504                 if ((get_pm_old_state() == S_LCDOFF) || (get_pm_old_state() == S_SLEEP))
1505                         lcd_on_procedure(LCD_DIM, NORMAL_MODE);
1506                 break;
1507
1508         case S_LCDOFF:
1509                 if ((get_pm_old_state() != S_SLEEP) && (get_pm_old_state() != S_LCDOFF)) {
1510                         stop_lock_timer();
1511                         /* lcd off state : turn off the backlight */
1512                         if (backlight_ops->get_lcd_power() == DPMS_ON)
1513                                 lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
1514                 }
1515
1516                 if (backlight_ops->get_lcd_power() == DPMS_ON
1517                     || lcd_paneloff_mode)
1518                         lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
1519                 break;
1520
1521         case S_SLEEP:
1522                 if ((get_pm_old_state() != S_SLEEP) && (get_pm_old_state() != S_LCDOFF))
1523                         stop_lock_timer();
1524
1525                 if (backlight_ops->get_lcd_power() == DPMS_ON)
1526                         lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
1527
1528                 if (!pm_get_power_lock_support()) {
1529                         /* sleep state : set system mode to SUSPEND */
1530                         if (get_wakeup_count(&wakeup_count) < 0)
1531                                 _E("Wakeup count read error.");
1532
1533                         if (wakeup_count < 0) {
1534                                 _I("Wakup Event. Can not enter suspend mode.");
1535                                 goto go_lcd_off;
1536                         }
1537
1538                         if (set_wakeup_count(wakeup_count) < 0) {
1539                                 _E("Wakeup count write error.");
1540                                 goto go_lcd_off;
1541                         }
1542                 }
1543                 goto go_suspend;
1544         }
1545
1546         return 0;
1547
1548 go_suspend:
1549 #ifdef ENABLE_PM_LOG
1550         pm_history_save(PM_LOG_SLEEP, get_pm_cur_state());
1551 #endif
1552         power_request_change_state(DEVICED_POWER_STATE_SLEEP, HAL_DEVICE_POWER_TRANSITION_REASON_DISPLAY_OFF_TIMEOUT);
1553         return 0;
1554
1555 go_lcd_off:
1556         if (!pm_get_power_lock_support()) {
1557                 /* Resume !! */
1558                 states[get_pm_cur_state()].trans(EVENT_DEVICE);
1559         }
1560         return 0;
1561 }
1562
1563 /*
1564  * default check function
1565  *   return
1566  *    0 : can't transit, others : transitable
1567  */
1568 static int default_check(int curr, int next)
1569 {
1570         int trans_cond;
1571
1572         makeup_trans_condition();
1573
1574         trans_cond = get_trans_condition() & MASK_BIT;
1575
1576         if (next == S_NORMAL) /* S_NORMAL is exceptional */
1577                 return 1;
1578
1579         switch (curr) {
1580         case S_NORMAL:
1581                 trans_cond = trans_cond & MASK_NORMAL;
1582                 break;
1583         case S_LCDDIM:
1584                 trans_cond = trans_cond & MASK_DIM;
1585                 break;
1586         case S_LCDOFF:
1587                 trans_cond = trans_cond & MASK_OFF;
1588                 break;
1589         default:
1590                 trans_cond = 0;
1591                 break;
1592         }
1593
1594         if (trans_cond != 0) {
1595                 print_node(curr);
1596                 return 0;
1597         }
1598
1599         return 1;               /* transitable */
1600 }
1601
1602 static void default_saving_mode(int onoff)
1603 {
1604         if (onoff)
1605                 set_pm_status_flag(PWRSV_FLAG);
1606         else
1607                 clear_pm_status_flag(PWRSV_FLAG);
1608
1609         if (get_pm_cur_state() == S_NORMAL)
1610                 backlight_ops->update();
1611 }
1612
1613 int poll_callback(int condition, PMMsg *data)
1614 {
1615         static time_t last_t;
1616         time_t now;
1617
1618         if (status != DEVICE_OPS_STATUS_START) {
1619                 _E("Display logic is not started.");
1620                 return -ECANCELED;
1621         }
1622
1623         if (condition == INPUT_POLL_EVENT) {
1624                 if ((get_pm_cur_state() == S_LCDOFF) || (get_pm_cur_state() == S_SLEEP))
1625                         _I("Input event signal at Display Off");
1626                 time(&now);
1627                 if ((last_t != now) ||
1628                     (get_pm_cur_state() == S_LCDOFF) ||
1629                     (get_pm_cur_state() == S_SLEEP)) {
1630                         states[get_pm_cur_state()].trans(EVENT_INPUT);
1631                         last_t = now;
1632                 }
1633         }
1634
1635         if (condition == PM_CONTROL_EVENT) {
1636                 proc_condition(data);
1637
1638                 if (IS_COND_REQUEST_CHANGE(data->cond))
1639                         proc_change_state(data->cond, data->pid);
1640         }
1641
1642         return 0;
1643 }
1644
1645 static int update_setting(int key_idx, int val)
1646 {
1647         int ret;
1648
1649         switch (key_idx) {
1650         case SETTING_TO_NORMAL:
1651                 update_display_time();
1652                 states[get_pm_cur_state()].trans(EVENT_INPUT);
1653                 break;
1654         case SETTING_HALLIC_OPEN:
1655                 hallic_open = val;
1656                 update_display_time();
1657                 if ((get_pm_cur_state() == S_NORMAL) || (get_pm_cur_state() == S_LCDDIM))
1658                         states[get_pm_cur_state()].trans(EVENT_INPUT);
1659                 else if ((get_pm_cur_state() == S_SLEEP) && hallic_open)
1660                         proc_change_state(S_LCDOFF, INTERNAL_LOCK_HALLIC);
1661                 break;
1662         case SETTING_LOW_BATT:
1663                 if (low_battery_state(val)) {
1664                         if (!(get_pm_status_flag() & CHRGR_FLAG))
1665                                 power_saving_func(true);
1666                         set_pm_status_flag(LOWBT_FLAG);
1667                 } else {
1668                         if (get_pm_status_flag() & PWRSV_FLAG)
1669                                 power_saving_func(false);
1670                         clear_pm_status_flag(LOWBT_FLAG);
1671                         clear_pm_status_flag(BRTCH_FLAG);
1672                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, false);
1673                         if (ret < 0)
1674                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
1675                 }
1676                 break;
1677         case SETTING_CHARGING:
1678                 if (val) {
1679                         if (get_pm_status_flag() & LOWBT_FLAG) {
1680                                 power_saving_func(false);
1681                                 clear_pm_status_flag(LOWBT_FLAG);
1682                         }
1683                         set_pm_status_flag(CHRGR_FLAG);
1684                 } else {
1685                         int bat_state;
1686                         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
1687                                 &bat_state);
1688                         if (ret < 0) {
1689                                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
1690                                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
1691                         }
1692                         if (low_battery_state(bat_state)) {
1693                                 power_saving_func(true);
1694                                 set_pm_status_flag(LOWBT_FLAG);
1695                         }
1696                         clear_pm_status_flag(CHRGR_FLAG);
1697                 }
1698                 break;
1699         case SETTING_BRT_LEVEL:
1700                 if (get_pm_status_flag() & PWRSV_FLAG) {
1701                         set_pm_status_flag(BRTCH_FLAG);
1702                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, true);
1703                         if (ret < 0)
1704                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
1705                         _I("Brightness changed in low battery,"
1706                                 "escape dim state.");
1707                 }
1708                 backlight_ops->set_default_brt(val);
1709                 break;
1710         case SETTING_LOCK_SCREEN:
1711                 set_lock_screen_state(val);
1712                 if (val == VCONFKEY_IDLE_UNLOCK) {
1713                         if (CHECK_OPS(keyfilter_ops, backlight_enable))
1714                                 keyfilter_ops->backlight_enable(false);
1715                 }
1716
1717                 /* LCD on if lock screen show before waiting time */
1718                 if ((get_pm_cur_state() == S_NORMAL) &&
1719                     val == VCONFKEY_IDLE_LOCK &&
1720                     backlight_ops->get_lcd_power() != DPMS_ON &&
1721                         is_lcdon_blocked() == LCDON_BLOCK_NONE)
1722                         lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
1723                 stop_lock_timer();
1724                 update_display_time();
1725                 if (get_pm_cur_state() == S_NORMAL)
1726                         states[get_pm_cur_state()].trans(EVENT_INPUT);
1727                 break;
1728         case SETTING_LOCK_SCREEN_BG:
1729                 set_lock_screen_bg_state(val);
1730                 update_display_time();
1731                 if (get_pm_cur_state() == S_NORMAL)
1732                         states[get_pm_cur_state()].trans(EVENT_INPUT);
1733                 break;
1734         case SETTING_POWER_CUSTOM_BRIGHTNESS:
1735                 if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON)
1736                         backlight_ops->set_custom_status(true);
1737                 else
1738                         backlight_ops->set_custom_status(false);
1739                 break;
1740
1741         default:
1742                 return -1;
1743         }
1744         return 0;
1745 }
1746
1747 static void check_seed_status(void)
1748 {
1749         int ret = -1;
1750         int tmp = 0;
1751         int bat_state;
1752         int brt = 0;
1753         int lock_state;
1754
1755         /* Charging check */
1756         if (fp_get_charging_status && (fp_get_charging_status(&tmp) == 0) && (tmp > 0))
1757                 set_pm_status_flag(CHRGR_FLAG);
1758
1759         ret = get_setting_brightness(&tmp);
1760         if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
1761                 _I("Failed to read vconf value for brightness.");
1762                 brt = display_conf.pm_default_brightness;
1763                 if (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS) {
1764                         ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
1765                         if (ret < 0)
1766                                 _E("Failed to set vconf value for lcd brightness: %d", vconf_get_ext_errno());
1767                 }
1768                 tmp = brt;
1769         }
1770         _I("Set brightness(%d) from setting app.", tmp);
1771         backlight_ops->set_default_brt(tmp);
1772         backlight_ops->set_brightness(tmp);
1773
1774         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
1775         if (ret < 0) {
1776                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
1777                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
1778         }
1779         if (low_battery_state(bat_state)) {
1780                 if (!(get_pm_status_flag() & CHRGR_FLAG)) {
1781                         power_saving_func(true);
1782                         set_pm_status_flag(LOWBT_FLAG);
1783                 }
1784         }
1785
1786         /* lock screen check */
1787         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1788         if (ret < 0) {
1789                 lock_state = -1;
1790                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
1791         }
1792         set_lock_screen_state(lock_state);
1793         if (lock_state == VCONFKEY_IDLE_LOCK) {
1794                 states[S_NORMAL].timeout = lock_screen_timeout;
1795                 _I("LCD NORMAL timeout(%d ms) is set"
1796                         " for lock screen.", lock_screen_timeout);
1797         }
1798
1799         return;
1800 }
1801
1802 static void init_lcd_operation(void)
1803 {
1804         const struct device_ops *ops = NULL;
1805
1806         ops = find_device("display");
1807         if (!check_default(ops))
1808                 SYS_G_LIST_APPEND(lcdon_ops, ops);
1809
1810         ops = find_device("touchkey");
1811         if (!check_default(ops))
1812                 SYS_G_LIST_APPEND(lcdon_ops, ops);
1813
1814         ops = find_device("touchscreen");
1815         if (!check_default(ops))
1816                 SYS_G_LIST_APPEND(lcdon_ops, ops);
1817 }
1818
1819 static void exit_lcd_operation(void)
1820 {
1821         GList *l = NULL;
1822         GList *l_next = NULL;
1823         const struct device_ops *ops = NULL;
1824
1825         SYS_G_LIST_FOREACH_SAFE(lcdon_ops, l, l_next, ops)
1826                 SYS_G_LIST_REMOVE_LIST(lcdon_ops, l);
1827 }
1828
1829 enum {
1830         INIT_SETTING = 0,
1831         INIT_INTERFACE,
1832         INIT_POLL,
1833         INIT_FIFO,
1834         INIT_DBUS,
1835         INIT_END
1836 };
1837
1838 static const char *errMSG[INIT_END] = {
1839         [INIT_SETTING] = "setting init error",
1840         [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
1841         [INIT_POLL] = "input devices poll init error",
1842         [INIT_FIFO] = "FIFO poll init error",
1843         [INIT_DBUS] = "d-bus init error",
1844 };
1845
1846 int set_lcd_timeout(int on, int dim, int holdkey_block, const char *name)
1847 {
1848         if (on == 0 && dim == 0) {
1849                 _I("LCD timeout changed: default setting");
1850                 custom_normal_timeout = custom_dim_timeout = 0;
1851         } else if (on < 0 || dim < 0) {
1852                 _E("Failed to set value(on=%d dim=%d).", on, dim);
1853                 return -EINVAL;
1854         } else {
1855                 _I("LCD timeout changed: on=%ds dim=%ds", on, dim);
1856                 custom_normal_timeout = SEC_TO_MSEC(on);
1857                 custom_dim_timeout = SEC_TO_MSEC(dim);
1858         }
1859         /* Apply new backlight time */
1860         update_display_time();
1861         if (get_pm_cur_state() == S_NORMAL)
1862                 states[get_pm_cur_state()].trans(EVENT_INPUT);
1863
1864         if (holdkey_block) {
1865                 custom_holdkey_block = true;
1866                 _I("Hold key disabled.");
1867         } else {
1868                 custom_holdkey_block = false;
1869                 _I("Hold key enabled.");
1870         }
1871
1872         if (custom_change_name) {
1873                 free(custom_change_name);
1874                 custom_change_name = 0;
1875         }
1876
1877         if (custom_normal_timeout == 0 &&
1878             custom_dim_timeout == 0 &&
1879             !holdkey_block)
1880                 return 0;
1881
1882         custom_change_name = strndup(name, strlen(name));
1883         if (!custom_change_name) {
1884                 _E("Failed to malloc.");
1885                 custom_normal_timeout = custom_dim_timeout = 0;
1886                 custom_holdkey_block = false;
1887                 return -ENOMEM;
1888         }
1889
1890         return 0;
1891 }
1892
1893 void reset_lcd_timeout(GDBusConnection *conn,
1894         const gchar     *sender,
1895         const gchar     *unique_name,
1896         gpointer         data)
1897 {
1898         if (!sender)
1899                 return;
1900
1901         if (!custom_change_name)
1902                 return;
1903
1904         if (strcmp(sender, custom_change_name))
1905                 return;
1906
1907         _I("reset lcd timeout: Set default timeout. sender=%s", sender);
1908
1909         free(custom_change_name);
1910         custom_change_name = 0;
1911         custom_normal_timeout = custom_dim_timeout = 0;
1912         custom_holdkey_block = false;
1913
1914         update_display_time();
1915         if (get_pm_cur_state() == S_NORMAL)
1916                 states[get_pm_cur_state()].trans(EVENT_INPUT);
1917 }
1918
1919 static int delayed_init_done(void *data)
1920 {
1921         static bool done = false;
1922
1923         if (!data)
1924                 return done;
1925
1926         done = *(int*)data;
1927         if (!done)
1928                 return done;
1929
1930         _I("Booting done, release booting lock.");
1931         if (disp_plgn->pm_unlock_internal) {
1932                 disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL, PM_SLEEP_MARGIN);
1933                 disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
1934         }
1935
1936         return done;
1937 }
1938
1939 static int battery_health_changed(void *data)
1940 {
1941         int health = DATA_VALUE_INT(data);
1942
1943         _I("battery health change %d", health);
1944
1945         if (health == HEALTH_GOOD) {
1946                 clear_pm_status_flag(BATTERY_FLAG);
1947                 clear_pm_status_flag(DIMSTAY_FLAG);
1948         } else if (health == HEALTH_LOW || health == HEALTH_HIGH || health == HEALTH_OVP) {
1949                 set_pm_status_flag(BATTERY_FLAG);
1950                 set_pm_status_flag(DIMSTAY_FLAG);
1951         }
1952
1953         if (backlight_ops->get_lcd_power() == DPMS_ON)
1954                 backlight_ops->update();
1955
1956         return 0;
1957 }
1958
1959 static gboolean delayed_dpms_init_done(gpointer data)
1960 {
1961         int timeout;
1962
1963         if (!dpms_init())
1964                 return G_SOURCE_CONTINUE;
1965
1966         switch (get_pm_cur_state()) {
1967         case S_NORMAL:
1968         case S_LCDDIM:
1969                 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
1970                 if (display_conf.timeout_enable) {
1971                         timeout = states[S_NORMAL].timeout;
1972                         /* check minimun lcd on time */
1973                         if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
1974                                 timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
1975                         reset_timeout(timeout);
1976                 }
1977                 break;
1978         case S_LCDOFF:
1979                 lcd_off_procedure(LCD_OFF_BY_EVENT);
1980                 timeout = display_conf.lcdoff_timeout;
1981                 reset_timeout(timeout);
1982                 break;
1983         default:
1984                 break;
1985         }
1986
1987         return G_SOURCE_REMOVE;
1988 }
1989
1990 static void add_timer_for_dpms_init(void)
1991 {
1992         guint id = g_timeout_add(500/* milliseconds */, delayed_dpms_init_done, NULL);
1993         if (id == 0)
1994                 _E("Failed to add dpms_init timeout.");
1995 }
1996
1997 /**
1998  * Power manager Main
1999  *
2000  */
2001 static int display_probe(void *data)
2002 {
2003         int ret;
2004
2005         /**
2006          * load display service
2007          * if there is no display shared library,
2008          * deviced does not provide any method and function of display.
2009          */
2010         ret = display_service_load();
2011         if (ret)
2012                 return ret;
2013
2014         /* display_plugin instance initialization */
2015         init_pm_internal();
2016         disp_plgn->device_flags_to_string = __device_flags_to_string;
2017
2018         if (battery_plgn->handle) {
2019                 fp_get_charging_status = dlsym(battery_plgn->handle, "get_charging_status");
2020                 if (!fp_get_charging_status)
2021                         _E("Failed to obtain address of get_charging_status");
2022         } else
2023                 _I("There is no battery module.");
2024
2025         return 0;
2026 }
2027
2028 static int input_init_handler(void)
2029 {
2030         if (!display_conf.input_support)
2031                 remove_device_by_devname("input");
2032
2033         return 0;
2034 }
2035
2036 static int power_resume_from_echomem_callback(void *data)
2037 {
2038         system_wakeup_flag = true;
2039         if (check_wakeup_src() == EVENT_DEVICE)
2040                 /* system waked up by devices */
2041                 states[get_pm_cur_state()].trans(EVENT_DEVICE);
2042         else
2043                 /* system waked up by user input */
2044                 states[get_pm_cur_state()].trans(EVENT_INPUT);
2045
2046         return 0;
2047 }
2048
2049 static int poweroff_triggered_callback(void *udata)
2050 {
2051         int val = (int)(intptr_t) udata;
2052
2053         switch (val) {
2054         case VCONFKEY_SYSMAN_POWER_OFF_NONE:
2055                 clear_pm_status_flag(PWROFF_FLAG);
2056                 break;
2057         case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
2058         case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
2059                 set_pm_status_flag(PWROFF_FLAG);
2060                 break;
2061         }
2062
2063         return 0;
2064 }
2065
2066 static void esd_action(void)
2067 {
2068         const struct device_ops *touchscreen_ops = NULL;
2069
2070         _I("ESD on");
2071
2072         touchscreen_ops = find_device("touchscreen");
2073
2074         if (!check_default(touchscreen_ops))
2075                 touchscreen_ops->stop(NORMAL_MODE);
2076         backlight_ops->off(NORMAL_MODE);
2077         backlight_ops->on(NORMAL_MODE);
2078         if (!check_default(touchscreen_ops))
2079                 touchscreen_ops->start(NORMAL_MODE);
2080 }
2081
2082 static void lcd_uevent_changed(struct udev_device *dev)
2083 {
2084         const char *devpath;
2085         const char *action;
2086
2087         devpath = udev_device_get_devpath(dev);
2088         if (!devpath)
2089                 return;
2090
2091         if (!fnmatch(LCD_ESD_PATH, devpath, 0)) {
2092                 action = udev_device_get_action(dev);
2093                 if (!strcmp(action, UDEV_CHANGE))
2094                         esd_action();
2095         }
2096 }
2097
2098 static const struct uevent_handler lcd_uevent_ops = {
2099         .subsystem      = LCD_EVENT_SUBSYSTEM,
2100         .uevent_func    = lcd_uevent_changed,
2101         .data           = NULL,
2102 };
2103
2104 static void display_init(void *data)
2105 {
2106         int ret, i;
2107         unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS);
2108         int timeout = 0;
2109
2110         _I("Start power manager.");
2111
2112         signal(SIGHUP, sig_hup);
2113
2114         power_saving_func = default_saving_mode;
2115
2116         /* load configutation */
2117         ret = config_parse(DISPLAY_CONF_FILE, display_load_config, &display_conf);
2118         if (ret < 0)
2119                 _W("Failed to load '%s', use default value: %d",
2120                     DISPLAY_CONF_FILE, ret);
2121
2122         register_kernel_uevent_control(&lcd_uevent_ops);
2123
2124         register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
2125         register_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
2126         register_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
2127         register_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
2128         register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed);
2129         register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed);
2130         register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing);
2131         register_notifier(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
2132         register_notifier(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback);
2133
2134         init_save_userlock();
2135
2136         for (i = INIT_SETTING; i < INIT_END; i++) {
2137                 switch (i) {
2138                 case INIT_SETTING:
2139                         ret = init_setting(update_setting);
2140                         break;
2141                 case INIT_INTERFACE:
2142                         if (display_conf.timeout_enable)
2143                                 get_lcd_timeout_from_settings();
2144                         ret = init_sysfs(flags);
2145                         break;
2146                 case INIT_POLL:
2147                         _I("input init");
2148                         ret = input_init_handler();
2149
2150                         pm_lock_detector_init();
2151                         break;
2152                 case INIT_DBUS:
2153                         _I("Dbus init.");
2154                         ret = init_pm_dbus();
2155                         break;
2156                 }
2157                 if (ret != 0) {
2158                         _E("Failed to init: %s", errMSG[i]);
2159                         break;
2160                 }
2161         }
2162
2163         if (i == INIT_END) {
2164                 display_ops_init(NULL);
2165 #ifdef ENABLE_PM_LOG
2166                 pm_history_init();
2167 #endif
2168                 init_lcd_operation();
2169                 check_seed_status();
2170
2171                 /* In smd test, TSP should be turned off if display panel is not existed. */
2172                 if (backlight_ops->get_lcd_power() == -ENOENT) {
2173                         _I("Display panel is not existed.");
2174                         lcd_direct_control(DPMS_OFF, NORMAL_MODE);
2175                         exit_lcd_operation();
2176                 }
2177
2178                 /* wm_ready needs to be checked
2179                  * since display manager can be launched later than deviced.
2180                  * In the case, display cannot be turned on at the first booting */
2181                 // wm_ready = check_wm_ready();
2182                 if (dpms_init()) {
2183                         if (is_lcdon_blocked() != LCDON_BLOCK_NONE)
2184                                 lcd_off_procedure(LCD_OFF_BY_EVENT);
2185                         else
2186                                 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
2187                 } else {
2188                         add_timer_for_dpms_init();
2189                 }
2190
2191                 if (display_conf.lcd_always_on) {
2192                         _I("LCD always on.");
2193                         trans_table[S_NORMAL][EVENT_TIMEOUT] = S_NORMAL;
2194                 }
2195
2196                 if (flags & WITHOUT_STARTNOTI) {        /* start without noti */
2197                         _I("Start Power managing without noti");
2198                         /*
2199                          * Lock lcd off until booting is done.
2200                          * deviced guarantees all booting script is executing.
2201                          * Last script of booting unlocks this suspend blocking state.
2202                          */
2203                         if (disp_plgn->pm_lock_internal)
2204                                 disp_plgn->pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF,
2205                                                 STAY_CUR_STATE, DELAYED_INIT_WATING_TIME);
2206
2207                         /* Initial display state right after the booting done */
2208                         if (is_lcdon_blocked())
2209                                 set_pm_cur_state(S_LCDOFF);
2210                         else
2211                                 set_pm_cur_state(S_NORMAL);
2212                         ret = vconf_set_int(VCONFKEY_PM_STATE, get_pm_cur_state());
2213                         if (ret < 0)
2214                                 _E("Failed to set vconf value for pm cur state: %d", vconf_get_ext_errno());
2215
2216                         status = DEVICE_OPS_STATUS_START;
2217                         if (display_conf.timeout_enable) {
2218                                 timeout = states[S_NORMAL].timeout;
2219                                 /* check minimun lcd on time */
2220                                 if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
2221                                         timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
2222
2223                                 if (disp_plgn->pm_lock_internal)
2224                                         disp_plgn->pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL,
2225                                                         STAY_CUR_STATE, timeout);
2226                         }
2227
2228                 }
2229
2230                 if (display_conf.input_support)
2231                         if (CHECK_OPS(keyfilter_ops, init))
2232                                 keyfilter_ops->init();
2233
2234                 set_display_init_direction(display_conf.display_init_direction);
2235         }
2236 }
2237
2238 static void display_exit(void *data)
2239 {
2240         int i = INIT_END;
2241
2242         status = DEVICE_OPS_STATUS_STOP;
2243
2244         /* Set current state to S_NORMAL */
2245         set_pm_cur_state(S_NORMAL);
2246         set_setting_pmstate(get_pm_cur_state());
2247         /* timeout is not needed */
2248         reset_timeout(TIMEOUT_NONE);
2249
2250         if (CHECK_OPS(keyfilter_ops, exit))
2251                 keyfilter_ops->exit();
2252
2253         unregister_kernel_uevent_control(&lcd_uevent_ops);
2254
2255         display_ops_exit(NULL);
2256
2257         for (i = i - 1; i >= INIT_SETTING; i--) {
2258                 switch (i) {
2259                 case INIT_SETTING:
2260                         exit_setting();
2261                         break;
2262                 case INIT_INTERFACE:
2263                         exit_sysfs();
2264                         break;
2265                 case INIT_POLL:
2266                         unregister_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
2267                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
2268                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
2269                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
2270                         unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed);
2271                         unregister_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed);
2272                         unregister_notifier(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
2273
2274                         break;
2275                 }
2276         }
2277
2278         exit_lcd_operation();
2279         free_lock_info_list();
2280
2281         /* free display service */
2282         display_service_free();
2283
2284         _I("Stop power manager.");
2285 }
2286
2287 static int display_start(enum device_flags flags)
2288 {
2289         const struct display_ops *enhance_ops = NULL;
2290         bool on = true;
2291
2292         /* NORMAL MODE */
2293         if (flags & NORMAL_MODE) {
2294                 if (flags & LCD_PANEL_OFF_MODE)
2295                         /* standby on */
2296                         backlight_ops->standby(true);
2297                 else
2298                         /* normal lcd on */
2299                         backlight_ops->on(flags);
2300                 FIND_DISPLAY(enhance_ops, "enhance");
2301                 if (enhance_ops && enhance_ops->func)
2302                         enhance_ops->func(RESTORE_ENHANCE_OUTDOOR, &on);
2303                 return 0;
2304         }
2305
2306         /* CORE LOGIC MODE */
2307         if (!(flags & CORE_LOGIC_MODE))
2308                 return 0;
2309
2310         if (status == DEVICE_OPS_STATUS_START)
2311                 return -EALREADY;
2312
2313         if (display_probe(NULL) < 0)
2314                 return -EPERM;
2315
2316         display_init(NULL);
2317
2318         return 0;
2319 }
2320
2321 static int display_stop(enum device_flags flags)
2322 {
2323         /* NORMAL MODE */
2324         if (flags & NORMAL_MODE || flags & FORCE_OFF_MODE) {
2325                 backlight_ops->off(flags);
2326                 return 0;
2327         }
2328
2329         /* CORE LOGIC MODE */
2330         if (!(flags & CORE_LOGIC_MODE))
2331                 return 0;
2332
2333         if (status == DEVICE_OPS_STATUS_STOP)
2334                 return -EALREADY;
2335
2336         display_exit(NULL);
2337
2338         return 0;
2339 }
2340
2341 static int display_status(void)
2342 {
2343         return status;
2344 }
2345
2346 static const struct device_ops display_device_ops = {
2347         .priority = DEVICE_PRIORITY_HIGH,
2348         DECLARE_NAME_LEN("display"),
2349         .probe    = display_probe,
2350         .init     = display_init,
2351         .exit     = display_exit,
2352         .start    = display_start,
2353         .stop     = display_stop,
2354         .status   = display_status,
2355 };
2356
2357 DEVICE_OPS_REGISTER(&display_device_ops)
2358
2359 static void __CONSTRUCTOR__ initialize(void)
2360 {
2361         disp_plgn = get_var_display_plugin();
2362         if (!disp_plgn)
2363                 _E("Failed to get display plugin variable.");
2364
2365         backlight_ops = get_var_backlight_ops();
2366         if (!backlight_ops)
2367                 _E("Failed to get backlight operator variable.");
2368
2369         battery_plgn = get_var_battery_plugin();
2370         if (!battery_plgn)
2371                 _E("Failed to get battery plugin variable.");
2372 }
2373 /**
2374  * @}
2375  */