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