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