display: Relocate lcd_on_direct()
[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
104 static int default_proc_change_state(unsigned int cond, pid_t pid);
105 static int (*proc_change_state)(unsigned int cond, pid_t pid) = default_proc_change_state;
106
107 static struct state states[S_END] = {
108         { S_START,    "S_START",    NULL,          NULL,           NULL,          NULL            },
109         { S_NORMAL,   "S_NORMAL",   NULL,          NULL,           NULL,          NULL            },
110         { S_LCDDIM,   "S_LCDDIM",   NULL,          NULL,           NULL,          NULL            },
111         { S_LCDOFF,   "S_LCDOFF",   NULL,          NULL,           NULL,          NULL            },
112         { S_STANDBY,  "S_STANDBY",  NULL,          NULL,           NULL,          NULL            },
113         { S_SLEEP,    "S_SLEEP",    NULL,          NULL,           NULL,          NULL            },
114         { S_POWEROFF, "S_POWEROFF", NULL,          NULL,           NULL,          NULL            },
115 };
116
117 #define TIMEOUT_NONE            (-1)
118
119 #define DELAYED_INIT_WATING_TIME        60000   /* 1 minute */
120
121 #define LOCK_SCREEN_WATING_TIME         300     /* 0.3 second */
122 #define LONG_PRESS_INTERVAL             2       /* 2 seconds */
123 #define SAMPLING_INTERVAL               1       /* 1 sec */
124 #define BRIGHTNESS_CHANGE_STEP          10
125 #define LCD_ALWAYS_ON                   0
126 #define ACCEL_SENSOR_ON                 1
127 #define CONTINUOUS_SAMPLING             1
128 #define LCDOFF_TIMEOUT                  300     /* milli second */
129
130 static struct display_config display_conf = {
131         .lock_wait_time         = LOCK_SCREEN_WATING_TIME,
132         .longpress_interval     = LONG_PRESS_INTERVAL,
133         .lightsensor_interval   = SAMPLING_INTERVAL,
134         .lcdoff_timeout         = LCDOFF_TIMEOUT,
135         .pm_default_brightness = 80,
136         .brightness_change_step = BRIGHTNESS_CHANGE_STEP,
137         .lcd_always_on          = LCD_ALWAYS_ON,
138         .dimming                = 1,
139         .framerate_app          = {0, 0, 0, 0},
140         .control_display        = 0,
141         .powerkey_doublepress   = 0,
142         .accel_sensor_on        = ACCEL_SENSOR_ON,
143         .continuous_sampling    = CONTINUOUS_SAMPLING,
144         .timeout_enable         = true,
145         .input_support          = true,
146         .display_init_direction = DISPLAY_INIT_DIRECTION_HORIZONTAL,
147         .aod_enter_level        = 40,
148         .aod_tsp                = true,
149         .touch_wakeup           = false,
150         .display_on_usb_conn_changed = true,
151         .display_dpms_type      = DISPLAY_DPMS_TYPE_WINDOW_MANAGER,
152 };
153
154 struct display_function_info display_info = {
155         .update_auto_brightness         = NULL,
156         .set_autobrightness_min         = NULL,
157         .reset_autobrightness_min       = NULL,
158         .face_detection                 = NULL,
159 };
160
161 inline const struct display_config* get_var_display_config()
162 {
163         return &display_conf;
164 }
165
166 inline struct state* state_st(enum state_t state)
167 {
168         return &states[state];
169 }
170
171 static const char* __device_flags_to_string(enum device_flags flags)
172 {
173         if (flags & LCD_ON_BY_GESTURE)
174                 return GESTURE_STR;
175         else if (flags & (LCD_ON_BY_POWER_KEY | LCD_OFF_BY_POWER_KEY))
176                 return POWER_KEY_STR;
177         else if (flags & (LCD_ON_BY_EVENT | LCD_OFF_BY_EVENT))
178                 return EVENT_STR;
179         else if (flags & LCD_ON_BY_TOUCH)
180                 return TOUCH_STR;
181         else if (flags & LCD_OFF_BY_TIMEOUT)
182                 return TIMEOUT_STR;
183         else
184                 return UNKNOWN_STR;
185 }
186
187 static gboolean timer_refresh_cb(gpointer data)
188 {
189         struct state *st;
190
191         /* state transition */
192         set_pm_old_state(get_pm_cur_state());
193         set_pm_cur_state(S_NORMAL);
194         st = &states[get_pm_cur_state()];
195
196         display_state_transition_do_state_action(st->timeout);
197
198         return 0;
199 }
200
201 int custom_lcdon(int timeout)
202 {
203         struct state *st;
204
205         if (timeout <= 0)
206                 return -EINVAL;
207
208         if (display_panel_get_dpms_cached_state() != DPMS_ON)
209                 display_panel_lcd_on_direct(LCD_ON_BY_GESTURE);
210
211         _I("Custom lcd on timeout(%d ms).", timeout);
212         if (set_custom_lcdon_timeout(timeout) == true)
213                 display_state_transition_update_display_state_timeout_by_priority();
214
215         /* state transition */
216         set_pm_old_state(get_pm_cur_state());
217         set_pm_cur_state(S_NORMAL);
218         st = &states[get_pm_cur_state()];
219
220         display_state_transition_do_state_action(st->timeout);
221
222         g_idle_add(timer_refresh_cb, NULL);
223
224         return 0;
225 }
226
227 int custom_lcdoff(enum device_flags flag)
228 {
229         struct state *st;
230
231         if (display_lock_is_state_locked(S_NORMAL) || display_lock_is_state_locked(S_LCDDIM)) {
232                 /*
233                  * When another proccess is normal lock, device is received call then,
234                  * call app can be changed to lcd state by proximity.
235                  * If proximity is near then normal lock will be unlocked.
236                  */
237                 if (flag & LCD_OFF_BY_PROXIMITY) {
238                         _I("custom lcd off by proximity, delete normal lock");
239                         display_lock_release_lock_all(S_NORMAL);
240                 } else {
241                         _I("skip custom lcd off");
242                         return -ECANCELED;
243                 }
244         }
245
246         _I("custom lcd off by flag(%d)", flag);
247         if (display_panel_get_dpms_cached_state() == DPMS_ON)
248                 display_panel_lcd_off_procedure(flag);
249
250         if (set_custom_lcdon_timeout(0) == true)
251                 display_state_transition_update_display_state_timeout_by_priority();
252
253         /* state transition */
254         set_pm_old_state(get_pm_cur_state());
255         set_pm_cur_state(S_LCDOFF);
256         st = &states[get_pm_cur_state()];
257
258         display_state_transition_do_state_action(st->timeout);
259
260         return 0;
261 }
262
263 int display_on_by_reason(const char *reason, int timeout)
264 {
265         struct state *st;
266         int flag;
267         int str_len;
268
269         str_len = strlen(reason);
270
271         if (!strncmp(reason, GESTURE_STR, str_len))
272                 flag = LCD_ON_BY_GESTURE;
273         else if (!strncmp(reason, EVENT_STR, str_len))
274                 flag = LCD_ON_BY_EVENT;
275         else {
276                 _E("Reason is unknown(%s)", reason);
277                 return -EINVAL;
278         }
279
280         if (timeout <= 0) {
281                 _E("Cannot setting timeout %d", timeout);
282                 return -EINVAL;
283         }
284
285         if (display_panel_get_dpms_cached_state() != DPMS_ON)
286                 display_panel_lcd_on_direct(flag);
287
288         _I("platform lcd on by %s (%d ms)", reason, timeout);
289         if (set_custom_lcdon_timeout(timeout) == true)
290                 display_state_transition_update_display_state_timeout_by_priority();
291
292         /* state transition */
293         set_pm_old_state(get_pm_cur_state());
294         set_pm_cur_state(S_NORMAL);
295         st = &states[get_pm_cur_state()];
296
297         display_state_transition_do_state_action(st->timeout);
298
299         return 0;
300 }
301
302 int display_off_by_reason(const char *reason)
303 {
304         struct state *st;
305         int flag;
306         int str_len;
307
308         str_len = strlen(reason);
309
310         if (!strncmp(reason, GESTURE_STR, str_len)) {
311                 if (display_lock_is_state_locked(S_NORMAL) || display_lock_is_state_locked(S_LCDDIM)) {
312                         _I("skip platform lcd off by gesture");
313                         return -ECANCELED;
314                 }
315                 flag = LCD_OFF_BY_GESTURE;
316         } else if (!strncmp(reason, PALM_STR, str_len)) {
317                 display_lock_release_lock_all(S_NORMAL);
318                 display_lock_release_lock_all(S_LCDDIM);
319
320                 flag = LCD_OFF_BY_PALM;
321         } else {
322                 _E("Reason is unknown(%s)", reason);
323                 return -EINVAL;
324         }
325
326         _I("platform lcd off by %s", reason);
327         if (display_panel_get_dpms_cached_state() == DPMS_ON)
328                 display_panel_lcd_off_procedure(flag);
329
330         /* state transition */
331         set_pm_old_state(get_pm_cur_state());
332         set_pm_cur_state(S_LCDOFF);
333         st = &states[get_pm_cur_state()];
334
335         display_state_transition_do_state_action(st->timeout);
336
337         return 0;
338 }
339
340 static void default_proc_change_state_action(enum state_t next, int timeout)
341 {
342         struct state *st;
343
344         set_pm_old_state(get_pm_cur_state());
345         set_pm_cur_state(next);
346
347         st = &states[get_pm_cur_state()];
348
349         if (timeout < 0)
350                 display_state_transition_do_state_action(st->timeout);
351         else
352                 display_state_transition_do_state_action(timeout);
353 }
354
355 static int default_proc_change_state(unsigned int cond, pid_t pid)
356 {
357         enum state_t next;
358
359         next = GET_COND_STATE(cond);
360         _I("Change process(%d) state to %s.", pid, states[next].name);
361
362         switch (next) {
363         case S_NORMAL:
364                 if (display_panel_get_dpms_cached_state() != DPMS_ON)
365                         display_panel_lcd_on_direct(LCD_ON_BY_EVENT);
366                 display_state_transition_update_lock_screen_timeout(LOCK_SCREEN_CONTROL_TIMEOUT);
367                 default_proc_change_state_action(next, -1);
368                 break;
369         case S_LCDDIM:
370                 default_proc_change_state_action(next, -1);
371                 break;
372         case S_LCDOFF:
373                 if (display_panel_get_dpms_cached_state() == DPMS_ON)
374                         display_panel_lcd_off_procedure(LCD_OFF_BY_EVENT);
375                 if (set_custom_lcdon_timeout(0))
376                         display_state_transition_update_display_state_timeout_by_priority();
377                 default_proc_change_state_action(next, -1);
378                 break;
379         case S_SLEEP:
380                 _I("Dangerous requests.");
381                 /* at first LCD_OFF and then goto sleep */
382                 /* state transition */
383                 default_proc_change_state_action(S_LCDOFF, TIMEOUT_NONE);
384                 display_lock_release_lock_all(S_NORMAL);
385                 display_lock_release_lock_all(S_LCDDIM);
386                 display_lock_release_lock_all(S_LCDOFF);
387                 if (display_panel_is_lcd_on_state_broadcasted()) {
388                         _I("broadcast lcd off signal at non-lcd device");
389                         broadcast_lcd_off(SIGNAL_PRE, 0);
390                         broadcast_lcd_off(SIGNAL_POST, 0);
391                 }
392                 default_proc_change_state_action(S_SLEEP, TIMEOUT_NONE);
393                 break;
394
395         default:
396                 return -EINVAL;
397         }
398
399         return 0;
400 }
401
402 static void proc_condition_lock(PMMsg *data)
403 {
404         char pname[PATH_MAX];
405         pid_t pid = data->pid;
406         enum state_t state;
407         int ret;
408         bool value = true;
409         unsigned int flags;
410         const char *lock_type = NULL;
411
412         state = GET_COND_STATE(data->cond);
413         if (state == S_START)
414                 return;
415
416         flags = GET_COND_FLAG(data->cond);
417         display_misc_get_process_name(pid, pname);
418
419         if ((state == S_LCDOFF) && (get_pm_cur_state() == S_SLEEP) &&
420             (pm_get_power_lock() == POWER_UNLOCK))
421                 proc_change_state(data->cond, INTERNAL_LOCK_PM);
422
423         ret = display_lock_request_lock(state, pid, data->timeout);
424         if (ret == -EALREADY)
425                 ret = display_lock_update_lock(state, pid, data->timeout);
426
427         if (ret != 0) {
428                 _E("Failed to acquire lock, state: %d, pid: %d.", state, pid);
429                 return;
430         }
431
432         if (state == S_LCDOFF)
433                 set_process_active(true, pid);
434
435         _I("[%s] locked by %5d with %u ms", states[state].name, pid, data->timeout);
436
437         if (pid < INTERNAL_LOCK_BASE) {
438                 /* for debug */
439                 if (state == S_LCDOFF)
440                         lock_type = PM_LCDOFF_STR;
441                 else if (state == S_LCDDIM)
442                         lock_type = PM_LCDDIM_STR;
443                 else if (state == S_NORMAL)
444                         lock_type = PM_LCDON_STR;
445
446                 if (lock_type) {
447                         /* power lock signal */
448                         ret = gdbus_signal_emit(NULL,
449                                         DEVICED_PATH_DISPLAY,
450                                         DEVICED_INTERFACE_DISPLAY,
451                                         "PowerLock",
452                                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
453                         if (ret < 0)
454                                 _E("Failed to send dbus signal PowerLock.");
455                 }
456         }
457
458         _SD("be requested LOCK info pname(%s), flags(%d)",
459             pname, flags);
460         set_lock_time(pid, pname, state);
461
462         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
463 }
464
465 static void proc_condition_unlock(PMMsg *data)
466 {
467         pid_t pid = data->pid;
468         enum state_t state;
469         char pname[PATH_MAX];
470         bool value = false;
471         unsigned int flags;
472         int ret;
473         const char *lock_type = NULL;
474
475         state = GET_COND_STATE(data->cond);
476         if (!state)
477                 return;
478
479         flags = GET_COND_FLAG(data->cond);
480         display_misc_get_process_name(pid, pname);
481
482         display_lock_release_lock(state, pid);
483
484         if (state == S_LCDOFF)
485                 set_process_active(false, pid);
486
487         _I("[%s] unlocked by %5d", states[state].name, pid);
488
489         if (pid < INTERNAL_LOCK_BASE) {
490                 /* for debug */
491                 if (state == S_LCDOFF)
492                         lock_type = PM_LCDOFF_STR;
493                 else if (state == S_LCDDIM)
494                         lock_type = PM_LCDDIM_STR;
495                 else if (state == S_NORMAL)
496                         lock_type = PM_LCDON_STR;
497
498                 if (lock_type) {
499                         /* power unlock signal */
500                         ret = gdbus_signal_emit(NULL,
501                                         DEVICED_PATH_DISPLAY,
502                                         DEVICED_INTERFACE_DISPLAY,
503                                         "PowerUnlock",
504                                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
505                         if (ret < 0)
506                                 _E("Failed to send dbus signal PowerUnlock.");
507                 }
508         }
509
510         _SD("be requested UNLOCK info pname(%s) flag(%d)", pname, flags);
511         set_unlock_time(pid, state);
512
513         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
514 }
515
516 static int proc_condition(PMMsg *data)
517 {
518         unsigned int flags;
519
520         if (IS_COND_REQUEST_LOCK(data->cond))
521                 proc_condition_lock(data);
522
523         if (IS_COND_REQUEST_UNLOCK(data->cond))
524                 proc_condition_unlock(data);
525
526         if (!display_conf.timeout_enable)
527                 return 0;
528
529         flags = GET_COND_FLAG(data->cond);
530         if (flags == 0) {
531                 /* guard time for suspend */
532                 if (get_pm_cur_state() == S_LCDOFF)
533                         display_state_transition_reset_state_transition_timeout(states[S_LCDOFF].timeout);
534         } else {
535                 if (flags & PM_FLAG_RESET_TIMER)
536                         display_state_transition_reset_state_transition_timeout(states[get_pm_cur_state()].timeout);
537         }
538
539         if (!display_state_transition_is_there_state_transition_timer())
540                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_TIMEOUT);
541
542         return 0;
543 }
544
545 /* SIGHUP signal handler
546  * For debug... print info to syslog
547  */
548 static void sig_hup(int signo)
549 {
550         _I("received sig hub %d", signo);
551
552         pm_save_logdump();
553 }
554
555 static void default_saving_mode(int onoff)
556 {
557         if (onoff)
558                 set_pm_status_flag(PWRSV_FLAG);
559         else
560                 clear_pm_status_flag(PWRSV_FLAG);
561
562         if (get_pm_cur_state() == S_NORMAL)
563                 display_backlight_update_by_default_brightness();
564 }
565
566 int poll_callback(int condition, PMMsg *data)
567 {
568         static time_t last_t;
569         time_t now;
570
571         display_get_display_ops_status(&status);
572         if (status != DEVICE_OPS_STATUS_START) {
573                 _E("Display logic is not started.");
574                 return -ECANCELED;
575         }
576
577         if (condition == INPUT_POLL_EVENT) {
578                 if ((get_pm_cur_state() == S_LCDOFF) || (get_pm_cur_state() == S_SLEEP))
579                         _I("Input event signal at Display Off");
580                 time(&now);
581                 if ((last_t != now) ||
582                     (get_pm_cur_state() == S_LCDOFF) ||
583                     (get_pm_cur_state() == S_SLEEP)) {
584                         display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
585                         last_t = now;
586                 }
587         }
588
589         if (condition == PM_CONTROL_EVENT) {
590                 proc_condition(data);
591
592                 if (IS_COND_REQUEST_CHANGE(data->cond))
593                         proc_change_state(data->cond, data->pid);
594         }
595
596         return 0;
597 }
598
599 static int update_setting(int key_idx, int val)
600 {
601         int ret;
602
603         switch (key_idx) {
604         case SETTING_TO_NORMAL:
605                 display_state_transition_update_display_state_timeout_by_priority();
606                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
607                 break;
608         case SETTING_LOW_BATT:
609                 if (display_misc_is_low_battery_state(val)) {
610                         if (!(get_pm_status_flag() & CHRGR_FLAG))
611                                 power_saving_func(true);
612                         set_pm_status_flag(LOWBT_FLAG);
613                 } else {
614                         if (get_pm_status_flag() & PWRSV_FLAG)
615                                 power_saving_func(false);
616                         clear_pm_status_flag(LOWBT_FLAG);
617                         clear_pm_status_flag(BRTCH_FLAG);
618                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, false);
619                         if (ret < 0)
620                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
621                 }
622                 break;
623         case SETTING_CHARGING:
624                 if (val) {
625                         if (get_pm_status_flag() & LOWBT_FLAG) {
626                                 power_saving_func(false);
627                                 clear_pm_status_flag(LOWBT_FLAG);
628                         }
629                         set_pm_status_flag(CHRGR_FLAG);
630                 } else {
631                         int bat_state;
632                         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
633                                 &bat_state);
634                         if (ret < 0) {
635                                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
636                                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
637                         }
638                         if (display_misc_is_low_battery_state(bat_state)) {
639                                 power_saving_func(true);
640                                 set_pm_status_flag(LOWBT_FLAG);
641                         }
642                         clear_pm_status_flag(CHRGR_FLAG);
643                 }
644                 break;
645         case SETTING_BRT_LEVEL:
646                 if (get_pm_status_flag() & PWRSV_FLAG) {
647                         set_pm_status_flag(BRTCH_FLAG);
648                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, true);
649                         if (ret < 0)
650                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
651                         _I("Brightness changed in low battery,"
652                                 "escape dim state.");
653                 }
654                 display_backlight_set_default_brightness(val);
655                 break;
656         case SETTING_LOCK_SCREEN:
657                 set_lock_screen_state(val);
658                 if (val == VCONFKEY_IDLE_UNLOCK)
659                         touchled_control_backlight(TOUCHLED_DIRECT_OFF);
660
661                 /* LCD on if lock screen show before waiting time */
662                 if ((get_pm_cur_state() == S_NORMAL) &&
663                     val == VCONFKEY_IDLE_LOCK &&
664                     display_panel_get_dpms_cached_state() != DPMS_ON &&
665                         is_lcdon_blocked() == LCDON_BLOCK_NONE)
666                         display_panel_lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
667                 display_state_transition_update_display_state_timeout_by_priority();
668                 if (get_pm_cur_state() == S_NORMAL)
669                         display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
670                 break;
671         case SETTING_LOCK_SCREEN_BG:
672                 set_lock_screen_bg_state(val);
673                 display_state_transition_update_display_state_timeout_by_priority();
674                 if (get_pm_cur_state() == S_NORMAL)
675                         display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
676                 break;
677         case SETTING_POWER_CUSTOM_BRIGHTNESS:
678                 if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON)
679                         display_backlight_set_custom_status(true);
680                 else
681                         display_backlight_set_custom_status(false);
682                 break;
683
684         default:
685                 return -1;
686         }
687         return 0;
688 }
689
690 static void check_seed_status(void)
691 {
692         int ret = -1;
693         int tmp = 0;
694         int bat_state;
695         int brt = 0;
696         int lock_state;
697         int lock_screen_timeout = 0;
698
699         /* Charging check */
700         if (fp_get_charging_status && (fp_get_charging_status(&tmp) == 0) && (tmp > 0))
701                 set_pm_status_flag(CHRGR_FLAG);
702
703         ret = get_setting_brightness(&tmp);
704         if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
705                 _I("Failed to read vconf value for brightness.");
706                 brt = display_conf.pm_default_brightness;
707                 if (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS) {
708                         ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
709                         if (ret < 0)
710                                 _E("Failed to set vconf value for lcd brightness: %d", vconf_get_ext_errno());
711                 }
712                 tmp = brt;
713         }
714         _I("Set brightness(%d) from setting app.", tmp);
715         display_backlight_set_default_brightness(tmp);
716         display_backlight_set_brightness(tmp);
717
718         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
719         if (ret < 0) {
720                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
721                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
722         }
723         if (display_misc_is_low_battery_state(bat_state)) {
724                 if (!(get_pm_status_flag() & CHRGR_FLAG)) {
725                         power_saving_func(true);
726                         set_pm_status_flag(LOWBT_FLAG);
727                 }
728         }
729
730         /* lock screen check */
731         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
732         if (ret < 0) {
733                 lock_state = -1;
734                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
735         }
736         set_lock_screen_state(lock_state);
737         display_state_transition_get_lock_screen_timeout(&lock_screen_timeout);
738         if (lock_state == VCONFKEY_IDLE_LOCK) {
739                 states[S_NORMAL].timeout = lock_screen_timeout;
740                 _I("LCD NORMAL timeout(%d ms) is set"
741                         " for lock screen.", lock_screen_timeout);
742         }
743
744         return;
745 }
746
747 static void init_lcd_operation(void)
748 {
749         const struct device_ops *ops = NULL;
750
751         ops = find_device("display");
752         if (!check_default(ops))
753                 display_register_dependent_device(ops);
754
755         ops = find_device("touchkey");
756         if (!check_default(ops))
757                 display_register_dependent_device(ops);
758
759         ops = find_device("touchscreen");
760         if (!check_default(ops))
761                 display_register_dependent_device(ops);
762 }
763
764 static void exit_lcd_operation(void)
765 {
766         display_unregister_dependent_device();
767 }
768
769 enum {
770         INIT_SETTING = 0,
771         INIT_INTERFACE,
772         INIT_POLL,
773         INIT_FIFO,
774         INIT_DBUS,
775         INIT_END
776 };
777
778 static const char *errMSG[INIT_END] = {
779         [INIT_SETTING] = "setting init error",
780         [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
781         [INIT_POLL] = "input devices poll init error",
782         [INIT_FIFO] = "FIFO poll init error",
783         [INIT_DBUS] = "d-bus init error",
784 };
785
786 int set_lcd_timeout(int on, int dim, const char *name)
787 {
788         unsigned int custom_normal_timeout = 0;
789         unsigned int custom_dim_timeout = 0;
790
791         if (on == 0 && dim == 0) {
792                 _I("LCD timeout changed: default setting");
793                 display_state_transition_set_custom_timeout(S_NORMAL, 0);
794                 display_state_transition_set_custom_timeout(S_LCDDIM, 0);
795         } else if (on < 0 || dim < 0) {
796                 _E("Failed to set value(on=%d dim=%d).", on, dim);
797                 return -EINVAL;
798         } else {
799                 _I("LCD timeout changed: on=%ds dim=%ds", on, dim);
800                 display_state_transition_set_custom_timeout(S_NORMAL, SEC_TO_MSEC(on));
801                 display_state_transition_set_custom_timeout(S_LCDDIM, SEC_TO_MSEC(dim));
802         }
803         /* Apply new backlight time */
804         display_state_transition_update_display_state_timeout_by_priority();
805         if (get_pm_cur_state() == S_NORMAL)
806                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
807
808         if (custom_change_name) {
809                 free(custom_change_name);
810                 custom_change_name = 0;
811         }
812
813         display_state_transition_get_custom_timeout(S_NORMAL, &custom_normal_timeout);
814         display_state_transition_get_custom_timeout(S_LCDDIM, &custom_dim_timeout);
815         if (custom_normal_timeout == 0 && custom_dim_timeout == 0)
816                 return 0;
817
818         custom_change_name = strndup(name, strlen(name));
819         if (!custom_change_name) {
820                 _E("Failed to malloc.");
821                 display_state_transition_set_custom_timeout(S_NORMAL, 0);
822                 display_state_transition_set_custom_timeout(S_LCDDIM, 0);
823                 return -ENOMEM;
824         }
825
826         return 0;
827 }
828
829 void reset_lcd_timeout(GDBusConnection *conn,
830         const gchar     *sender,
831         const gchar     *unique_name,
832         gpointer         data)
833 {
834         if (!sender)
835                 return;
836
837         if (!custom_change_name)
838                 return;
839
840         if (strcmp(sender, custom_change_name))
841                 return;
842
843         _I("reset lcd timeout: Set default timeout. sender=%s", sender);
844
845         free(custom_change_name);
846         custom_change_name = 0;
847         display_state_transition_set_custom_timeout(S_NORMAL, 0);
848         display_state_transition_set_custom_timeout(S_LCDDIM, 0);
849
850         display_state_transition_update_display_state_timeout_by_priority();
851         if (get_pm_cur_state() == S_NORMAL)
852                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
853 }
854
855 static int delayed_init_done(void *data)
856 {
857         static bool done = false;
858
859         if (!data)
860                 return done;
861
862         done = *(int*)data;
863         if (!done)
864                 return done;
865
866         _I("Booting done, release booting lock.");
867         if (disp_plgn->pm_unlock_internal) {
868                 disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL, PM_SLEEP_MARGIN);
869                 disp_plgn->pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
870         }
871
872         return done;
873 }
874
875 static gboolean delayed_dpms_init_done(gpointer data)
876 {
877         int timeout;
878
879         if (!display_panel_init_dpms())
880                 return G_SOURCE_CONTINUE;
881
882         switch (get_pm_cur_state()) {
883         case S_NORMAL:
884         case S_LCDDIM:
885                 display_panel_lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
886                 if (display_conf.timeout_enable) {
887                         timeout = states[S_NORMAL].timeout;
888                         /* check minimun lcd on time */
889                         if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
890                                 timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
891                         display_state_transition_reset_state_transition_timeout(timeout);
892                 }
893                 break;
894         case S_LCDOFF:
895                 display_panel_lcd_off_procedure(LCD_OFF_BY_EVENT);
896                 timeout = display_conf.lcdoff_timeout;
897                 display_state_transition_reset_state_transition_timeout(timeout);
898                 break;
899         default:
900                 break;
901         }
902
903         return G_SOURCE_REMOVE;
904 }
905
906 static void add_timer_for_dpms_init(void)
907 {
908         guint id = g_timeout_add(500/* milliseconds */, delayed_dpms_init_done, NULL);
909         if (id == 0)
910                 _E("Failed to add display_panel_init_dpms timeout.");
911 }
912
913 static void init_display_states(void *data)
914 {
915         struct display_plugin *dp = (struct display_plugin *) data;
916         for(int i = 0; i < S_END; i++)
917                 dp->display_states[i] = &states[i];
918 }
919 /**
920  * Power manager Main
921  *
922  */
923
924 static int display_probe(void *data)
925 {
926         int ret;
927         struct display_plugin *dp = (struct display_plugin *) data;
928         assert(dp);
929
930         dp->config = &display_conf;
931         init_display_states(dp);
932         setup_display_plugin_backlight_ops(dp);
933         dp->set_dim_state = NULL;
934         dp->get_device_flags = NULL;
935         dp->lcd_on_procedure = NULL;
936         dp->lcd_off_procedure = NULL;
937         setup_display_plugin_backlight_ops(dp);
938
939         /**
940          * load display service
941          * if there is no display shared library,
942          * deviced does not provide any method and function of display.
943          */
944         ret = display_service_load();
945         if (ret)
946                 return ret;
947
948         /* display_plugin instance initialization */
949         init_pm_internal(data);
950         disp_plgn->device_flags_to_string = __device_flags_to_string;
951
952         if (battery_plgn->handle) {
953                 fp_get_charging_status = dlsym(battery_plgn->handle, "get_charging_status");
954                 if (!fp_get_charging_status)
955                         _E("Failed to obtain address of get_charging_status");
956         } else
957                 _I("There is no battery module.");
958
959         return 0;
960 }
961
962 static int input_init_handler(void)
963 {
964         if (!display_conf.input_support)
965                 remove_device_by_devname("input");
966
967         return 0;
968 }
969
970 static int power_resume_from_echomem_callback(void *data)
971 {
972         system_wakeup_flag = true;
973         if (check_wakeup_src() == EVENT_DEVICE)
974                 /* system waked up by devices */
975                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_DEVICE);
976         else
977                 /* system waked up by user input */
978                 display_state_transition_do_state_transition(get_pm_cur_state(), EVENT_INPUT);
979
980         return 0;
981 }
982
983 static int poweroff_triggered_callback(void *udata)
984 {
985         int val = (int)(intptr_t) udata;
986
987         switch (val) {
988         case VCONFKEY_SYSMAN_POWER_OFF_NONE:
989                 clear_pm_status_flag(PWROFF_FLAG);
990                 break;
991         case VCONFKEY_SYSMAN_POWER_OFF_DIRECT:
992         case VCONFKEY_SYSMAN_POWER_OFF_RESTART:
993                 set_pm_status_flag(PWROFF_FLAG);
994                 break;
995         }
996
997         return 0;
998 }
999
1000 static void esd_action(void)
1001 {
1002         const struct device_ops *touchscreen_ops = NULL;
1003
1004         _I("ESD on");
1005
1006         touchscreen_ops = find_device("touchscreen");
1007
1008         if (!check_default(touchscreen_ops))
1009                 touchscreen_ops->stop(NORMAL_MODE);
1010         display_panel_set_panel_state_by_off_state(NORMAL_MODE);
1011         display_panel_set_panel_state_by_on_state(NORMAL_MODE);
1012         if (!check_default(touchscreen_ops))
1013                 touchscreen_ops->start(NORMAL_MODE);
1014 }
1015
1016 static void lcd_uevent_changed(struct udev_device *dev)
1017 {
1018         const char *devpath;
1019         const char *action;
1020
1021         devpath = udev_device_get_devpath(dev);
1022         if (!devpath)
1023                 return;
1024
1025         if (!fnmatch(LCD_ESD_PATH, devpath, 0)) {
1026                 action = udev_device_get_action(dev);
1027                 if (!strcmp(action, UDEV_CHANGE))
1028                         esd_action();
1029         }
1030 }
1031
1032 static const struct uevent_handler lcd_uevent_ops = {
1033         .subsystem      = LCD_EVENT_SUBSYSTEM,
1034         .uevent_func    = lcd_uevent_changed,
1035         .data           = NULL,
1036 };
1037
1038 static void display_init(void *data)
1039 {
1040         int ret, i;
1041         unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS);
1042         int timeout = 0;
1043
1044         _I("Start power manager.");
1045
1046         signal(SIGHUP, sig_hup);
1047
1048         power_saving_func = default_saving_mode;
1049
1050         /* load configutation */
1051         ret = display_load_config(&display_conf);
1052         if (ret < 0)
1053                 _W("Failed to load '%s', use default value: %d",
1054                     DISPLAY_CONF_FILE, ret);
1055
1056         register_kernel_uevent_control(&lcd_uevent_ops);
1057
1058         register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
1059         register_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
1060         register_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
1061         register_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
1062         register_notifier(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
1063         register_notifier(DEVICE_NOTIFIER_POWEROFF_TRIGGERED, poweroff_triggered_callback);
1064
1065         init_save_userlock();
1066
1067         for (i = INIT_SETTING; i < INIT_END; i++) {
1068                 switch (i) {
1069                 case INIT_SETTING:
1070                         ret = init_setting(update_setting);
1071                         break;
1072                 case INIT_INTERFACE:
1073                         if (display_conf.timeout_enable)
1074                                 display_initialize_display_state_timeout_from_setting();
1075                         ret = init_sysfs(flags);
1076                         break;
1077                 case INIT_POLL:
1078                         _I("input init");
1079                         ret = input_init_handler();
1080
1081                         pm_lock_detector_init();
1082                         break;
1083                 case INIT_DBUS:
1084                         _I("Dbus init.");
1085                         ret = init_pm_dbus();
1086                         break;
1087                 }
1088                 if (ret != 0) {
1089                         _E("Failed to init: %s", errMSG[i]);
1090                         break;
1091                 }
1092         }
1093
1094         if (i == INIT_END) {
1095                 display_ops_init(NULL);
1096 #ifdef ENABLE_PM_LOG
1097                 pm_history_init();
1098 #endif
1099                 init_lcd_operation();
1100                 check_seed_status();
1101
1102                 /* In smd test, TSP should be turned off if display panel is not existed. */
1103                 if (display_panel_get_dpms_cached_state() == -ENOENT) {
1104                         _I("Display panel is not existed.");
1105                         lcd_direct_control(DPMS_OFF, NORMAL_MODE);
1106                         exit_lcd_operation();
1107                 }
1108
1109                 /* wm_ready needs to be checked
1110                  * since display manager can be launched later than deviced.
1111                  * In the case, display cannot be turned on at the first booting */
1112                 // wm_ready = check_wm_ready();
1113                 if (display_panel_init_dpms()) {
1114                         if (is_lcdon_blocked() != LCDON_BLOCK_NONE)
1115                                 display_panel_lcd_off_procedure(LCD_OFF_BY_EVENT);
1116                         else
1117                                 display_panel_lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
1118                 } else {
1119                         add_timer_for_dpms_init();
1120                 }
1121
1122                 if (display_conf.lcd_always_on) {
1123                         _I("LCD always on.");
1124                         display_state_transition_set_transition_table_display_state(S_NORMAL, S_NORMAL, EVENT_TIMEOUT);
1125                 }
1126
1127                 if (flags & WITHOUT_STARTNOTI) {        /* start without noti */
1128                         _I("Start Power managing without noti");
1129                         power_request_change_state_strict(DEVICED_POWER_STATE_SLEEP, DEVICED_POWER_STATE_NORMAL,
1130                                 HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN, NULL);
1131                         /*
1132                          * Lock lcd off until booting is done.
1133                          * deviced guarantees all booting script is executing.
1134                          * Last script of booting unlocks this suspend blocking state.
1135                          */
1136                         if (disp_plgn->pm_lock_internal)
1137                                 disp_plgn->pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF,
1138                                                 STAY_CUR_STATE, DELAYED_INIT_WATING_TIME);
1139
1140                         /* Initial display state right after the booting done */
1141                         if (is_lcdon_blocked())
1142                                 set_pm_cur_state(S_LCDOFF);
1143                         else
1144                                 set_pm_cur_state(S_NORMAL);
1145                         ret = vconf_set_int(VCONFKEY_PM_STATE, get_pm_cur_state());
1146                         if (ret < 0)
1147                                 _E("Failed to set vconf value for pm cur state: %d", vconf_get_ext_errno());
1148
1149                         display_set_display_ops_status(DEVICE_OPS_STATUS_START);
1150                         if (display_conf.timeout_enable) {
1151                                 timeout = states[S_NORMAL].timeout;
1152                                 /* check minimun lcd on time */
1153                                 if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
1154                                         timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
1155
1156                                 if (disp_plgn->pm_lock_internal)
1157                                         disp_plgn->pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL,
1158                                                         STAY_CUR_STATE, timeout);
1159                         }
1160
1161                 }
1162
1163                 set_display_init_direction(display_conf.display_init_direction);
1164         }
1165 }
1166
1167 static void display_exit(void *data)
1168 {
1169         int i = INIT_END;
1170
1171         display_set_display_ops_status(DEVICE_OPS_STATUS_STOP);
1172
1173         /* Set current state to S_NORMAL */
1174         set_pm_cur_state(S_NORMAL);
1175         set_setting_pmstate(get_pm_cur_state());
1176         /* timeout is not needed */
1177         display_state_transition_reset_state_transition_timeout(TIMEOUT_NONE);
1178
1179         unregister_kernel_uevent_control(&lcd_uevent_ops);
1180
1181         display_ops_exit(NULL);
1182
1183         for (i = i - 1; i >= INIT_SETTING; i--) {
1184                 switch (i) {
1185                 case INIT_SETTING:
1186                         exit_setting();
1187                         break;
1188                 case INIT_INTERFACE:
1189                         exit_sysfs();
1190                         break;
1191                 case INIT_POLL:
1192                         unregister_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_done);
1193                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background);
1194                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground);
1195                         unregister_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated);
1196                         unregister_notifier(DEVICE_NOTIFIER_POWER_RESUME_FROM_ECHO_MEM, power_resume_from_echomem_callback);
1197
1198                         break;
1199                 }
1200         }
1201
1202         exit_lcd_operation();
1203         free_lock_info_list();
1204
1205         /* free display service */
1206         display_service_free();
1207
1208         _I("Stop power manager.");
1209 }
1210
1211 static int display_start(enum device_flags flags)
1212 {
1213         /* NORMAL MODE */
1214         if (flags & NORMAL_MODE) {
1215                 if (flags & LCD_PANEL_OFF_MODE)
1216                         /* standby on */
1217                         display_panel_set_panel_state_by_standby_state(true);
1218                 else
1219                         /* normal lcd on */
1220                         display_panel_set_panel_state_by_on_state(flags);
1221
1222                 return 0;
1223         }
1224
1225         /* CORE LOGIC MODE */
1226         if (!(flags & CORE_LOGIC_MODE))
1227                 return 0;
1228
1229         display_get_display_ops_status(&status);
1230         if (status == DEVICE_OPS_STATUS_START)
1231                 return -EALREADY;
1232
1233         if (display_probe(NULL) < 0)
1234                 return -EPERM;
1235
1236         display_init(NULL);
1237
1238         return 0;
1239 }
1240
1241 static int display_stop(enum device_flags flags)
1242 {
1243         /* NORMAL MODE */
1244         if (flags & NORMAL_MODE || flags & FORCE_OFF_MODE) {
1245                 display_panel_set_panel_state_by_off_state(flags);
1246                 return 0;
1247         }
1248
1249         /* CORE LOGIC MODE */
1250         if (!(flags & CORE_LOGIC_MODE))
1251                 return 0;
1252
1253         display_get_display_ops_status(&status);
1254         if (status == DEVICE_OPS_STATUS_STOP)
1255                 return -EALREADY;
1256
1257         display_exit(NULL);
1258
1259         return 0;
1260 }
1261
1262 static int display_status(void)
1263 {
1264         return status;
1265 }
1266
1267 static const struct device_ops display_plugin_device_ops = {
1268         .disable_auto_init = true,
1269         DECLARE_NAME_LEN("display-plugin"),
1270         .probe    = display_probe,
1271         .init     = display_init,
1272         .exit     = display_exit,
1273         .start    = display_start,
1274         .stop     = display_stop,
1275         .status   = display_status,
1276 };
1277
1278 DEVICE_OPS_REGISTER(&display_plugin_device_ops)
1279
1280 static void __CONSTRUCTOR__ initialize(void)
1281 {
1282         disp_plgn = get_var_display_plugin();
1283         if (!disp_plgn)
1284                 _E("Failed to get display plugin variable.");
1285
1286         backlight_ops = get_var_backlight_ops();
1287         if (!backlight_ops)
1288                 _E("Failed to get backlight operator variable.");
1289
1290         battery_plgn = get_var_battery_plugin();
1291         if (!battery_plgn)
1292                 _E("Failed to get battery plugin variable.");
1293 }
1294 /**
1295  * @}
1296  */