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