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