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