display: state-transition: Relocate default_trans()
[platform/core/system/deviced.git] / plugins / tv / 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 "poll.h"
49 #include "lock-detector.h"
50 #include "display-ops.h"
51 #include "shared/devices.h"
52 #include "shared/device-notifier.h"
53 #include "core/udev.h"
54 #include "shared/common.h"
55 #include "shared/apps.h"
56 #include "extcon/extcon.h"
57 #include "battery/power-supply.h"
58 #include "power/power.h"
59 #include "power/power-off.h"
60 #include "power/power-suspend.h"
61 #include "power/power-boot.h"
62 #include "power/power-doze.h"
63 #include "device-interface.h"
64 #include "display-plugin.h"
65 #include "display-signal.h"
66 #include "display-lock.h"
67 #include "display-backlight.h"
68 #include "display-misc.h"
69 #include "display-panel.h"
70 #include "display-config.h"
71 #include "display-state-transition.h"
72 #include "shared/plugin.h"
73 #include "led/touch-key.h"
74
75 /**
76  * @addtogroup POWER_MANAGER
77  * @{
78  */
79
80 #define LOCK_SCREEN_CONTROL_TIMEOUT     5000
81
82 #define GESTURE_STR             "gesture"
83 #define POWER_KEY_STR           "powerkey"
84 #define TOUCH_STR               "touch"
85 #define EVENT_STR               "event"
86 #define TIMEOUT_STR             "timeout"
87 #define PROXI_STR               "proximity"
88 #define PALM_STR                "palm"
89 #define UNKNOWN_STR             "unknown"
90
91 extern void init_save_userlock(void);
92
93 static struct display_plugin *disp_plgn;
94 static struct display_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 int system_wakeup_flag = false;
102 static char *custom_change_name;
103 static guint lock_timeout_id;
104 static struct timeval lcdon_tv;
105 /*
106  * The two variables(lcdon_broadcast, pmstate_suspend) must be set initial
107  * state because it should be sent from previous state at booting time.
108  */
109 static bool lcdon_broadcast = true;
110
111 static bool touch_blocked = false;
112
113 /* default transition, action fuctions */
114 static int default_action(int timeout);
115
116 static int default_proc_change_state(unsigned int cond, pid_t pid);
117 static int (*proc_change_state)(unsigned int cond, pid_t pid) = default_proc_change_state;
118
119 static struct state states[S_END] = {
120         { S_START,    "S_START",    NULL,          NULL,           NULL,          NULL            },
121         { S_NORMAL,   "S_NORMAL",   NULL,          default_action, NULL,          NULL            },
122         { S_LCDDIM,   "S_LCDDIM",   NULL,          default_action, NULL,          NULL            },
123         { S_LCDOFF,   "S_LCDOFF",   NULL,          default_action, NULL,          NULL            },
124         { S_STANDBY,  "S_STANDBY",  NULL,          NULL,           NULL,          NULL            },
125         { S_SLEEP,    "S_SLEEP",    NULL,          default_action, NULL,          NULL            },
126         { S_POWEROFF, "S_POWEROFF", NULL,          NULL,           NULL,          NULL            },
127 };
128
129 #define TIMEOUT_NONE            (-1)
130
131 #define DELAYED_INIT_WATING_TIME        60000   /* 1 minute */
132
133 #define LOCK_SCREEN_WATING_TIME         300     /* 0.3 second */
134 #define LONG_PRESS_INTERVAL             2       /* 2 seconds */
135 #define SAMPLING_INTERVAL               1       /* 1 sec */
136 #define BRIGHTNESS_CHANGE_STEP          10
137 #define LCD_ALWAYS_ON                   0
138 #define ACCEL_SENSOR_ON                 1
139 #define CONTINUOUS_SAMPLING             1
140 #define LCDOFF_TIMEOUT                  300     /* milli second */
141
142 #define DIFF_TIMEVAL_MS(a, b) \
143         (((a.tv_sec * 1000000 + a.tv_usec) - \
144         (b.tv_sec * 1000000 + b.tv_usec)) \
145         / 1000)
146
147 static struct display_config display_conf = {
148         .lock_wait_time         = LOCK_SCREEN_WATING_TIME,
149         .longpress_interval     = LONG_PRESS_INTERVAL,
150         .lightsensor_interval   = SAMPLING_INTERVAL,
151         .lcdoff_timeout         = LCDOFF_TIMEOUT,
152         .pm_default_brightness = 80,
153         .brightness_change_step = BRIGHTNESS_CHANGE_STEP,
154         .lcd_always_on          = LCD_ALWAYS_ON,
155         .dimming                = 1,
156         .framerate_app          = {0, 0, 0, 0},
157         .control_display        = 0,
158         .powerkey_doublepress   = 0,
159         .accel_sensor_on        = ACCEL_SENSOR_ON,
160         .continuous_sampling    = CONTINUOUS_SAMPLING,
161         .timeout_enable         = true,
162         .input_support          = true,
163         .display_init_direction = DISPLAY_INIT_DIRECTION_HORIZONTAL,
164         .lockcheck_timeout      = 600,
165         .aod_enter_level        = 40,
166         .aod_tsp                = true,
167         .touch_wakeup           = false,
168         .display_on_usb_conn_changed = true,
169         .display_dpms_type      = DISPLAY_DPMS_TYPE_WINDOW_MANAGER,
170 };
171
172 struct display_function_info display_info = {
173         .update_auto_brightness         = NULL,
174         .set_autobrightness_min         = NULL,
175         .reset_autobrightness_min       = NULL,
176         .face_detection                 = NULL,
177 };
178
179 inline const struct display_config* get_var_display_config()
180 {
181         return &display_conf;
182 }
183
184 inline struct state* state_st(enum state_t state)
185 {
186         return &states[state];
187 }
188
189 static const char* __device_flags_to_string(enum device_flags flags)
190 {
191         if (flags & LCD_ON_BY_GESTURE)
192                 return GESTURE_STR;
193         else if (flags & (LCD_ON_BY_POWER_KEY | LCD_OFF_BY_POWER_KEY))
194                 return POWER_KEY_STR;
195         else if (flags & (LCD_ON_BY_EVENT | LCD_OFF_BY_EVENT))
196                 return EVENT_STR;
197         else if (flags & LCD_ON_BY_TOUCH)
198                 return TOUCH_STR;
199         else if (flags & LCD_OFF_BY_TIMEOUT)
200                 return TIMEOUT_STR;
201         else
202                 return UNKNOWN_STR;
203 }
204
205 bool touch_event_blocked(void)
206 {
207         return touch_blocked;
208 }
209
210 void lcd_on_procedure(int state, enum device_flags flag)
211 {
212         unsigned long flags = NORMAL_MODE;
213         display_plugin_get_device_flags(&flags);
214         flags |= flag;
215
216         /*
217          * Display on procedure
218          * step 1. leave doze
219          * step 2. broadcast lcd on signal with cause
220          * step 3. set brightness
221          * step 4. set pmstate of vconf
222          * step 5. display on operate
223          *  - a. display on
224          *  - b. TSP(touch screen) and touchkey enable
225          * step 6. broadcast lcd on complete signal
226          * step 7. key backlight enable
227          */
228         leave_doze();
229
230         _I("[lcdstep] 0x%lx", flags);
231
232         /* send LCDOn dbus signal */
233         if (!lcdon_broadcast)
234                 broadcast_lcd_on(SIGNAL_PRE, flags);
235
236         /* Update brightness level */
237         if (state == LCD_DIM)
238                 display_backlight_set_brightness_by_dim_brightness();
239         else if (state == LCD_NORMAL)
240                 display_backlight_update_by_default_brightness();
241
242         if (state == LCD_NORMAL)
243                 set_setting_pmstate(S_NORMAL);
244         else if (state == LCD_DIM)
245                 set_setting_pmstate(S_LCDDIM);
246
247         display_start_dependent_device(flags);
248
249         if (!lcdon_broadcast) {
250         broadcast_lcd_on(SIGNAL_POST, flags);
251                 lcdon_broadcast = true;
252         }
253
254         touchled_control_backlight(TOUCHLED_DIRECT_ON);
255
256         touch_blocked = false;
257 }
258
259 inline void lcd_off_procedure(enum device_flags flag)
260 {
261         unsigned long flags = NORMAL_MODE;
262         display_plugin_get_device_flags(&flags);
263         flags |= flag;
264
265         /*
266          * Display off procedure
267          * step 0. enhance mode off using nofity (e.g mdnie, HBM, LBM)
268          * step 1. broadcast lcd off signal with cause
269          * step 2. set pmstate of vconf
270          * step 3. display off operate
271          *  - a. display off
272          *  - b. TSP(touch screen) and touchkey disable
273          * step 4. broadcast lcd off complete siganl
274          * step 5. enter doze mode if it is enabled
275          */
276         _I("[lcdstep] 0x%lx", flags);
277
278         /* notification */
279
280         device_notify(DEVICE_NOTIFIER_LCD_OFF, NULL);
281
282         if (lcdon_broadcast) {
283                 broadcast_lcd_off(SIGNAL_PRE, flags);
284                 lcdon_broadcast = false;
285         }
286
287         /* operation */
288
289         touch_blocked = true;
290
291         set_setting_pmstate(S_LCDOFF);
292
293         touchled_control_backlight(TOUCHLED_DIRECT_OFF);
294
295         display_stop_dependent_device(flags);
296
297         broadcast_lcd_off(SIGNAL_POST, flags);
298         device_notify(DEVICE_NOTIFIER_LCD_OFF_COMPLETE, NULL);
299
300         enter_doze();
301 }
302
303 static void update_display_locktime(int time)
304 {
305         display_state_transition_set_lock_screen_timeout(time);
306         display_state_transition_update_display_state_timeout_by_priority();
307 }
308
309 void lcd_on_direct(enum device_flags flags)
310 {
311         enum hal_device_power_transition_reason reason;
312
313         if (flags & LCD_ON_BY_POWER_KEY)
314                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_POWER_KEY;
315         else if (flags & LCD_ON_BY_TOUCH)
316                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_TOUCH_SCREEN;
317         else
318                 reason = HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN;
319
320         power_request_change_state_strict(DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL, reason, NULL);
321         set_pm_cur_state(S_NORMAL);
322
323         _D("lcd is on directly");
324         gettimeofday(&lcdon_tv, NULL);
325         lcd_on_procedure(LCD_NORMAL, flags);
326
327         update_display_locktime(LOCK_SCREEN_INPUT_TIMEOUT);
328 }
329
330 static inline bool check_lcd_is_on(void)
331 {
332         if (display_panel_get_dpms_cached_state() != DPMS_ON)
333                 return false;
334
335         return true;
336 }
337
338 static gboolean timer_refresh_cb(gpointer data)
339 {
340         struct state *st;
341
342         /* state transition */
343         set_pm_old_state(get_pm_cur_state());
344         set_pm_cur_state(S_NORMAL);
345         st = &states[get_pm_cur_state()];
346
347         if (st->action)
348                 st->action(st->timeout);
349
350         return 0;
351 }
352
353 int custom_lcdon(int timeout)
354 {
355         struct state *st;
356
357         if (timeout <= 0)
358                 return -EINVAL;
359
360         if (check_lcd_is_on() == false)
361                 lcd_on_direct(LCD_ON_BY_GESTURE);
362
363         _I("Custom lcd on timeout(%d ms).", timeout);
364         if (set_custom_lcdon_timeout(timeout) == true)
365                 display_state_transition_update_display_state_timeout_by_priority();
366
367         /* state transition */
368         set_pm_old_state(get_pm_cur_state());
369         set_pm_cur_state(S_NORMAL);
370         st = &states[get_pm_cur_state()];
371
372         /* enter action */
373         if (st->action)
374                 st->action(st->timeout);
375
376         g_idle_add(timer_refresh_cb, NULL);
377
378         return 0;
379 }
380
381 int custom_lcdoff(enum device_flags flag)
382 {
383         struct state *st;
384
385         check_processes(S_NORMAL);
386         check_processes(S_LCDDIM);
387
388         /* check holdkey block flag in lock node */
389         if (check_lock_condition(S_NORMAL) || check_lock_condition(S_LCDDIM)) {
390                 /*
391                  * When another proccess is normal lock, device is received call then,
392                  * call app can be changed to lcd state by proximity.
393                  * If proximity is near then normal lock will be unlocked.
394                  */
395                 if (flag & LCD_OFF_BY_PROXIMITY) {
396                         _I("custom lcd off by proximity, delete normal lock");
397                         delete_condition(S_NORMAL);
398                 } else {
399                         _I("skip custom lcd off");
400                         return -ECANCELED;
401                 }
402         }
403
404         _I("custom lcd off by flag(%d)", flag);
405         if (display_panel_get_dpms_cached_state() == DPMS_ON)
406                 lcd_off_procedure(flag);
407
408         if (set_custom_lcdon_timeout(0) == true)
409                 display_state_transition_update_display_state_timeout_by_priority();
410
411         /* state transition */
412         set_pm_old_state(get_pm_cur_state());
413         set_pm_cur_state(S_LCDOFF);
414         st = &states[get_pm_cur_state()];
415
416         /* enter action */
417         if (st->action)
418                 st->action(st->timeout);
419
420         return 0;
421 }
422
423 int display_on_by_reason(const char *reason, int timeout)
424 {
425         struct state *st;
426         int flag;
427         int str_len;
428
429         str_len = strlen(reason);
430
431         if (!strncmp(reason, GESTURE_STR, str_len))
432                 flag = LCD_ON_BY_GESTURE;
433         else if (!strncmp(reason, EVENT_STR, str_len))
434                 flag = LCD_ON_BY_EVENT;
435         else {
436                 _E("Reason is unknown(%s)", reason);
437                 return -EINVAL;
438         }
439
440         if (timeout <= 0) {
441                 _E("Cannot setting timeout %d", timeout);
442                 return -EINVAL;
443         }
444
445         if (check_lcd_is_on() == false)
446                 lcd_on_direct(flag);
447
448         _I("platform lcd on by %s (%d ms)", reason, timeout);
449         if (set_custom_lcdon_timeout(timeout) == true)
450                 display_state_transition_update_display_state_timeout_by_priority();
451
452         /* state transition */
453         set_pm_old_state(get_pm_cur_state());
454         set_pm_cur_state(S_NORMAL);
455         st = &states[get_pm_cur_state()];
456
457         /* enter action */
458         if (st->action)
459                 st->action(st->timeout);
460
461         return 0;
462 }
463
464 int display_off_by_reason(const char *reason)
465 {
466         struct state *st;
467         int flag;
468         int str_len;
469
470         str_len = strlen(reason);
471
472         if (!strncmp(reason, GESTURE_STR, str_len)) {
473                 check_processes(S_NORMAL);
474                 check_processes(S_LCDDIM);
475
476                 /* check holdkey block flag in lock node */
477                 if (check_lock_condition(S_NORMAL) || check_lock_condition(S_LCDDIM)) {
478                         _I("skip platform lcd off by gesture");
479                         return -ECANCELED;
480                 }
481                 flag = LCD_OFF_BY_GESTURE;
482         } else if (!strncmp(reason, PALM_STR, str_len)) {
483                 delete_condition(S_NORMAL);
484                 delete_condition(S_LCDDIM);
485
486                 flag = LCD_OFF_BY_PALM;
487         } else {
488                 _E("Reason is unknown(%s)", reason);
489                 return -EINVAL;
490         }
491
492         _I("platform lcd off by %s", reason);
493         if (display_panel_get_dpms_cached_state() == DPMS_ON)
494                 lcd_off_procedure(flag);
495
496         /* state transition */
497         set_pm_old_state(get_pm_cur_state());
498         set_pm_cur_state(S_LCDOFF);
499         st = &states[get_pm_cur_state()];
500
501         /* enter action */
502         if (st->action)
503                 st->action(st->timeout);
504
505         return 0;
506 }
507
508 static void default_proc_change_state_action(enum state_t next, int timeout)
509 {
510         struct state *st;
511
512         set_pm_old_state(get_pm_cur_state());
513         set_pm_cur_state(next);
514
515         st = &states[get_pm_cur_state()];
516
517         if (st && st->action) {
518                 if (timeout < 0)
519                         st->action(st->timeout);
520                 else
521                         st->action(timeout);
522         }
523 }
524
525 static int default_proc_change_state(unsigned int cond, pid_t pid)
526 {
527         enum state_t next;
528
529         next = GET_COND_STATE(cond);
530         _I("Change process(%d) state to %s.", pid, states[next].name);
531
532         switch (next) {
533         case S_NORMAL:
534                 if (check_lcd_is_on() == false)
535                         lcd_on_direct(LCD_ON_BY_EVENT);
536                 update_display_locktime(LOCK_SCREEN_CONTROL_TIMEOUT);
537                 default_proc_change_state_action(next, -1);
538                 break;
539         case S_LCDDIM:
540                 default_proc_change_state_action(next, -1);
541                 break;
542         case S_LCDOFF:
543                 if (display_panel_get_dpms_cached_state() == DPMS_ON)
544                         lcd_off_procedure(LCD_OFF_BY_EVENT);
545                 if (set_custom_lcdon_timeout(0))
546                         display_state_transition_update_display_state_timeout_by_priority();
547                 default_proc_change_state_action(next, -1);
548                 break;
549         case S_SLEEP:
550                 _I("Dangerous requests.");
551                 /* at first LCD_OFF and then goto sleep */
552                 /* state transition */
553                 default_proc_change_state_action(S_LCDOFF, TIMEOUT_NONE);
554                 delete_condition(S_NORMAL);
555                 delete_condition(S_LCDDIM);
556                 delete_condition(S_LCDOFF);
557                 if (lcdon_broadcast) {
558                         _I("broadcast lcd off signal at non-lcd device");
559                         broadcast_lcd_off(SIGNAL_PRE, 0);
560                         broadcast_lcd_off(SIGNAL_POST, 0);
561                 }
562                 default_proc_change_state_action(S_SLEEP, TIMEOUT_NONE);
563                 break;
564
565         default:
566                 return -EINVAL;
567         }
568
569         return 0;
570 }
571
572 static void proc_condition_lock(PMMsg *data)
573 {
574         PmLockNode *tmp;
575         char pname[PATH_MAX];
576         pid_t pid = data->pid;
577         enum state_t state;
578         int holdkey_block, ret;
579         bool value = true;
580         unsigned int flags;
581         const char *lock_type = NULL;
582
583         state = GET_COND_STATE(data->cond);
584         if (state == S_START)
585                 return;
586
587         flags = GET_COND_FLAG(data->cond);
588         display_misc_get_process_name(pid, pname);
589
590         if ((state == S_LCDOFF) && (get_pm_cur_state() == S_SLEEP) &&
591             (pm_get_power_lock() == POWER_UNLOCK))
592                 proc_change_state(data->cond, INTERNAL_LOCK_PM);
593
594         holdkey_block = GET_COND_FLAG(data->cond) & PM_FLAG_BLOCK_HOLDKEY;
595         tmp = display_lock_add_pmlock_node(state, pid, holdkey_block, data->timeout);
596         if (!tmp) {
597                 _E("Failed to acquire lock, state: %d, pid: %d.", state, pid);
598                 return;
599         }
600
601         if (state == S_LCDOFF)
602                 set_process_active(true, pid);
603
604         _I("[%s] locked by %5d with %u ms", states[state].name, pid, data->timeout);
605
606         if (pid < INTERNAL_LOCK_BASE) {
607                 /* for debug */
608                 if (state == S_LCDOFF)
609                         lock_type = PM_LCDOFF_STR;
610                 else if (state == S_LCDDIM)
611                         lock_type = PM_LCDDIM_STR;
612                 else if (state == S_NORMAL)
613                         lock_type = PM_LCDON_STR;
614
615                 if (lock_type) {
616                         /* power lock signal */
617                         ret = gdbus_signal_emit(NULL,
618                                         DEVICED_PATH_DISPLAY,
619                                         DEVICED_INTERFACE_DISPLAY,
620                                         "PowerLock",
621                                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
622                         if (ret < 0)
623                                 _E("Failed to send dbus signal PowerLock.");
624                 }
625         }
626
627         _SD("be requested LOCK info pname(%s), holdkeyblock(%d) flags(%d)",
628             pname, holdkey_block, flags);
629         set_lock_time(pid, pname, state);
630
631         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
632 }
633
634 static void proc_condition_unlock(PMMsg *data)
635 {
636         pid_t pid = data->pid;
637         enum state_t state;
638         PmLockNode *tmp;
639         char pname[PATH_MAX];
640         bool value = false;
641         unsigned int flags;
642         int ret;
643         const char *lock_type = NULL;
644
645         state = GET_COND_STATE(data->cond);
646         if (!state)
647                 return;
648
649         flags = GET_COND_FLAG(data->cond);
650         display_misc_get_process_name(pid, pname);
651
652         tmp = find_node(state, pid);
653         del_node(state, tmp);
654
655         if (state == S_LCDOFF)
656                 set_process_active(false, pid);
657
658         _I("[%s] unlocked by %5d", states[state].name, pid);
659
660         if (pid < INTERNAL_LOCK_BASE) {
661                 /* for debug */
662                 if (state == S_LCDOFF)
663                         lock_type = PM_LCDOFF_STR;
664                 else if (state == S_LCDDIM)
665                         lock_type = PM_LCDDIM_STR;
666                 else if (state == S_NORMAL)
667                         lock_type = PM_LCDON_STR;
668
669                 if (lock_type) {
670                         /* power unlock signal */
671                         ret = gdbus_signal_emit(NULL,
672                                         DEVICED_PATH_DISPLAY,
673                                         DEVICED_INTERFACE_DISPLAY,
674                                         "PowerUnlock",
675                                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
676                         if (ret < 0)
677                                 _E("Failed to send dbus signal PowerUnlock.");
678                 }
679         }
680
681         _SD("be requested UNLOCK info pname(%s) flag(%d)", pname, flags);
682         set_unlock_time(pid, state);
683
684         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
685 }
686
687 static int proc_condition(PMMsg *data)
688 {
689         unsigned int flags;
690
691         if (IS_COND_REQUEST_LOCK(data->cond))
692                 proc_condition_lock(data);
693
694         if (IS_COND_REQUEST_UNLOCK(data->cond))
695                 proc_condition_unlock(data);
696
697         if (!display_conf.timeout_enable)
698                 return 0;
699
700         flags = GET_COND_FLAG(data->cond);
701         if (flags == 0) {
702                 /* guard time for suspend */
703                 if (get_pm_cur_state() == S_LCDOFF)
704                         display_state_transition_reset_state_transition_timeout(states[S_LCDOFF].timeout);
705         } else {
706                 if (flags & PM_FLAG_RESET_TIMER)
707                         display_state_transition_reset_state_transition_timeout(states[get_pm_cur_state()].timeout);
708         }
709
710         if (!display_state_transition_is_there_state_transition_timer())
711                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_TIMEOUT);
712
713         return 0;
714 }
715
716 /* SIGHUP signal handler
717  * For debug... print info to syslog
718  */
719 static void sig_hup(int signo)
720 {
721         _I("received sig hub %d", signo);
722
723         pm_save_logdump();
724 }
725
726 static gboolean lcd_on_expired(void *data)
727 {
728         int lock_state, ret;
729
730         if (lock_timeout_id)
731                 lock_timeout_id = 0;
732
733         /* check state of lock */
734         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
735         if (ret > 0 && lock_state == VCONFKEY_IDLE_LOCK)
736                 return G_SOURCE_REMOVE;
737         else if (ret < 0)
738                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
739
740         /* lock screen is not launched yet, but lcd is on */
741         if (check_lcd_is_on() == false)
742                 lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
743
744         return G_SOURCE_REMOVE;
745 }
746
747 static inline void stop_lock_timer(void)
748 {
749         if (lock_timeout_id) {
750                 g_source_remove(lock_timeout_id);
751                 lock_timeout_id = 0;
752         }
753 }
754
755 static void check_lock_screen(void)
756 {
757         int lock_state, ret;
758
759         stop_lock_timer();
760
761         /* check state of lock */
762         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
763         if (ret < 0 || lock_state == VCONFKEY_IDLE_LOCK)
764                 return;
765
766         /* Use time to check lock is done. */
767         lock_timeout_id = g_timeout_add(display_conf.lock_wait_time,
768             lcd_on_expired, NULL);
769 }
770
771 /* default enter action function */
772 static int default_action(int timeout)
773 {
774         int wakeup_count = -1, pm_cur_state;
775         time_t now;
776         double diff;
777         static time_t last_update_time = 0;
778         static int last_timeout = 0;
779         struct timeval now_tv;
780         bool custom_status;
781         int brightness;
782         bool lcd_paneloff_mode = false;
783
784         if (status != DEVICE_OPS_STATUS_START) {
785                 _E("Display is not started.");
786                 return -EINVAL;
787         }
788
789         if (get_pm_cur_state() != S_SLEEP) {
790                 if ((get_pm_cur_state() == S_NORMAL) &&
791                     lcdon_tv.tv_sec != 0) {
792                         gettimeofday(&now_tv, NULL);
793                         timeout -= DIFF_TIMEVAL_MS(now_tv, lcdon_tv);
794                         lcdon_tv.tv_sec = 0;
795                 }
796                 /* set timer with current state timeout */
797                 display_state_transition_reset_state_transition_timeout(timeout);
798
799                 if (get_pm_cur_state() == S_NORMAL) {
800                         time(&last_update_time);
801                         last_timeout = timeout;
802                 } else {
803                         _I("Timout set: %s state %d ms",
804                             states[get_pm_cur_state()].name, timeout);
805                 }
806         }
807
808         if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) {
809                 power_request_change_state_strict(DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL,
810                         power_get_wakeup_reason(), NULL);
811                 set_setting_pmstate(get_pm_cur_state());
812                 pm_cur_state = get_pm_cur_state();
813                 device_notify(DEVICE_NOTIFIER_LCD, (void *)&pm_cur_state);
814         }
815
816         if ((get_pm_old_state() == S_NORMAL) && (get_pm_cur_state() != S_NORMAL)) {
817                 time(&now);
818                 diff = difftime(now, last_update_time);
819                 _I("S_NORMAL is changed to %s (timeout=%d ms diff=%.0f s).",
820                     states[get_pm_cur_state()].name, last_timeout, diff);
821         }
822
823         switch (get_pm_cur_state()) {
824         case S_NORMAL:
825                 /*
826                  * normal state : backlight on and restore
827                  * the previous brightness
828                  */
829                 if ((get_pm_old_state() == S_LCDOFF) || (get_pm_old_state() == S_SLEEP))
830                         check_lock_screen();
831                 else if (get_pm_old_state() == S_LCDDIM)
832                         display_backlight_update_by_default_brightness();
833
834                 if (check_lcd_is_on() == false)
835                         lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
836                 break;
837
838         case S_LCDDIM:
839                 display_backlight_get_custom_status(&custom_status);
840                 if ((get_pm_old_state() == S_NORMAL) && custom_status) {
841                         display_backlight_get_brightness(&brightness);
842                         display_backlight_set_custom_brightness(brightness);
843                 }
844                 /* lcd dim state : dim the brightness */
845                 display_backlight_set_brightness_by_dim_brightness();
846
847                 if ((get_pm_old_state() == S_LCDOFF) || (get_pm_old_state() == S_SLEEP))
848                         lcd_on_procedure(LCD_DIM, NORMAL_MODE);
849                 break;
850
851         case S_LCDOFF:
852                 if ((get_pm_old_state() != S_SLEEP) && (get_pm_old_state() != S_LCDOFF)) {
853                         stop_lock_timer();
854                         /* lcd off state : turn off the backlight */
855                         if (display_panel_get_dpms_cached_state() == DPMS_ON)
856                                 lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
857                 }
858
859                 display_panel_get_lcd_paneloff_mode(&lcd_paneloff_mode);
860                 if (display_panel_get_dpms_cached_state() == DPMS_ON
861                     || lcd_paneloff_mode)
862                         lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
863                 break;
864
865         case S_SLEEP:
866                 if ((get_pm_old_state() != S_SLEEP) && (get_pm_old_state() != S_LCDOFF))
867                         stop_lock_timer();
868
869                 if (display_panel_get_dpms_cached_state() == DPMS_ON)
870                         lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
871
872                 if (!pm_get_power_lock_support()) {
873                         /* sleep state : set system mode to SUSPEND */
874                         if (get_wakeup_count(&wakeup_count) < 0)
875                                 _E("Wakeup count read error.");
876
877                         if (wakeup_count < 0) {
878                                 _I("Wakup Event. Can not enter suspend mode.");
879                                 goto go_lcd_off;
880                         }
881
882                         if (set_wakeup_count(wakeup_count) < 0) {
883                                 _E("Wakeup count write error.");
884                                 goto go_lcd_off;
885                         }
886                 }
887                 goto go_suspend;
888         }
889
890         return 0;
891
892 go_suspend:
893 #ifdef ENABLE_PM_LOG
894         pm_history_save(PM_LOG_SLEEP, get_pm_cur_state());
895 #endif
896         power_request_change_state(DEVICED_POWER_STATE_SLEEP, HAL_DEVICE_POWER_TRANSITION_REASON_DISPLAY_OFF_TIMEOUT);
897         return 0;
898
899 go_lcd_off:
900         if (!pm_get_power_lock_support()) {
901                 /* Resume !! */
902                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_DEVICE);
903         }
904         return 0;
905 }
906
907 static void default_saving_mode(int onoff)
908 {
909         if (onoff)
910                 set_pm_status_flag(PWRSV_FLAG);
911         else
912                 clear_pm_status_flag(PWRSV_FLAG);
913
914         if (get_pm_cur_state() == S_NORMAL)
915                 display_backlight_update_by_default_brightness();
916 }
917
918 int poll_callback(int condition, PMMsg *data)
919 {
920         static time_t last_t;
921         time_t now;
922
923         if (status != DEVICE_OPS_STATUS_START) {
924                 _E("Display logic is not started.");
925                 return -ECANCELED;
926         }
927
928         if (condition == INPUT_POLL_EVENT) {
929                 if ((get_pm_cur_state() == S_LCDOFF) || (get_pm_cur_state() == S_SLEEP))
930                         _I("Input event signal at Display Off");
931                 time(&now);
932                 if ((last_t != now) ||
933                     (get_pm_cur_state() == S_LCDOFF) ||
934                     (get_pm_cur_state() == S_SLEEP)) {
935                         display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
936                         last_t = now;
937                 }
938         }
939
940         if (condition == PM_CONTROL_EVENT) {
941                 proc_condition(data);
942
943                 if (IS_COND_REQUEST_CHANGE(data->cond))
944                         proc_change_state(data->cond, data->pid);
945         }
946
947         return 0;
948 }
949
950 static int update_setting(int key_idx, int val)
951 {
952         int ret;
953
954         switch (key_idx) {
955         case SETTING_TO_NORMAL:
956                 display_state_transition_update_display_state_timeout_by_priority();
957                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
958                 break;
959         case SETTING_LOW_BATT:
960                 if (display_misc_is_low_battery_state(val)) {
961                         if (!(get_pm_status_flag() & CHRGR_FLAG))
962                                 power_saving_func(true);
963                         set_pm_status_flag(LOWBT_FLAG);
964                 } else {
965                         if (get_pm_status_flag() & PWRSV_FLAG)
966                                 power_saving_func(false);
967                         clear_pm_status_flag(LOWBT_FLAG);
968                         clear_pm_status_flag(BRTCH_FLAG);
969                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, false);
970                         if (ret < 0)
971                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
972                 }
973                 break;
974         case SETTING_CHARGING:
975                 if (val) {
976                         if (get_pm_status_flag() & LOWBT_FLAG) {
977                                 power_saving_func(false);
978                                 clear_pm_status_flag(LOWBT_FLAG);
979                         }
980                         set_pm_status_flag(CHRGR_FLAG);
981                 } else {
982                         int bat_state;
983                         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
984                                 &bat_state);
985                         if (ret < 0) {
986                                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
987                                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
988                         }
989                         if (display_misc_is_low_battery_state(bat_state)) {
990                                 power_saving_func(true);
991                                 set_pm_status_flag(LOWBT_FLAG);
992                         }
993                         clear_pm_status_flag(CHRGR_FLAG);
994                 }
995                 break;
996         case SETTING_BRT_LEVEL:
997                 if (get_pm_status_flag() & PWRSV_FLAG) {
998                         set_pm_status_flag(BRTCH_FLAG);
999                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, true);
1000                         if (ret < 0)
1001                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
1002                         _I("Brightness changed in low battery,"
1003                                 "escape dim state.");
1004                 }
1005                 display_backlight_set_default_brightness(val);
1006                 break;
1007         case SETTING_LOCK_SCREEN:
1008                 set_lock_screen_state(val);
1009                 if (val == VCONFKEY_IDLE_UNLOCK)
1010                         touchled_control_backlight(TOUCHLED_DIRECT_OFF);
1011
1012                 /* LCD on if lock screen show before waiting time */
1013                 if ((get_pm_cur_state() == S_NORMAL) &&
1014                     val == VCONFKEY_IDLE_LOCK &&
1015                     display_panel_get_dpms_cached_state() != DPMS_ON &&
1016                         is_lcdon_blocked() == LCDON_BLOCK_NONE)
1017                         lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
1018                 stop_lock_timer();
1019                 display_state_transition_update_display_state_timeout_by_priority();
1020                 if (get_pm_cur_state() == S_NORMAL)
1021                         display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
1022                 break;
1023         case SETTING_LOCK_SCREEN_BG:
1024                 set_lock_screen_bg_state(val);
1025                 display_state_transition_update_display_state_timeout_by_priority();
1026                 if (get_pm_cur_state() == S_NORMAL)
1027                         display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
1028                 break;
1029         case SETTING_POWER_CUSTOM_BRIGHTNESS:
1030                 if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON)
1031                         display_backlight_set_custom_status(true);
1032                 else
1033                         display_backlight_set_custom_status(false);
1034                 break;
1035
1036         default:
1037                 return -1;
1038         }
1039         return 0;
1040 }
1041
1042 static void check_seed_status(void)
1043 {
1044         int ret = -1;
1045         int tmp = 0;
1046         int bat_state;
1047         int brt = 0;
1048         int lock_state;
1049         int lock_screen_timeout = 0;
1050
1051         /* Charging check */
1052         if (fp_get_charging_status && (fp_get_charging_status(&tmp) == 0) && (tmp > 0))
1053                 set_pm_status_flag(CHRGR_FLAG);
1054
1055         ret = get_setting_brightness(&tmp);
1056         if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
1057                 _I("Failed to read vconf value for brightness.");
1058                 brt = display_conf.pm_default_brightness;
1059                 if (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS) {
1060                         ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
1061                         if (ret < 0)
1062                                 _E("Failed to set vconf value for lcd brightness: %d", vconf_get_ext_errno());
1063                 }
1064                 tmp = brt;
1065         }
1066         _I("Set brightness(%d) from setting app.", tmp);
1067         display_backlight_set_default_brightness(tmp);
1068         display_backlight_set_brightness(tmp);
1069
1070         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
1071         if (ret < 0) {
1072                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
1073                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
1074         }
1075         if (display_misc_is_low_battery_state(bat_state)) {
1076                 if (!(get_pm_status_flag() & CHRGR_FLAG)) {
1077                         power_saving_func(true);
1078                         set_pm_status_flag(LOWBT_FLAG);
1079                 }
1080         }
1081
1082         /* lock screen check */
1083         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1084         if (ret < 0) {
1085                 lock_state = -1;
1086                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
1087         }
1088         set_lock_screen_state(lock_state);
1089         display_state_transition_get_lock_screen_timeout(&lock_screen_timeout);
1090         if (lock_state == VCONFKEY_IDLE_LOCK) {
1091                 states[S_NORMAL].timeout = lock_screen_timeout;
1092                 _I("LCD NORMAL timeout(%d ms) is set"
1093                         " for lock screen.", lock_screen_timeout);
1094         }
1095
1096         return;
1097 }
1098
1099 static void init_lcd_operation(void)
1100 {
1101         const struct device_ops *ops = NULL;
1102
1103         ops = find_device("display");
1104         if (!check_default(ops))
1105                 display_register_dependent_device(ops);
1106
1107         ops = find_device("touchkey");
1108         if (!check_default(ops))
1109                 display_register_dependent_device(ops);
1110
1111         ops = find_device("touchscreen");
1112         if (!check_default(ops))
1113                 display_register_dependent_device(ops);
1114 }
1115
1116 static void exit_lcd_operation(void)
1117 {
1118         display_unregister_dependent_device();
1119 }
1120
1121 enum {
1122         INIT_SETTING = 0,
1123         INIT_INTERFACE,
1124         INIT_POLL,
1125         INIT_FIFO,
1126         INIT_DBUS,
1127         INIT_END
1128 };
1129
1130 static const char *errMSG[INIT_END] = {
1131         [INIT_SETTING] = "setting init error",
1132         [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
1133         [INIT_POLL] = "input devices poll init error",
1134         [INIT_FIFO] = "FIFO poll init error",
1135         [INIT_DBUS] = "d-bus init error",
1136 };
1137
1138 int set_lcd_timeout(int on, int dim, int holdkey_block, const char *name)
1139 {
1140         unsigned int custom_normal_timeout = 0;
1141         unsigned int custom_dim_timeout = 0;
1142
1143         if (on == 0 && dim == 0) {
1144                 _I("LCD timeout changed: default setting");
1145                 display_state_transition_set_custom_timeout(S_NORMAL, 0);
1146                 display_state_transition_set_custom_timeout(S_LCDDIM, 0);
1147         } else if (on < 0 || dim < 0) {
1148                 _E("Failed to set value(on=%d dim=%d).", on, dim);
1149                 return -EINVAL;
1150         } else {
1151                 _I("LCD timeout changed: on=%ds dim=%ds", on, dim);
1152                 display_state_transition_set_custom_timeout(S_NORMAL, SEC_TO_MSEC(on));
1153                 display_state_transition_set_custom_timeout(S_LCDDIM, SEC_TO_MSEC(dim));
1154         }
1155         /* Apply new backlight time */
1156         display_state_transition_update_display_state_timeout_by_priority();
1157         if (get_pm_cur_state() == S_NORMAL)
1158                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
1159
1160         if (holdkey_block) {
1161                 display_lock_set_custom_holdkey_block(true);
1162                 _I("Hold key disabled.");
1163         } else {
1164                 display_lock_set_custom_holdkey_block(false);
1165                 _I("Hold key enabled.");
1166         }
1167
1168         if (custom_change_name) {
1169                 free(custom_change_name);
1170                 custom_change_name = 0;
1171         }
1172
1173         display_state_transition_get_custom_timeout(S_NORMAL, &custom_normal_timeout);
1174         display_state_transition_get_custom_timeout(S_LCDDIM, &custom_dim_timeout);
1175         if (custom_normal_timeout == 0 &&
1176             custom_dim_timeout == 0 &&
1177             !holdkey_block)
1178                 return 0;
1179
1180         custom_change_name = strndup(name, strlen(name));
1181         if (!custom_change_name) {
1182                 _E("Failed to malloc.");
1183                 display_state_transition_set_custom_timeout(S_NORMAL, 0);
1184                 display_state_transition_set_custom_timeout(S_LCDDIM, 0);
1185                 display_lock_set_custom_holdkey_block(false);
1186                 return -ENOMEM;
1187         }
1188
1189         return 0;
1190 }
1191
1192 void reset_lcd_timeout(GDBusConnection *conn,
1193         const gchar     *sender,
1194         const gchar     *unique_name,
1195         gpointer         data)
1196 {
1197         if (!sender)
1198                 return;
1199
1200         if (!custom_change_name)
1201                 return;
1202
1203         if (strcmp(sender, custom_change_name))
1204                 return;
1205
1206         _I("reset lcd timeout: Set default timeout. sender=%s", sender);
1207
1208         free(custom_change_name);
1209         custom_change_name = 0;
1210         display_state_transition_set_custom_timeout(S_NORMAL, 0);
1211         display_state_transition_set_custom_timeout(S_LCDDIM, 0);
1212         display_lock_set_custom_holdkey_block(false);
1213
1214         display_state_transition_update_display_state_timeout_by_priority();
1215         if (get_pm_cur_state() == S_NORMAL)
1216                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
1217 }
1218
1219 static int delayed_init_done(void *data)
1220 {
1221         static bool done = false;
1222
1223         if (!data)
1224                 return done;
1225
1226         done = *(int*)data;
1227         if (!done)
1228                 return done;
1229
1230         _I("Booting done, release booting lock.");
1231         if (disp_plgn->pm_unlock_internal) {
1232                 disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL, PM_SLEEP_MARGIN);
1233                 disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
1234         }
1235
1236         return done;
1237 }
1238
1239 static gboolean delayed_dpms_init_done(gpointer data)
1240 {
1241         int timeout;
1242
1243         if (!display_panel_init_dpms())
1244                 return G_SOURCE_CONTINUE;
1245
1246         switch (get_pm_cur_state()) {
1247         case S_NORMAL:
1248         case S_LCDDIM:
1249                 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
1250                 if (display_conf.timeout_enable) {
1251                         timeout = states[S_NORMAL].timeout;
1252                         /* check minimun lcd on time */
1253                         if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
1254                                 timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
1255                         display_state_transition_reset_state_transition_timeout(timeout);
1256                 }
1257                 break;
1258         case S_LCDOFF:
1259                 lcd_off_procedure(LCD_OFF_BY_EVENT);
1260                 timeout = display_conf.lcdoff_timeout;
1261                 display_state_transition_reset_state_transition_timeout(timeout);
1262                 break;
1263         default:
1264                 break;
1265         }
1266
1267         return G_SOURCE_REMOVE;
1268 }
1269
1270 static void add_timer_for_dpms_init(void)
1271 {
1272         guint id = g_timeout_add(500/* milliseconds */, delayed_dpms_init_done, NULL);
1273         if (id == 0)
1274                 _E("Failed to add display_panel_init_dpms timeout.");
1275 }
1276
1277 static void init_display_states(void *data)
1278 {
1279         struct display_plugin *dp = (struct display_plugin *) data;
1280         for(int i = 0; i < S_END; i++)
1281                 dp->display_states[i] = &states[i];
1282 }
1283 /**
1284  * Power manager Main
1285  *
1286  */
1287
1288 static int display_probe(void *data)
1289 {
1290         int ret;
1291         struct display_plugin *dp = (struct display_plugin *) data;
1292         assert(dp);
1293
1294         dp->config = &display_conf;
1295         init_display_states(dp);
1296         setup_display_plugin_backlight_ops(dp);
1297         dp->set_dim_state = NULL;
1298         dp->get_device_flags = NULL;
1299         setup_display_plugin_backlight_ops(dp);
1300
1301         /**
1302          * load display service
1303          * if there is no display shared library,
1304          * deviced does not provide any method and function of display.
1305          */
1306         ret = display_service_load();
1307         if (ret)
1308                 return ret;
1309
1310         /* display_plugin instance initialization */
1311         init_pm_internal(data);
1312         disp_plgn->device_flags_to_string = __device_flags_to_string;
1313
1314         if (battery_plgn->handle) {
1315                 fp_get_charging_status = dlsym(battery_plgn->handle, "get_charging_status");
1316                 if (!fp_get_charging_status)
1317                         _E("Failed to obtain address of get_charging_status");
1318         } else
1319                 _I("There is no battery module.");
1320
1321         return 0;
1322 }
1323
1324 static int input_init_handler(void)
1325 {
1326         if (!display_conf.input_support)
1327                 remove_device_by_devname("input");
1328
1329         return 0;
1330 }
1331
1332 static int power_resume_from_echomem_callback(void *data)
1333 {
1334         system_wakeup_flag = true;
1335         if (check_wakeup_src() == EVENT_DEVICE)
1336                 /* system waked up by devices */
1337                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_DEVICE);
1338         else
1339                 /* system waked up by user input */
1340                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
1341
1342         return 0;
1343 }
1344
1345 static int poweroff_triggered_callback(void *udata)
1346 {
1347         int val = (int)(intptr_t) udata;
1348
1349         switch (val) {
1350         case VCONFKEY_SYSMAN_POWER_OFF_NONE:
1351                 clear_pm_status_flag(PWROFF_FLAG);
1352                 break;
1353         case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
1354         case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
1355                 set_pm_status_flag(PWROFF_FLAG);
1356                 break;
1357         }
1358
1359         return 0;
1360 }
1361
1362 static void esd_action(void)
1363 {
1364         const struct device_ops *touchscreen_ops = NULL;
1365
1366         _I("ESD on");
1367
1368         touchscreen_ops = find_device("touchscreen");
1369
1370         if (!check_default(touchscreen_ops))
1371                 touchscreen_ops->stop(NORMAL_MODE);
1372         display_panel_set_panel_state_by_off_state(NORMAL_MODE);
1373         display_panel_set_panel_state_by_on_state(NORMAL_MODE);
1374         if (!check_default(touchscreen_ops))
1375                 touchscreen_ops->start(NORMAL_MODE);
1376 }
1377
1378 static void lcd_uevent_changed(struct udev_device *dev)
1379 {
1380         const char *devpath;
1381         const char *action;
1382
1383         devpath = udev_device_get_devpath(dev);
1384         if (!devpath)
1385                 return;
1386
1387         if (!fnmatch(LCD_ESD_PATH, devpath, 0)) {
1388                 action = udev_device_get_action(dev);
1389                 if (!strcmp(action, UDEV_CHANGE))
1390                         esd_action();
1391         }
1392 }
1393
1394 static const struct uevent_handler lcd_uevent_ops = {
1395         .subsystem      = LCD_EVENT_SUBSYSTEM,
1396         .uevent_func    = lcd_uevent_changed,
1397         .data           = NULL,
1398 };
1399
1400 static void display_init(void *data)
1401 {
1402         int ret, i;
1403         unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS);
1404         int timeout = 0;
1405
1406         _I("Start power manager.");
1407
1408         signal(SIGHUP, sig_hup);
1409
1410         power_saving_func = default_saving_mode;
1411
1412         /* load configutation */
1413         ret = display_load_config(&display_conf);
1414         if (ret < 0)
1415                 _W("Failed to load '%s', use default value: %d",
1416                     DISPLAY_CONF_FILE, ret);
1417
1418         register_kernel_uevent_control(&lcd_uevent_ops);
1419
1420         register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
1421         register_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
1422         register_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
1423         register_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
1424         register_notifier(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
1425         register_notifier(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback);
1426
1427         init_save_userlock();
1428
1429         for (i = INIT_SETTING; i < INIT_END; i++) {
1430                 switch (i) {
1431                 case INIT_SETTING:
1432                         ret = init_setting(update_setting);
1433                         break;
1434                 case INIT_INTERFACE:
1435                         if (display_conf.timeout_enable)
1436                                 display_initialize_display_state_timeout_from_setting();
1437                         ret = init_sysfs(flags);
1438                         break;
1439                 case INIT_POLL:
1440                         _I("input init");
1441                         ret = input_init_handler();
1442
1443                         pm_lock_detector_init();
1444                         break;
1445                 case INIT_DBUS:
1446                         _I("Dbus init.");
1447                         ret = init_pm_dbus();
1448                         break;
1449                 }
1450                 if (ret != 0) {
1451                         _E("Failed to init: %s", errMSG[i]);
1452                         break;
1453                 }
1454         }
1455
1456         if (i == INIT_END) {
1457                 display_ops_init(NULL);
1458 #ifdef ENABLE_PM_LOG
1459                 pm_history_init();
1460 #endif
1461                 init_lcd_operation();
1462                 check_seed_status();
1463
1464                 /* In smd test, TSP should be turned off if display panel is not existed. */
1465                 if (display_panel_get_dpms_cached_state() == -ENOENT) {
1466                         _I("Display panel is not existed.");
1467                         lcd_direct_control(DPMS_OFF, NORMAL_MODE);
1468                         exit_lcd_operation();
1469                 }
1470
1471                 /* wm_ready needs to be checked
1472                  * since display manager can be launched later than deviced.
1473                  * In the case, display cannot be turned on at the first booting */
1474                 // wm_ready = check_wm_ready();
1475                 if (display_panel_init_dpms()) {
1476                         if (is_lcdon_blocked() != LCDON_BLOCK_NONE)
1477                                 lcd_off_procedure(LCD_OFF_BY_EVENT);
1478                         else
1479                                 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
1480                 } else {
1481                         add_timer_for_dpms_init();
1482                 }
1483
1484                 if (display_conf.lcd_always_on) {
1485                         _I("LCD always on.");
1486                         display_state_transition_set_transition_table_display_state(S_NORMAL, S_NORMAL, EVENT_TIMEOUT);
1487                 }
1488
1489                 if (flags & WITHOUT_STARTNOTI) {        /* start without noti */
1490                         _I("Start Power managing without noti");
1491                         power_request_change_state_strict(DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL,
1492                                 HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN, NULL);
1493                         /*
1494                          * Lock lcd off until booting is done.
1495                          * deviced guarantees all booting script is executing.
1496                          * Last script of booting unlocks this suspend blocking state.
1497                          */
1498                         if (disp_plgn->pm_lock_internal)
1499                                 disp_plgn->pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF,
1500                                                 STAY_CUR_STATE, DELAYED_INIT_WATING_TIME);
1501
1502                         /* Initial display state right after the booting done */
1503                         if (is_lcdon_blocked())
1504                                 set_pm_cur_state(S_LCDOFF);
1505                         else
1506                                 set_pm_cur_state(S_NORMAL);
1507                         ret = vconf_set_int(VCONFKEY_PM_STATE, get_pm_cur_state());
1508                         if (ret < 0)
1509                                 _E("Failed to set vconf value for pm cur state: %d", vconf_get_ext_errno());
1510
1511                         status = DEVICE_OPS_STATUS_START;
1512                         if (display_conf.timeout_enable) {
1513                                 timeout = states[S_NORMAL].timeout;
1514                                 /* check minimun lcd on time */
1515                                 if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
1516                                         timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
1517
1518                                 if (disp_plgn->pm_lock_internal)
1519                                         disp_plgn->pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL,
1520                                                         STAY_CUR_STATE, timeout);
1521                         }
1522
1523                 }
1524
1525                 set_display_init_direction(display_conf.display_init_direction);
1526         }
1527 }
1528
1529 static void display_exit(void *data)
1530 {
1531         int i = INIT_END;
1532
1533         status = DEVICE_OPS_STATUS_STOP;
1534
1535         /* Set current state to S_NORMAL */
1536         set_pm_cur_state(S_NORMAL);
1537         set_setting_pmstate(get_pm_cur_state());
1538         /* timeout is not needed */
1539         display_state_transition_reset_state_transition_timeout(TIMEOUT_NONE);
1540
1541         unregister_kernel_uevent_control(&lcd_uevent_ops);
1542
1543         display_ops_exit(NULL);
1544
1545         for (i = i - 1; i >= INIT_SETTING; i--) {
1546                 switch (i) {
1547                 case INIT_SETTING:
1548                         exit_setting();
1549                         break;
1550                 case INIT_INTERFACE:
1551                         exit_sysfs();
1552                         break;
1553                 case INIT_POLL:
1554                         unregister_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
1555                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
1556                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
1557                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
1558                         unregister_notifier(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
1559
1560                         break;
1561                 }
1562         }
1563
1564         exit_lcd_operation();
1565         free_lock_info_list();
1566
1567         /* free display service */
1568         display_service_free();
1569
1570         _I("Stop power manager.");
1571 }
1572
1573 static int display_start(enum device_flags flags)
1574 {
1575         /* NORMAL MODE */
1576         if (flags & NORMAL_MODE) {
1577                 if (flags & LCD_PANEL_OFF_MODE)
1578                         /* standby on */
1579                         display_panel_set_panel_state_by_standby_state(true);
1580                 else
1581                         /* normal lcd on */
1582                         display_panel_set_panel_state_by_on_state(flags);
1583
1584                 return 0;
1585         }
1586
1587         /* CORE LOGIC MODE */
1588         if (!(flags & CORE_LOGIC_MODE))
1589                 return 0;
1590
1591         if (status == DEVICE_OPS_STATUS_START)
1592                 return -EALREADY;
1593
1594         if (display_probe(NULL) < 0)
1595                 return -EPERM;
1596
1597         display_init(NULL);
1598
1599         return 0;
1600 }
1601
1602 static int display_stop(enum device_flags flags)
1603 {
1604         /* NORMAL MODE */
1605         if (flags & NORMAL_MODE || flags & FORCE_OFF_MODE) {
1606                 display_panel_set_panel_state_by_off_state(flags);
1607                 return 0;
1608         }
1609
1610         /* CORE LOGIC MODE */
1611         if (!(flags & CORE_LOGIC_MODE))
1612                 return 0;
1613
1614         if (status == DEVICE_OPS_STATUS_STOP)
1615                 return -EALREADY;
1616
1617         display_exit(NULL);
1618
1619         return 0;
1620 }
1621
1622 static int display_status(void)
1623 {
1624         return status;
1625 }
1626
1627 static const struct device_ops display_plugin_device_ops = {
1628         .disable_auto_init = true,
1629         DECLARE_NAME_LEN("display-plugin"),
1630         .probe    = display_probe,
1631         .init     = display_init,
1632         .exit     = display_exit,
1633         .start    = display_start,
1634         .stop     = display_stop,
1635         .status   = display_status,
1636 };
1637
1638 DEVICE_OPS_REGISTER(&display_plugin_device_ops)
1639
1640 static void __CONSTRUCTOR__ initialize(void)
1641 {
1642         disp_plgn = get_var_display_plugin();
1643         if (!disp_plgn)
1644                 _E("Failed to get display plugin variable.");
1645
1646         backlight_ops = get_var_backlight_ops();
1647         if (!backlight_ops)
1648                 _E("Failed to get backlight operator variable.");
1649
1650         battery_plgn = get_var_battery_plugin();
1651         if (!battery_plgn)
1652                 _E("Failed to get battery plugin variable.");
1653 }
1654 /**
1655  * @}
1656  */