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