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