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