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