Support silent boot (Only for mobile)
[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 <fnmatch.h>
39 #include <vconf-keys.h>
40 #include <sys/time.h>
41
42 #include "ambient-mode.h"
43 #include "util.h"
44 #include "core.h"
45 #include "device-node.h"
46 #include "lock-detector.h"
47 #include "display-ops.h"
48 #include "core/devices.h"
49 #include "core/device-notifier.h"
50 #include "core/udev.h"
51 #include "core/list.h"
52 #include "core/common.h"
53 #include "core/config-parser.h"
54 #include "core/launch.h"
55 #include "apps/apps.h"
56 #include "extcon/extcon.h"
57 #include "battery/power-supply.h"
58 #include "power/power-handler.h"
59 #include "power/boot.h"
60 #include "dd-display.h"
61 #include "display/display-dpms.h"
62 #include "proximity.h"
63 #include "display-info.h"
64
65 #define DISPLAY_CONF_FILE    "/etc/deviced/display.conf"
66
67 /**
68  * @addtogroup POWER_MANAGER
69  * @{
70  */
71
72 #define LOCK_SCREEN_INPUT_TIMEOUT       10000
73 #define LOCK_SCREEN_CONTROL_TIMEOUT     5000
74 #define ALWAYS_ON_TIMEOUT               360000000
75 #define LATE_LCD_TRANSIT                1
76
77 #define PID_MAX                 6
78
79 #define GESTURE_STR             "gesture"
80 #define POWER_KEY_STR           "powerkey"
81 #define TOUCH_STR               "touch"
82 #define EVENT_STR               "event"
83 #define TIMEOUT_STR             "timeout"
84 #define PROXI_STR               "proximity"
85 #define PALM_STR                "palm"
86 #define UNKNOWN_STR             "unknown"
87
88 #define METHOD_APP_STATUS       "CheckAppStatus"
89
90 #define PM_WAKEUP               0
91 #define PM_SUSPEND              1
92
93 extern void init_pm_internal();
94 extern int get_charging_status(int *val);
95 extern void init_save_userlock(void);
96
97 unsigned int pm_status_flag;
98 static int trans_condition;
99
100 static void (*power_saving_func) (int onoff);
101 static enum device_ops_status status = DEVICE_OPS_STATUS_UNINIT;
102
103 int pm_cur_state;
104 int pm_old_state;
105 guint timeout_src_id;
106 int system_wakeup_flag = false;
107 static unsigned int custom_normal_timeout = 0;
108 static unsigned int custom_dim_timeout = 0;
109 static int custom_holdkey_block = false;
110 static int custom_change_pid = -1;
111 static char *custom_change_name;
112 static bool hallic_open = true;
113 static guint lock_timeout_id;
114 static guint transit_timer;
115 static int lock_screen_timeout = LOCK_SCREEN_INPUT_TIMEOUT;
116 static long displayoff_time;
117 static struct timeval lcdon_tv;
118 static int lcd_paneloff_mode = false;
119 static int stay_touchscreen_off = false;
120 dd_list *lcdon_ops;
121 /*
122  * The two variables(lcdon_broadcast, pmstate_suspend) must be set initial
123  * state because it should be sent from previous state at booting time.
124  */
125 static bool lcdon_broadcast = true;
126 static int pmstate_suspend = PM_SUSPEND;
127
128 static bool touch_blocked = false;
129
130 /* default transition, action fuctions */
131 static int default_trans(int evt);
132 static int default_action(int timeout);
133 static int default_check(int curr, int next);
134
135 static gboolean del_normal_cond(void *data);
136 static gboolean del_dim_cond(void *data);
137 static gboolean del_off_cond(void *data);
138
139 static gboolean pmlock_check(void *data);
140
141 static int default_proc_change_state(unsigned int cond, pid_t pid);
142 static int (*proc_change_state)(unsigned int cond, pid_t pid) = default_proc_change_state;
143
144 struct state states[S_END] = {
145         { S_START,    "S_START",    NULL,          NULL,           NULL,          NULL            },
146         { S_NORMAL,   "S_NORMAL",   default_trans, default_action, default_check, del_normal_cond },
147         { S_LCDDIM,   "S_LCDDIM",   default_trans, default_action, default_check, del_dim_cond    },
148         { S_LCDOFF,   "S_LCDOFF",   default_trans, default_action, default_check, del_off_cond    },
149         { S_STANDBY,  "S_STANDBY",  NULL,          NULL,           NULL,          NULL            },
150         { S_SLEEP,    "S_SLEEP",    default_trans, default_action, default_check, NULL            },
151         { S_POWEROFF, "S_POWEROFF", NULL,          NULL,           NULL,          NULL            },
152 };
153
154 static int trans_table[S_END][EVENT_END] = {
155         /* Timeout,   Input */
156         { S_START,    S_START    }, /* S_START */
157         { S_LCDDIM,   S_NORMAL   }, /* S_NORMAL */
158         { S_LCDOFF,   S_NORMAL   }, /* S_LCDDIM */
159         { S_SLEEP,    S_NORMAL   }, /* S_LCDOFF */
160         { S_SLEEP,    S_STANDBY  }, /* S_STANDBY */
161         { S_LCDOFF,   S_NORMAL   }, /* S_SLEEP */
162         { S_POWEROFF, S_POWEROFF }, /* S_POWEROFF */
163 };
164
165 enum signal_type {
166         SIGNAL_INVALID = 0,
167         SIGNAL_PRE,
168         SIGNAL_POST,
169         SIGNAL_MAX,
170 };
171
172 static const char *lcdon_sig_lookup[SIGNAL_MAX] = {
173         [SIGNAL_PRE]  = "LCDOn",
174         [SIGNAL_POST] = "LCDOnCompleted",
175 };
176 static const char *lcdoff_sig_lookup[SIGNAL_MAX] = {
177         [SIGNAL_PRE]  = "LCDOff",
178         [SIGNAL_POST] = "LCDOffCompleted",
179 };
180
181 #define SHIFT_UNLOCK            4
182 #define SHIFT_CHANGE_STATE      7
183 #define CHANGE_STATE_BIT        0xF00   /* 1111 0000 0000 */
184 #define SHIFT_LOCK_FLAG 16
185 #define SHIFT_CHANGE_TIMEOUT    20
186 #define CUSTOM_TIMEOUT_BIT      0x1
187 #define CUSTOM_HOLDKEY_BIT      0x2
188 #define HOLD_KEY_BLOCK_BIT      0x1
189 #define TIMEOUT_NONE            (-1)
190
191 #define S_COVER_TIMEOUT                 8000
192 #define GET_HOLDKEY_BLOCK_STATE(x) ((x >> SHIFT_LOCK_FLAG) & HOLD_KEY_BLOCK_BIT)
193 #define BOOTING_DONE_WATING_TIME        60000   /* 1 minute */
194 #define LOCK_TIME_WARNING               60      /* 60 seconds */
195
196 #define ACTIVE_ACT "active"
197 #define INACTIVE_ACT "inactive"
198
199 #define LOCK_SCREEN_WATING_TIME         300     /* 0.3 second */
200 #define LONG_PRESS_INTERVAL             400       /* 0.4 seconds */
201 #define SAMPLING_INTERVAL               1       /* 1 sec */
202 #define BRIGHTNESS_CHANGE_STEP          10
203 #define LCD_ALWAYS_ON                   0
204 #define ACCEL_SENSOR_ON                 1
205 #define CONTINUOUS_SAMPLING             1
206 #define LCDOFF_TIMEOUT                  500     /* milli second */
207
208 #define DIFF_TIMEVAL_MS(a, b) \
209         (((a.tv_sec * 1000000 + a.tv_usec) - \
210         (b.tv_sec * 1000000 + b.tv_usec)) \
211         / 1000)
212
213 struct display_config display_conf = {
214         .lock_wait_time         = LOCK_SCREEN_WATING_TIME,
215         .longpress_interval     = LONG_PRESS_INTERVAL,
216         .lightsensor_interval   = SAMPLING_INTERVAL,
217         .lcdoff_timeout         = LCDOFF_TIMEOUT,
218         .pm_default_brightness = 80,
219         .brightness_change_step = BRIGHTNESS_CHANGE_STEP,
220         .lcd_always_on          = LCD_ALWAYS_ON,
221         .dimming                = 1,
222         .framerate_app          = {0, 0, 0, 0},
223         .control_display        = 0,
224         .powerkey_doublepress   = 0,
225         .accel_sensor_on        = ACCEL_SENSOR_ON,
226         .continuous_sampling    = CONTINUOUS_SAMPLING,
227         .timeout_enable         = true,
228         .input_support          = true,
229         .lockcheck_timeout      = 600,
230         .aod_enter_level        = 40,
231         .aod_tsp                = true,
232         .touch_wakeup           = false,
233         .sleep_support          = true,
234 };
235
236 struct display_function_info display_info = {
237         .update_auto_brightness         = NULL,
238         .set_autobrightness_min         = NULL,
239         .reset_autobrightness_min       = NULL,
240         .face_detection                 = NULL,
241 };
242
243 typedef struct _pm_lock_node {
244         pid_t pid;
245         guint timeout_id;
246         guint warning_id;
247         GVariant *warning_param;
248         time_t time;
249         bool holdkey_block;
250         bool background;
251         bool broadcast_warning;
252 } PmLockNode;
253
254 static dd_list *cond_head[S_END];
255
256 static void set_process_active(bool flag, pid_t pid)
257 {
258         int ret;
259
260         if (pid >= INTERNAL_LOCK_BASE)
261                 return;
262
263         /* Send dbug to resourced */
264         ret = dbus_handle_emit_dbus_signal(NULL,
265                                                         RESOURCED_PATH_PROCESS,
266                                                     RESOURCED_INTERFACE_PROCESS,
267                                                     RESOURCED_METHOD_ACTIVE,
268                                                     g_variant_new("(si)", (flag ? ACTIVE_ACT : INACTIVE_ACT), pid));
269         if (ret < 0)
270                 _E("Failed to send dbus signal to resourced.");
271 }
272
273 bool check_lock_state(int state)
274 {
275         dd_list *elem;
276         PmLockNode *t;
277
278         DD_LIST_FOREACH(cond_head[state], elem, t) {
279                 if (t->background == false)
280                         return true;
281         }
282
283         return false;
284 }
285
286 void change_state_action(enum state_t state, int (*func)(int timeout))
287 {
288         _I("[%s] 'action' is changed.", states[state].name);
289         states[state].action = func;
290 }
291
292 void change_state_trans(enum state_t state, int (*func)(int evt))
293 {
294         _I("[%s] 'trans' is changed.", states[state].name);
295         states[state].trans = func;
296 }
297
298 void change_state_check(enum state_t state, int (*func)(int curr, int next))
299 {
300         _I("[%s] 'check' is changed.", states[state].name);
301         states[state].check = func;
302 }
303
304 void change_state_name(enum state_t state, const char *name)
305 {
306         _I("[%s] 'name' is changed.", states[state].name);
307         states[state].name = name;
308 }
309
310 void change_trans_table(enum state_t state, enum state_t next)
311 {
312         _I("[%s] 'timeout trans table' is changed.", states[state].name);
313         trans_table[state][EVENT_TIMEOUT] = next;
314 }
315
316 void change_proc_change_state(int (*func)(unsigned int cond, pid_t pid))
317 {
318         _I("'proc change state' is changed.");
319         proc_change_state = func;
320 }
321
322 static inline long clock_gettime_to_long(void)
323 {
324         struct timespec now;
325         int ret;
326
327         ret = clock_gettime(CLOCK_REALTIME, &now);
328
329         if (ret < 0) {
330                 _E("Failed to clock gettime!");
331                 return 0;
332         }
333
334         return SEC_TO_MSEC(now.tv_sec) + NSEC_TO_MSEC(now.tv_nsec);
335 }
336
337 static int display_brightness_changed(void *data)
338 {
339         int brt, ret;
340
341         brt = DATA_VALUE_INT(data);
342
343         ret = dbus_handle_emit_dbus_signal(NULL,
344                                                         DEVICED_PATH_DISPLAY,
345                                                         DEVICED_INTERFACE_DISPLAY,
346                                                         "Brightness",
347                                                         g_variant_new("(i)", brt));
348         if (ret < 0)
349                 _E("Failed to send dbus signal Brightness.");
350
351         return 0;
352 }
353
354 static int display_auto_brightness_sensing(void *data)
355 {
356         if (!transit_timer)
357                 return 0;
358
359         g_source_remove(transit_timer);
360         transit_timer = 0;
361
362         return 0;
363 }
364
365 static void broadcast_lcd_on(enum signal_type type, enum device_flags flags)
366 {
367         const char *str;
368         const char *signal;
369         int ret;
370         long diff = 0;
371
372         if (type <= SIGNAL_INVALID || type >= SIGNAL_MAX) {
373                 _E("Invalid signal type(%d).", type);
374                 return;
375         }
376
377         if (type == SIGNAL_PRE && displayoff_time != 0)
378                 diff = clock_gettime_to_long() - displayoff_time;
379
380         if (flags & LCD_ON_BY_GESTURE)
381                 str = GESTURE_STR;
382         else if (flags & LCD_ON_BY_POWER_KEY)
383                 str = POWER_KEY_STR;
384         else if (flags & LCD_ON_BY_EVENT)
385                 str = EVENT_STR;
386         else if (flags & LCD_ON_BY_TOUCH)
387                 str = TOUCH_STR;
388         else
389                 str = UNKNOWN_STR;
390
391         signal = lcdon_sig_lookup[type];
392         _I("lcdstep : Broadcast signal(%s:%s).", signal, str);
393         ret = dbus_handle_emit_dbus_signal(NULL,
394                                                 DEVICED_PATH_DISPLAY,
395                                                 DEVICED_INTERFACE_DISPLAY,
396                                                 signal,
397                                                 g_variant_new("(si)", str, diff));
398         if (ret < 0)
399                 _E("Failed to send dbus signal(%s)", signal);
400 }
401
402 static void broadcast_lcd_off(enum signal_type type, enum device_flags flags)
403 {
404         const char *str;
405         const char *signal;
406         int ret;
407
408         if (type <= SIGNAL_INVALID || type >= SIGNAL_MAX) {
409                 _E("Invalid signal type(%d).", type);
410                 return;
411         }
412
413         if (type == SIGNAL_PRE)
414                 displayoff_time = clock_gettime_to_long();
415
416         signal = lcdoff_sig_lookup[type];
417
418         if (flags & LCD_OFF_BY_POWER_KEY)
419                 str = POWER_KEY_STR;
420         else if (flags & LCD_OFF_BY_TIMEOUT)
421                 str = TIMEOUT_STR;
422         else if (flags & LCD_OFF_BY_EVENT)
423                 str = EVENT_STR;
424         else if (flags & LCD_OFF_BY_PROXIMITY)
425                 str = PROXI_STR;
426         else if (flags & LCD_OFF_BY_PALM)
427                 str = PALM_STR;
428         else if (flags & LCD_OFF_BY_GESTURE)
429                 str = GESTURE_STR;
430         else
431                 str = UNKNOWN_STR;
432
433         _I("lcdstep : Broadcast signal(%s).", signal);
434         ret = dbus_handle_emit_dbus_signal(NULL,
435                                                 DEVICED_PATH_DISPLAY,
436                                                 DEVICED_INTERFACE_DISPLAY,
437                                                 signal,
438                                                 g_variant_new("(s)", str));
439         if (ret < 0)
440                 _E("Failed to send dbus signal(%s)", signal);
441 }
442
443 void broadcast_lcd_off_late(enum device_flags flags)
444 {
445         static enum device_flags late_flags;
446
447         if (flags & LCD_OFF_LATE_MODE)
448                 broadcast_lcd_off(SIGNAL_POST, late_flags);
449         else
450                 late_flags = flags;
451 }
452
453 static unsigned long get_lcd_on_flags(void)
454 {
455         unsigned long flags = NORMAL_MODE;
456
457         if (lcd_paneloff_mode)
458                 flags |= LCD_PANEL_OFF_MODE;
459
460         if (ambient_get_condition() == true) {
461                 flags |= AMBIENT_MODE;
462                 flags |= LCD_PHASED_TRANSIT_MODE;
463         }
464
465         return flags;
466 }
467
468 bool touch_event_blocked(void)
469 {
470         return touch_blocked;
471 }
472
473 static gboolean late_transit_on(void *data)
474 {
475         if (!transit_timer)
476                 return G_SOURCE_REMOVE;
477
478         g_source_remove(transit_timer);
479         transit_timer = 0;
480
481         backlight_ops.transit_state(DPMS_ON);
482         return G_SOURCE_REMOVE;
483 }
484
485 void lcd_on_procedure(int state, enum device_flags flag)
486 {
487         dd_list *l = NULL;
488         const struct device_ops *ops = NULL;
489         unsigned long flags = get_lcd_on_flags();
490         flags |= flag;
491
492         /*
493          * Display on procedure
494          * step 1. broadcast lcd on signal with cause
495          * step 2. set brightness
496          * step 3. set pmstate of vconf
497          * step 4. display on operate
498          *  - a. display on
499          *  - b. TSP(touch screen) and touchkey enable
500          * step 5. broadcast lcd on complete siganl
501          * step 6. key backlight enable
502          */
503         _I("[lcdstep] 0x%lx", flags);
504
505         if (flags & AMBIENT_MODE) {
506                 if (ambient_get_state() == false && backlight_ops.get_lcd_power() == DPMS_ON)
507                         return;
508                 ambient_set_state(false);
509         }
510
511         /* send LCDOn dbus signal */
512         if (!lcdon_broadcast)
513                 broadcast_lcd_on(SIGNAL_PRE, flags);
514
515         if (!(flags & LCD_PHASED_TRANSIT_MODE)) {
516                 /* Update brightness level */
517                 if (state == LCD_DIM)
518                         backlight_ops.dim();
519                 else if (state == LCD_NORMAL)
520                         backlight_ops.update();
521         }
522
523         if (state == LCD_NORMAL)
524                 set_setting_pmstate(S_NORMAL);
525         else if (state == LCD_DIM)
526                 set_setting_pmstate(S_LCDDIM);
527
528         DD_LIST_FOREACH(lcdon_ops, l, ops)
529                 ops->start(flags);
530
531         if (!lcdon_broadcast) {
532         broadcast_lcd_on(SIGNAL_POST, flags);
533                 if (flags & LCD_PHASED_TRANSIT_MODE)
534                         transit_timer = g_timeout_add_seconds(LATE_LCD_TRANSIT,
535                                         late_transit_on, NULL);
536                 lcdon_broadcast = true;
537         }
538
539         if (CHECK_OPS(keyfilter_ops, backlight_enable))
540                 keyfilter_ops->backlight_enable(true);
541
542         touch_blocked = false;
543 }
544
545 static unsigned long get_lcd_off_flags(void)
546 {
547         unsigned long flags = NORMAL_MODE;
548
549         if (ambient_get_condition() == true) {
550                 flags |= AMBIENT_MODE;
551                 flags |= LCD_PHASED_TRANSIT_MODE;
552         }
553
554         if (stay_touchscreen_off)
555                 flags |= TOUCH_SCREEN_OFF_MODE;
556
557         return flags;
558 }
559
560 inline void lcd_off_procedure(enum device_flags flag)
561 {
562         dd_list *l = NULL;
563         const struct device_ops *ops = NULL;
564         unsigned long flags = get_lcd_off_flags();
565         flags |= flag;
566
567         /*
568          * Display off procedure
569          * step 0. enhance mode off using nofity (e.g mdnie, HBM, LBM)
570          * step 1. broadcast lcd off signal with cause
571          * step 2. set pmstate of vconf
572          * step 3. display off operate
573          *  - a. display off
574          *  - b. TSP(touch screen) and touchkey disable
575          * step 4. broadcast lcd off complete siganl
576          */
577         _I("[lcdstep] 0x%lx", flags);
578
579         device_notify(DEVICE_NOTIFIER_LCD_OFF, NULL);
580
581         touch_blocked = true;
582
583         if (flags & AMBIENT_MODE) {
584                 if (ambient_get_state() == true)
585                         return;
586                 ambient_set_state(true);
587         }
588
589         if (lcdon_broadcast) {
590                 broadcast_lcd_off(SIGNAL_PRE, flags);
591                 lcdon_broadcast = false;
592         }
593         set_setting_pmstate(S_LCDOFF);
594
595         if (CHECK_OPS(keyfilter_ops, backlight_enable))
596                 keyfilter_ops->backlight_enable(false);
597
598         if (transit_timer) {
599                 g_source_remove(transit_timer);
600                 transit_timer = 0;
601         }
602
603         if (flags & LCD_PHASED_TRANSIT_MODE)
604                 backlight_ops.transit_state(DPMS_OFF);
605
606         DD_LIST_FOREACH(lcdon_ops, l, ops)
607                 ops->stop(flags);
608
609         if (flags & AMBIENT_MODE)
610                 broadcast_lcd_off_late(flags);
611         else
612                 broadcast_lcd_off(SIGNAL_POST, flags);
613
614         device_notify(DEVICE_NOTIFIER_LCD_OFF_COMPLETE, NULL);
615 }
616
617 void set_stay_touchscreen_off(int val)
618 {
619         _I("Stay touch screen off: %d", val);
620         stay_touchscreen_off = val;
621
622         if (disp_plgn.pm_change_internal)
623                 disp_plgn.pm_change_internal(INTERNAL_LOCK_PM, LCD_NORMAL);
624 }
625
626 void set_lcd_paneloff_mode(int val)
627 {
628         _I("Lcd paneloff mode: %d", val);
629         lcd_paneloff_mode = val;
630
631         if (disp_plgn.pm_change_internal)
632                 disp_plgn.pm_change_internal(INTERNAL_LOCK_PM, LCD_NORMAL);
633 }
634
635 int low_battery_state(int val)
636 {
637         switch (val) {
638         case VCONFKEY_SYSMAN_BAT_POWER_OFF:
639         case VCONFKEY_SYSMAN_BAT_CRITICAL_LOW:
640         case VCONFKEY_SYSMAN_BAT_REAL_POWER_OFF:
641                 return true;
642         }
643         return false;
644 }
645
646 int get_hallic_open(void)
647 {
648         return hallic_open;
649 }
650
651 static int refresh_app_cond()
652 {
653         trans_condition = 0;
654
655         if (check_lock_state(S_NORMAL))
656                 trans_condition = trans_condition | MASK_NORMAL;
657         if (check_lock_state(S_LCDDIM))
658                 trans_condition = trans_condition | MASK_DIM;
659         if (check_lock_state(S_LCDOFF))
660                 trans_condition = trans_condition | MASK_OFF;
661
662         return 0;
663 }
664
665 static void makeup_trans_condition(void)
666 {
667         check_processes(S_NORMAL);
668         check_processes(S_LCDDIM);
669         check_processes(S_LCDOFF);
670         refresh_app_cond();
671 }
672
673 static PmLockNode *find_node(enum state_t s_index, pid_t pid)
674 {
675         dd_list *elem;
676         PmLockNode *t = NULL;
677
678         DD_LIST_FOREACH(cond_head[s_index], elem, t) {
679                 if (t->pid == pid)
680                         return t;
681         }
682
683         return NULL;
684 }
685
686 static PmLockNode *add_node(enum state_t s_index, pid_t pid, guint timeout_id,
687                 bool holdkey_block)
688 {
689         guint warning_id = 0;
690         PmLockNode *n;
691         GVariant *v = NULL;
692         time_t now;
693
694         n = (PmLockNode *) malloc(sizeof(PmLockNode));
695         if (n == NULL) {
696                 _E("Not enough memory, add cond. fail");
697                 return NULL;
698         }
699
700         if (pid < INTERNAL_LOCK_BASE) {
701                 v = g_variant_new("(ii)", s_index, pid);
702                 if (v) {
703                         warning_id = g_timeout_add_seconds(display_conf.lockcheck_timeout,
704                                 pmlock_check, (void *)v);
705                 } else {
706                         _E("Failed to make GVariant.");
707                 }
708
709         }
710
711         time(&now);
712         n->pid = pid;
713         n->timeout_id = timeout_id;
714         n->warning_id = warning_id;
715         n->warning_param = v;
716         n->time = now;
717         n->holdkey_block = holdkey_block;
718         n->background = false;
719         n->broadcast_warning = true;
720         DD_LIST_APPEND(cond_head[s_index], n);
721
722         refresh_app_cond();
723         return n;
724 }
725
726 static int del_node(enum state_t s_index, PmLockNode *n)
727 {
728         if (n == NULL)
729                 return 0;
730
731         DD_LIST_REMOVE(cond_head[s_index], n);
732
733         /* delete timer */
734         if (n->timeout_id) {
735                 g_source_remove(n->timeout_id);
736                 n->timeout_id = 0;
737         }
738         if (n->warning_id) {
739                 g_source_remove(n->warning_id);
740                 n->warning_id = 0;
741         }
742         if (n->warning_param) {
743                 g_variant_unref(n->warning_param);
744                 n->warning_param = NULL;
745         }
746
747         free(n);
748         refresh_app_cond();
749         return 0;
750 }
751
752 static void print_node(int next)
753 {
754         int ret;
755         dd_list *elem;
756         PmLockNode *n;
757         char buf[30];
758         time_t now;
759         double diff;
760
761         if (next <= S_START || next >= S_END)
762                 return;
763
764         time(&now);
765         DD_LIST_FOREACH(cond_head[next], elem, n) {
766                 diff = difftime(now, n->time);
767                 ctime_r(&n->time, buf);
768                 buf[strlen(buf) - 1] = 0;
769
770                 if (diff > LOCK_TIME_WARNING) {
771                         if (diff > LOCK_TIME_WARNING * 60 && n->pid < INTERNAL_LOCK_BASE && n->broadcast_warning) {
772                                 ret = dbus_handle_emit_dbus_signal(NULL,
773                                                                                 DEVICED_PATH_DISPLAY,
774                                                                                 DEVICED_INTERFACE_DISPLAY,
775                                                                                 "pmlock_over",
776                                                                                 g_variant_new("(i)", n->pid));
777                                 if (ret < 0)
778                                         _E("Failed to send dbus signal pmlock_over.");
779                                 n->broadcast_warning = false;
780                         }
781                         _W("Over(%.0f s) pid( %5d) lock time(%s)", diff, n->pid, buf);
782                 } else
783                         _I("Pid(%5d) lock time(%s)", n->pid, buf);
784         }
785 }
786
787 void get_pname(pid_t pid, char *pname)
788 {
789         char buf[PATH_MAX];
790         int cmdline, r;
791
792         if (pid >= INTERNAL_LOCK_BASE)
793                 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", getpid());
794         else
795                 snprintf(buf, PATH_MAX, "/proc/%d/cmdline", pid);
796
797         cmdline = open(buf, O_RDONLY);
798         if (cmdline < 0) {
799                 pname[0] = '\0';
800                 _E("Process(%d) does not exist now(may be dead without unlock).", pid);
801                 return;
802         }
803
804         r = read(cmdline, pname, PATH_MAX);
805         if ((r >= 0) && (r < PATH_MAX))
806                 pname[r] = '\0';
807         else
808                 pname[0] = '\0';
809
810         close(cmdline);
811 }
812
813 static void del_state_cond(void *data, enum state_t state)
814 {
815         PmLockNode *tmp = NULL;
816         pid_t pid;
817
818         if (!data)
819                 return;
820
821         /* A passed data is a pid_t type data, not a 64bit data. */
822         pid = (pid_t)((intptr_t)data);
823         _I("delete prohibit dim condition by timeout (%d)", pid);
824
825         if (pid == INTERNAL_LOCK_AMBIENT)
826                 ambient_check_invalid_state(pid);
827
828         tmp = find_node(state, pid);
829         del_node(state, tmp);
830         set_unlock_time(pid, state);
831
832         if (!timeout_src_id)
833                 states[pm_cur_state].trans(EVENT_TIMEOUT);
834
835         if (state == S_LCDOFF)
836                 set_process_active(false, pid);
837 }
838
839 static gboolean del_normal_cond(void *data)
840 {
841         del_state_cond(data, S_NORMAL);
842         return G_SOURCE_REMOVE;
843 }
844
845 static gboolean del_dim_cond(void *data)
846 {
847         del_state_cond(data, S_LCDDIM);
848         return G_SOURCE_REMOVE;
849 }
850
851 static gboolean del_off_cond(void *data)
852 {
853         del_state_cond(data, S_LCDOFF);
854         return G_SOURCE_REMOVE;
855 }
856
857 static void pmlock_check_cb(GVariant *var, void *user_data, GError *err)
858 {
859         pid_t pid = 0;
860         int ret, detected = 0;
861         char *app_id = NULL;
862         enum state_t state = (enum state_t) user_data;
863         PmLockNode *node;
864         time_t now;
865         double diff;
866
867         if (!var)
868                 return;
869
870         if (!dh_get_param_from_var(var, "(iis)", &pid, &detected, &app_id)) {
871                 _E("Failed to get params from gvariant. expected:%s, type:%s", "(iis)", g_variant_get_type_string(var));
872                 goto out;
873         }
874
875         if (is_app(pid) == 1 && !detected)
876                 goto out;
877
878         node = find_node(state, pid);
879         if (!node)
880                 goto out;
881
882         time(&now);
883         diff = difftime(now, node->time);
884
885         CRITICAL_LOG("%s(%d) has held %s lock for a long time(%.0f s).",
886                         app_id, pid, states[state].name + 2, diff);
887
888         ret = dbus_handle_emit_dbus_signal(NULL,
889                                                 DEVICED_PATH_DISPLAY,
890                                                 DEVICED_INTERFACE_DISPLAY,
891                                                 "pmlock_expired",
892                                                 g_variant_new("(i)", pid));
893         if (ret < 0)
894                 _E("Failed to send dbus pmlock_expired");
895
896 out:
897         if (app_id)
898                 g_free(app_id);
899         g_variant_unref(var);
900 }
901
902 /*
903  * Any process is possible many time lock, deviced can not know malicious
904  * or good process. so infinity or more then 10 min lock process, deviced
905  * will check it through resoured. And then, it will ask the user whether to quit or not.
906  */
907 static gboolean pmlock_check(void *data)
908 {
909         const char *arr[2];
910         char chr_pid[PID_MAX];
911         PmLockNode *node;
912         GVariant *v;
913         enum state_t state;
914         pid_t pid;
915         int ret;
916
917         if (!data) {
918                 _E("Invalid parameter.");
919                 return G_SOURCE_REMOVE;
920         }
921
922         v = (GVariant*)data;
923         g_variant_get(v, "(ii)", &state, &pid);
924
925         if (state == S_LCDOFF && backlight_ops.get_lcd_power() == DPMS_ON) {
926                 _D("Lcd state is PM_LCD_POWER_ON");
927                 return G_SOURCE_CONTINUE;
928         }
929
930         /* Stop checking lock if process had been terminated */
931         if (kill(pid, 0) == -1) {
932                 node = find_node(state, pid);
933                 del_node(state, node);
934                 _I("Process %d not found. Stop checking lock.", pid);
935                 return G_SOURCE_REMOVE;
936         }
937
938         snprintf(chr_pid, sizeof(chr_pid), "%d", pid);
939         arr[0] = chr_pid;
940         switch (state) {
941         case S_NORMAL:
942                 arr[1] = "normal";
943                 break;
944         case S_LCDDIM:
945                 arr[1] = "lcddim";
946                 break;
947         case S_LCDOFF:
948                 arr[1] = "lcdoff";
949                 break;
950         default:
951                 _E("Invalid state.");
952                 g_variant_unref(v);
953                 return G_SOURCE_REMOVE;
954         }
955
956         ret = dbus_handle_method_async_with_reply(RESOURCED_BUS_NAME,
957                 RESOURCED_PATH_PROCESS,
958                 RESOURCED_INTERFACE_PROCESS,
959                 METHOD_APP_STATUS,
960                 "is", arr, pmlock_check_cb, -1, (void *)(intptr_t)state);
961         if (ret < 0)
962                 _E("Failed to call dbus method");
963
964         return G_SOURCE_CONTINUE;
965 }
966
967 /* timeout handler  */
968 gboolean timeout_handler(void *data)
969 {
970         _I("Time out state %s", states[pm_cur_state].name);
971
972         if (timeout_src_id) {
973                 g_source_remove(timeout_src_id);
974                 timeout_src_id = 0;
975         }
976
977         states[pm_cur_state].trans(EVENT_TIMEOUT);
978         return G_SOURCE_REMOVE;
979 }
980
981 void reset_timeout(int timeout)
982 {
983         if (!display_conf.timeout_enable)
984                 return;
985
986         if (pm_cur_state == S_LCDOFF
987         && (is_emulator() == true || display_conf.sleep_support == false))
988                 return;
989
990         _I("Reset timeout(%d ms).", timeout);
991         if (timeout_src_id != 0) {
992                 g_source_remove(timeout_src_id);
993                 timeout_src_id = 0;
994         }
995
996         if (trans_table[pm_cur_state][EVENT_TIMEOUT] == pm_cur_state)
997                 return;
998
999         if (timeout > 0)
1000                 timeout_src_id = g_timeout_add(timeout,
1001                     timeout_handler, NULL);
1002         else if (timeout == 0)
1003                 states[pm_cur_state].trans(EVENT_TIMEOUT);
1004 }
1005
1006 /* get configurations from setting */
1007 static int get_lcd_timeout_from_settings(void)
1008 {
1009         int i;
1010         int val = 0;
1011
1012         for (i = 0; i < S_END; i++) {
1013                 switch (states[i].state) {
1014                 case S_NORMAL:
1015                         get_run_timeout(&val);
1016                         break;
1017                 case S_LCDDIM:
1018                         get_dim_timeout(&val);
1019                         break;
1020                 case S_LCDOFF:
1021                         val = display_conf.lcdoff_timeout;
1022                         break;
1023                 default:
1024                         /* This state doesn't need to set time out. */
1025                         val = 0;
1026                         break;
1027                 }
1028                 if (val > 0)
1029                         states[i].timeout = val;
1030
1031                 _I("State(%s) timeout(%d) ms", states[i].name,
1032                         states[i].timeout);
1033         }
1034
1035         return 0;
1036 }
1037
1038 static void update_display_time(void)
1039 {
1040         int run_timeout, val;
1041
1042         /* first priority : s cover */
1043         if (!hallic_open) {
1044                 states[S_NORMAL].timeout = S_COVER_TIMEOUT;
1045                 _I("S cover closed: Timeout(%d ms) is set by normal.",
1046                     S_COVER_TIMEOUT);
1047                 return;
1048         }
1049
1050         /* second priority : custom timeout */
1051         if (custom_normal_timeout > 0) {
1052                 states[S_NORMAL].timeout = custom_normal_timeout;
1053                 states[S_LCDDIM].timeout = custom_dim_timeout;
1054                 _I("CUSTOM : timeout is set by normal(%d ms), dim(%d ms)",
1055                     custom_normal_timeout, custom_dim_timeout);
1056                 return;
1057         }
1058
1059         /* third priority : lock state */
1060         if ((__get_lock_screen_state() == VCONFKEY_IDLE_LOCK) &&
1061             !get_lock_screen_bg_state()) {
1062                 /* timeout is different according to key or event. */
1063                 states[S_NORMAL].timeout = lock_screen_timeout;
1064                 _I("LOCK: Timeout(%d ms) is set by normal.",
1065                     lock_screen_timeout);
1066                 return;
1067         }
1068
1069         /* default setting */
1070         get_run_timeout(&run_timeout);
1071
1072         /* for sdk
1073          * if the run_timeout is zero, it regards AlwaysOn state
1074          */
1075         if (run_timeout == 0 || display_conf.lcd_always_on) {
1076                 run_timeout = ALWAYS_ON_TIMEOUT;
1077                 _I("LCD always on.");
1078         }
1079
1080         states[S_NORMAL].timeout = run_timeout;
1081
1082         get_dim_timeout(&val);
1083         states[S_LCDDIM].timeout = val;
1084
1085         _I("Normal: NORMAL timeout is set by %d ms", states[S_NORMAL].timeout);
1086         _I("Normal: DIM timeout is set by %d ms", states[S_LCDDIM].timeout);
1087 }
1088
1089 static void update_display_locktime(int time)
1090 {
1091         lock_screen_timeout = time;
1092         update_display_time();
1093 }
1094
1095 void set_dim_state(bool on)
1096 {
1097         _I("Dim state is %d.", on);
1098         update_display_time();
1099         states[pm_cur_state].trans(EVENT_INPUT);
1100 }
1101
1102 static void broadcast_pm_suspend(void)
1103 {
1104         int ret;
1105         long now;
1106
1107         if (pmstate_suspend)
1108                 return;
1109
1110         _D("PM will be changed to sleep.");
1111
1112         pmstate_suspend = PM_SUSPEND;
1113         now = clock_gettime_to_long();
1114         ret = dbus_handle_emit_dbus_signal(NULL,
1115                                                         DEVICED_PATH_DISPLAY,
1116                                                         DEVICED_INTERFACE_DISPLAY,
1117                                                         "sleep",
1118                                                         g_variant_new("(t)", (guint64)now));
1119         if (ret < 0)
1120                 _E("Failed to send dbus signal sleep.");
1121 }
1122
1123 static void broadcast_pm_wakeup(void)
1124 {
1125         int ret;
1126         long now;
1127
1128         if (!pmstate_suspend)
1129                 return;
1130
1131          _D("PM is changed to wakeup.");
1132
1133          pmstate_suspend = PM_WAKEUP;
1134          now = clock_gettime_to_long();
1135          ret = dbus_handle_emit_dbus_signal(NULL,
1136                                                          DEVICED_PATH_DISPLAY,
1137                                                          DEVICED_INTERFACE_DISPLAY,
1138                                                          "wakeup",
1139                                                          g_variant_new("(t)", (guint64)now));
1140          if (ret < 0)
1141                  _E("Failed to send dbus signal wakeup.");
1142
1143 }
1144
1145 void lcd_on_direct(enum device_flags flags)
1146 {
1147         if (power_ops.get_power_lock_support()
1148             && pm_cur_state == S_SLEEP) {
1149                 broadcast_pm_wakeup();
1150                 power_ops.power_lock();
1151         }
1152
1153         pm_cur_state = S_NORMAL;
1154
1155         _D("lcd is on directly");
1156         gettimeofday(&lcdon_tv, NULL);
1157         lcd_on_procedure(LCD_NORMAL, flags);
1158
1159         update_display_locktime(LOCK_SCREEN_INPUT_TIMEOUT);
1160 }
1161
1162 static inline bool check_lcd_is_on(void)
1163 {
1164         if (backlight_ops.get_lcd_power() != DPMS_ON)
1165                 return false;
1166
1167         return true;
1168 }
1169
1170 static int check_lock_condition(enum state_t state)
1171 {
1172         dd_list *elem;
1173         PmLockNode *t = NULL;
1174         int ret = false;
1175         pid_t owner = getpid();
1176
1177         _D("check holdkey block : state of %s", states[state].name);
1178
1179         DD_LIST_FOREACH(cond_head[state], elem, t) {
1180                 if (t->pid != owner && t->background == false) {
1181                         ret = true;
1182                         _I("state change was blocked by pid(%d)!", t->pid);
1183                         break;
1184                 }
1185         }
1186
1187         return ret;
1188 }
1189
1190 static gboolean timer_refresh_cb(gpointer data)
1191 {
1192         struct state *st;
1193
1194         /* state transition */
1195         pm_old_state = pm_cur_state;
1196         pm_cur_state = S_NORMAL;
1197         st = &states[pm_cur_state];
1198
1199         if (st->action)
1200                 st->action(st->timeout);
1201
1202         return 0;
1203 }
1204
1205 int custom_lcdon(int timeout)
1206 {
1207         struct state *st;
1208
1209         if (timeout <= 0)
1210                 return -EINVAL;
1211
1212         if (check_lcd_is_on() == false)
1213                 lcd_on_direct(LCD_ON_BY_GESTURE);
1214
1215         _I("Custom lcd on timeout(%d ms).", timeout);
1216         if (set_custom_lcdon_timeout(timeout) == true)
1217                 update_display_time();
1218
1219         /* state transition */
1220         pm_old_state = pm_cur_state;
1221         pm_cur_state = S_NORMAL;
1222         st = &states[pm_cur_state];
1223
1224         /* enter action */
1225         if (st->action)
1226                 st->action(st->timeout);
1227
1228         g_idle_add(timer_refresh_cb, NULL);
1229
1230         return 0;
1231 }
1232
1233 int custom_lcdoff(enum device_flags flag)
1234 {
1235         struct state *st;
1236
1237         check_processes(S_NORMAL);
1238         check_processes(S_LCDDIM);
1239
1240         /* check holdkey block flag in lock node */
1241         if (check_lock_condition(S_NORMAL) || check_lock_condition(S_LCDDIM)) {
1242                 /*
1243                  * When another proccess is normal lock, device is received call then,
1244                  * call app can be changed to lcd state by proximity.
1245                  * If proximity is near then normal lock will be unlocked.
1246                  */
1247                 if (flag & LCD_OFF_BY_PROXIMITY) {
1248                         _I("custom lcd off by proximity, delete normal lock");
1249                         delete_condition(S_NORMAL);
1250                 } else {
1251                         _I("skip custom lcd off");
1252                         return -ECANCELED;
1253                 }
1254         }
1255
1256         _I("custom lcd off by flag(%d)", flag);
1257         if (backlight_ops.get_lcd_power() == DPMS_ON)
1258                 lcd_off_procedure(flag);
1259
1260         if (set_custom_lcdon_timeout(0) == true)
1261                 update_display_time();
1262
1263         /* state transition */
1264         pm_old_state = pm_cur_state;
1265         pm_cur_state = S_LCDOFF;
1266         st = &states[pm_cur_state];
1267
1268         /* enter action */
1269         if (st->action)
1270                 st->action(st->timeout);
1271
1272         return 0;
1273 }
1274
1275 int display_on_by_reason(const char *reason, int timeout)
1276 {
1277         struct state *st;
1278         int flag;
1279         int str_len;
1280
1281         str_len = strlen(reason);
1282
1283         if (!strncmp(reason, GESTURE_STR, str_len))
1284                 flag = LCD_ON_BY_GESTURE;
1285         else if (!strncmp(reason, EVENT_STR, str_len))
1286                 flag = LCD_ON_BY_EVENT;
1287         else {
1288                 _E("Reason is unkown(%s)", reason);
1289                 return -EINVAL;
1290         }
1291
1292         if (timeout <= 0) {
1293                 _E("Cannot setting timeout %d", timeout);
1294                 return -EINVAL;
1295         }
1296
1297         if (check_lcd_is_on() == false)
1298                 lcd_on_direct(flag);
1299
1300         _I("platform lcd on by %s (%d ms)", reason, timeout);
1301         if (set_custom_lcdon_timeout(timeout) == true)
1302                 update_display_time();
1303
1304         /* state transition */
1305         pm_old_state = pm_cur_state;
1306         pm_cur_state = S_NORMAL;
1307         st = &states[pm_cur_state];
1308
1309         /* enter action */
1310         if (st->action)
1311                 st->action(st->timeout);
1312
1313         return 0;
1314 }
1315
1316 int display_off_by_reason(const char *reason)
1317 {
1318         struct state *st;
1319         int flag;
1320         int str_len;
1321
1322         str_len = strlen(reason);
1323
1324         if (!strncmp(reason, GESTURE_STR, str_len)) {
1325                 check_processes(S_NORMAL);
1326                 check_processes(S_LCDDIM);
1327
1328                 /* check holdkey block flag in lock node */
1329                 if (check_lock_condition(S_NORMAL) || check_lock_condition(S_LCDDIM)) {
1330                         _I("skip platform lcd off by gesture");
1331                         return -ECANCELED;
1332                 }
1333                 flag = LCD_OFF_BY_GESTURE;
1334         } else if (!strncmp(reason, PALM_STR, str_len)) {
1335                 delete_condition(S_NORMAL);
1336                 delete_condition(S_LCDDIM);
1337
1338                 flag = LCD_OFF_BY_PALM;
1339         } else {
1340                 _E("Reason is unkown(%s)", reason);
1341                 return -EINVAL;
1342         }
1343
1344         _I("platform lcd off by %s", reason);
1345         if (backlight_ops.get_lcd_power() == DPMS_ON)
1346                 lcd_off_procedure(flag);
1347
1348         /* state transition */
1349         pm_old_state = pm_cur_state;
1350         pm_cur_state = S_LCDOFF;
1351         st = &states[pm_cur_state];
1352
1353         /* enter action */
1354         if (st->action)
1355                 st->action(st->timeout);
1356
1357         return 0;
1358 }
1359
1360 static void default_proc_change_state_action(enum state_t next, int timeout)
1361 {
1362         struct state *st;
1363
1364         pm_old_state = pm_cur_state;
1365         pm_cur_state = next;
1366
1367         st = &states[pm_cur_state];
1368
1369         if (st && st->action) {
1370                 if (timeout < 0)
1371                         st->action(st->timeout);
1372                 else
1373                         st->action(timeout);
1374         }
1375 }
1376
1377 static int default_proc_change_state(unsigned int cond, pid_t pid)
1378 {
1379         enum state_t next;
1380
1381         next = GET_COND_STATE(cond);
1382         _I("Change process(%d) state to %s.", pid, states[next].name);
1383
1384         switch (next) {
1385         case S_NORMAL:
1386                 if (check_lcd_is_on() == false)
1387                         lcd_on_direct(LCD_ON_BY_EVENT);
1388                 update_display_locktime(LOCK_SCREEN_CONTROL_TIMEOUT);
1389                 default_proc_change_state_action(next, -1);
1390                 break;
1391         case S_LCDDIM:
1392                 default_proc_change_state_action(next, -1);
1393                 break;
1394         case S_LCDOFF:
1395                 if (backlight_ops.get_lcd_power() == DPMS_ON) {
1396                         if (get_proximity_state() == SENSOR_PROXIMITY_NEAR)
1397                                 lcd_off_procedure(LCD_OFF_BY_PROXIMITY);
1398                         else
1399                         lcd_off_procedure(LCD_OFF_BY_EVENT);
1400                 }
1401                 if (set_custom_lcdon_timeout(0))
1402                         update_display_time();
1403                 default_proc_change_state_action(next, -1);
1404                 break;
1405         case S_SLEEP:
1406                 _I("Dangerous requests.");
1407                 /* at first LCD_OFF and then goto sleep */
1408                 /* state transition */
1409                 default_proc_change_state_action(S_LCDOFF, TIMEOUT_NONE);
1410                 delete_condition(S_NORMAL);
1411                 delete_condition(S_LCDDIM);
1412                 delete_condition(S_LCDOFF);
1413                 if (lcdon_broadcast) {
1414                         _I("broadcast lcd off signal at non-lcd device");
1415                         broadcast_lcd_off(SIGNAL_PRE, 0);
1416                         broadcast_lcd_off(SIGNAL_POST, 0);
1417                 }
1418                 default_proc_change_state_action(S_SLEEP, TIMEOUT_NONE);
1419                 break;
1420
1421         default:
1422                 return -EINVAL;
1423         }
1424
1425         return 0;
1426 }
1427
1428 /* update transition condition for application requrements */
1429 static void update_lock_timer(PMMsg *data,
1430                 PmLockNode *node, guint timeout_id)
1431 {
1432         time_t now;
1433
1434         if (data->timeout > 0) {
1435                 time(&now);
1436                 node->time = now;
1437         }
1438
1439         if (node->timeout_id)
1440                 g_source_remove(node->timeout_id);
1441         node->timeout_id = timeout_id;
1442 }
1443
1444 static void proc_condition_lock(PMMsg *data)
1445 {
1446         PmLockNode *tmp;
1447         guint cond_timeout_id = 0;
1448         char pname[PATH_MAX];
1449         pid_t pid = data->pid;
1450         enum state_t state;
1451         int holdkey_block,ret;
1452         bool value = true;
1453         unsigned int flags;
1454         char *lock_type;
1455
1456         state = GET_COND_STATE(data->cond);
1457         if (state == S_START)
1458                 return;
1459
1460         flags = GET_COND_FLAG(data->cond);
1461         get_pname(pid, pname);
1462
1463         if (state == S_LCDOFF && pm_cur_state == S_SLEEP &&
1464             power_ops.get_power_lock() == POWER_UNLOCK)
1465                 proc_change_state(data->cond, INTERNAL_LOCK_PM);
1466
1467         if (data->timeout > 0) {
1468                 /* To pass a pid_t data through the timer infrastructure
1469                  * without memory allocation, a pid_t data becomes typecast
1470                  * to intptr_t and void *(64bit) type. */
1471                 cond_timeout_id = g_timeout_add(
1472                                 data->timeout,
1473                                 states[state].timeout_cb,
1474                                 (void*)((intptr_t)pid));
1475                 if (!cond_timeout_id)
1476                         _E("Failed to register display timer.");
1477         }
1478
1479         holdkey_block = GET_COND_FLAG(data->cond) & PM_FLAG_BLOCK_HOLDKEY;
1480
1481         tmp = find_node(state, pid);
1482         if (!tmp)
1483                 add_node(state, pid, cond_timeout_id, holdkey_block);
1484         else {
1485                 update_lock_timer(data, tmp, cond_timeout_id);
1486                 tmp->holdkey_block = holdkey_block;
1487         }
1488
1489         if (state == S_LCDOFF)
1490                 set_process_active(true, pid);
1491
1492         _I("[%s] locked by %5d with %u ms", states[state].name, pid, data->timeout);
1493         /* for debug */
1494         if (state == S_LCDOFF)
1495                 lock_type = PM_LCDOFF_STR;
1496         else if (state == S_LCDDIM)
1497                 lock_type = PM_LCDDIM_STR;
1498         else if (state == S_NORMAL)
1499                 lock_type = PM_LCDON_STR;
1500         else
1501                 goto skip_broadcast_signal;
1502
1503         /* power lock signal */
1504         ret = dbus_handle_emit_dbus_signal(NULL,
1505                         DEVICED_PATH_DISPLAY,
1506                         DEVICED_INTERFACE_DISPLAY,
1507                         "PowerLock",
1508                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
1509         if (ret < 0)
1510                 _E("Failed to send dbus signal PowerLock.");
1511
1512 skip_broadcast_signal:
1513         _SD("be requested LOCK info pname(%s), holdkeyblock(%d) flags(%d)",
1514             pname, holdkey_block, flags);
1515         set_lock_time(pid, pname, state);
1516
1517         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
1518 }
1519
1520 static void proc_condition_unlock(PMMsg *data)
1521 {
1522         pid_t pid = data->pid;
1523         enum state_t state;
1524         PmLockNode *tmp;
1525         char pname[PATH_MAX];
1526         bool value = false;
1527         unsigned int flags;
1528         int ret;
1529         char *lock_type;
1530
1531         state = GET_COND_STATE(data->cond);
1532         if (!state)
1533                 return;
1534
1535         flags = GET_COND_FLAG(data->cond);
1536         get_pname(pid, pname);
1537
1538         tmp = find_node(state, pid);
1539         del_node(state, tmp);
1540
1541         if (state == S_LCDOFF)
1542                 set_process_active(false, pid);
1543
1544         _I("[%s] unlocked by %5d", states[state].name, pid);
1545         /* for debug */
1546         if (state == S_LCDOFF)
1547                 lock_type =  PM_LCDOFF_STR;
1548         else if (state == S_LCDDIM)
1549                 lock_type = PM_LCDDIM_STR;
1550         else if (state == S_NORMAL)
1551                 lock_type = PM_LCDON_STR;
1552         else
1553                 goto skip_broadcast_signal;
1554
1555         /* power unlock signal */
1556         ret = dbus_handle_emit_dbus_signal(NULL,
1557                         DEVICED_PATH_DISPLAY,
1558                         DEVICED_INTERFACE_DISPLAY,
1559                         "PowerUnlock",
1560                         g_variant_new("(sii)", lock_type, pid, (int)data->timeout));
1561         if (ret < 0)
1562                 _E("Failed to send dbus signal PowerUnlock.");
1563
1564 skip_broadcast_signal:
1565         _SD("be requested UNLOCK info pname(%s) flag(%d)", pname, flags);
1566         set_unlock_time(pid, state);
1567
1568         device_notify(DEVICE_NOTIFIER_DISPLAY_LOCK, (void *)&value);
1569 }
1570
1571 static int proc_condition(PMMsg *data)
1572 {
1573         unsigned int flags;
1574
1575         if (IS_COND_REQUEST_LOCK(data->cond))
1576                 proc_condition_lock(data);
1577
1578         if (IS_COND_REQUEST_UNLOCK(data->cond))
1579                 proc_condition_unlock(data);
1580
1581         if (!display_conf.timeout_enable)
1582                 return 0;
1583
1584         flags = GET_COND_FLAG(data->cond);
1585         if (flags == 0) {
1586                 /* guard time for suspend */
1587                 if (pm_cur_state == S_LCDOFF)
1588                         reset_timeout(states[S_LCDOFF].timeout);
1589         } else {
1590                 if (flags & PM_FLAG_RESET_TIMER)
1591                         reset_timeout(states[pm_cur_state].timeout);
1592         }
1593
1594         if (!timeout_src_id)
1595                 states[pm_cur_state].trans(EVENT_TIMEOUT);
1596
1597         return 0;
1598 }
1599
1600 /* If some changed, return 1 */
1601 int check_processes(enum state_t prohibit_state)
1602 {
1603         dd_list *elem, *next;
1604         PmLockNode *t = NULL;
1605         int ret = 0;
1606
1607         DD_LIST_FOREACH_SAFE(cond_head[prohibit_state], elem, next, t) {
1608                 if (t->pid < INTERNAL_LOCK_BASE && kill(t->pid, 0) == -1) {
1609                         _E("%d process does not exist, delete the REQ"
1610                                 " - prohibit state %d ",
1611                                 t->pid, prohibit_state);
1612                         if (t->pid == custom_change_pid) {
1613                                 get_lcd_timeout_from_settings();
1614                                 custom_normal_timeout = custom_dim_timeout = 0;
1615                                 custom_change_pid = -1;
1616                         }
1617                         ret = 1;
1618                         set_unlock_time(t->pid, prohibit_state);
1619                         del_node(prohibit_state, t);
1620                 }
1621         }
1622
1623         return ret;
1624 }
1625
1626 int check_holdkey_block(enum state_t state)
1627 {
1628         dd_list *elem;
1629         PmLockNode *t = NULL;
1630         int ret = 0;
1631
1632         _I("Check holdkey block: state of %s", states[state].name);
1633
1634         if (custom_holdkey_block == true) {
1635                 _I("Custom hold key blocked by pid(%d).",
1636                         custom_change_pid);
1637                 return 1;
1638         }
1639
1640         DD_LIST_FOREACH(cond_head[state], elem, t) {
1641                 if (t->holdkey_block == true) {
1642                         ret = 1;
1643                         _I("Hold key blocked by pid(%d).", t->pid);
1644                         break;
1645                 }
1646         }
1647
1648         return ret;
1649 }
1650
1651 int delete_condition(enum state_t state)
1652 {
1653         dd_list *elem, *next;
1654         PmLockNode *t = NULL;
1655
1656         _I("delete condition : state of %s", states[state].name);
1657
1658         if (!cond_head[state])
1659                 return 0;
1660
1661         DD_LIST_FOREACH_SAFE(cond_head[state], elem, next, t) {
1662                 if (t->timeout_id > 0) {
1663                         g_source_remove(t->timeout_id);
1664                         t->timeout_id = 0;
1665                 }
1666                 if (state == S_LCDOFF)
1667                         set_process_active(false, t->pid);
1668                 _I("delete node of pid(%d)", t->pid);
1669                 set_unlock_time(t->pid, state);
1670                 del_node(state, t);
1671         }
1672
1673         DD_LIST_FREE_LIST(cond_head[state]);
1674         cond_head[state] = NULL;
1675
1676         return 0;
1677 }
1678
1679 void update_lcdoff_source(int source)
1680 {
1681         int ret;
1682
1683         switch (source) {
1684         case VCONFKEY_PM_LCDOFF_BY_TIMEOUT:
1685                 _I("LCD OFF by timeout.");
1686                 break;
1687         case VCONFKEY_PM_LCDOFF_BY_POWERKEY:
1688                 _I("LCD OFF by powerkey.");
1689                 break;
1690         default:
1691                 _E("Invalid value(%d).", source);
1692                 return;
1693         }
1694         ret = vconf_set_int(VCONFKEY_PM_LCDOFF_SOURCE, source);
1695         if (ret < 0)
1696                 _E("Failed to set vconf value for lcd off source: %d", vconf_get_ext_errno());
1697 }
1698
1699 #ifdef ENABLE_PM_LOG
1700
1701 typedef struct _pm_history {
1702         time_t time;
1703         enum pm_log_type log_type;
1704         int keycode;
1705 } pm_history;
1706
1707 static int max_history_count = MAX_LOG_COUNT;
1708 static pm_history pm_history_log[MAX_LOG_COUNT] = {{0, }, };
1709 static int history_count = 0;
1710
1711 static const char history_string[PM_LOG_MAX][15] = {
1712         "PRESS", "LONG PRESS", "RELEASE", "LCD ON", "LCD ON COMPL", "LCD ON FAIL",
1713         "LCD DIM", "LCD DIM FAIL", "LCD OFF", "LCD OFF COMPL", "LCD OFF FAIL",
1714         "LCD FAIL", "SLEEP"};
1715
1716 void pm_history_init()
1717 {
1718         memset(pm_history_log, 0x0, sizeof(pm_history_log));
1719         history_count = 0;
1720         max_history_count = MAX_LOG_COUNT;
1721 }
1722
1723 void pm_history_save(enum pm_log_type log_type, int code)
1724 {
1725         time_t now;
1726
1727         time(&now);
1728         pm_history_log[history_count].time = now;
1729         pm_history_log[history_count].log_type = log_type;
1730         pm_history_log[history_count].keycode = code;
1731         history_count++;
1732
1733         if (history_count >= max_history_count)
1734                 history_count = 0;
1735 }
1736
1737 void pm_history_print(int fd, int count)
1738 {
1739         int start_index, index, i;
1740         int ret;
1741         char buf[255];
1742         char time_buf[30];
1743
1744         if (count <= 0 || count > max_history_count)
1745                 return;
1746
1747         start_index = (history_count - count + max_history_count)
1748                     % max_history_count;
1749
1750         for (i = 0; i < count; i++) {
1751                 index = (start_index + i) % max_history_count;
1752
1753                 if (pm_history_log[index].time == 0)
1754                         continue;
1755
1756                 if (pm_history_log[index].log_type < PM_LOG_MIN ||
1757                     pm_history_log[index].log_type >= PM_LOG_MAX)
1758                         continue;
1759                 ctime_r(&pm_history_log[index].time, time_buf);
1760                 time_buf[strlen(time_buf) - 1] = 0;
1761                 snprintf(buf, sizeof(buf), "[%3d] %15s %3d %s\n",
1762                         index,
1763                         history_string[pm_history_log[index].log_type],
1764                         pm_history_log[index].keycode,
1765                         time_buf);
1766                 ret = write(fd, buf, strlen(buf));
1767                 if (ret < 0)
1768                         _E("Write() failed: %d", errno);
1769         }
1770 }
1771 #endif
1772
1773 void print_info(int fd)
1774 {
1775         int s_index = 0;
1776         char buf[PATH_MAX + 255];
1777         int i = 1;
1778         int ret;
1779         char pname[PATH_MAX];
1780         PmLockNode *t;
1781         dd_list *elem;
1782         char time_buf[30];
1783
1784         if (fd < 0)
1785                 return;
1786
1787         snprintf(buf, sizeof(buf),
1788                 "\n==========================================="
1789                 "===========================\n");
1790         ret = write(fd, buf, strlen(buf));
1791         if (ret < 0)
1792                 _E("Write() failed: %d", errno);
1793         snprintf(buf, sizeof(buf), "Timeout Info: Run[%dms] Dim[%dms] Off[%dms]\n",
1794                  states[S_NORMAL].timeout,
1795                  states[S_LCDDIM].timeout, states[S_LCDOFF].timeout);
1796         ret = write(fd, buf, strlen(buf));
1797         if (ret < 0)
1798                 _E("Write() failed: %d", errno);
1799
1800         snprintf(buf, sizeof(buf), "Tran. Locked : %s %s %s\n",
1801                  (trans_condition & MASK_NORMAL) ? states[S_NORMAL].name : "-",
1802                  (trans_condition & MASK_DIM) ? states[S_LCDDIM].name : "-",
1803                  (trans_condition & MASK_OFF) ? states[S_LCDOFF].name : "-");
1804         ret = write(fd, buf, strlen(buf));
1805         if (ret < 0)
1806                 _E("Write() failed: %d", errno);
1807
1808         snprintf(buf, sizeof(buf), "Current State: %s\n",
1809                 states[pm_cur_state].name);
1810         ret = write(fd, buf, strlen(buf));
1811         if (ret < 0)
1812                 _E("Write() failed: %d", errno);
1813
1814         snprintf(buf, sizeof(buf), "Current Lock Conditions: \n");
1815         ret = write(fd, buf, strlen(buf));
1816         if (ret < 0)
1817                 _E("Write() failed: %d", errno);
1818
1819         for (s_index = S_NORMAL; s_index < S_END; s_index++) {
1820                 DD_LIST_FOREACH(cond_head[s_index], elem, t) {
1821                         get_pname((pid_t)t->pid, pname);
1822                         ctime_r(&t->time, time_buf);
1823                         time_buf[strlen(time_buf) - 1] = 0;
1824                         snprintf(buf, sizeof(buf),
1825                                  " %d: [%s] locked by pid %d %s %s\n",
1826                                  i++, states[s_index].name, t->pid, pname, time_buf);
1827                         ret = write(fd, buf, strlen(buf));
1828                         if (ret < 0)
1829                                 _E("Write() failed: %d", errno);
1830                 }
1831         }
1832
1833         print_lock_info_list(fd);
1834
1835 #ifdef ENABLE_PM_LOG
1836         pm_history_print(fd, 250);
1837 #endif
1838 }
1839
1840 void save_display_log(const char *path)
1841 {
1842         int fd, ret;
1843         char buf[255];
1844         time_t now_time;
1845         char time_buf[30];
1846
1847         _D("internal state is saved!");
1848
1849         time(&now_time);
1850         ctime_r(&now_time, time_buf);
1851         time_buf[strlen(time_buf) - 1] = 0;
1852
1853         fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0644);
1854         if (fd != -1) {
1855                 snprintf(buf, sizeof(buf),
1856                         "\npm_state_log now-time : %d(s) %s\n\n",
1857                         (int)now_time, time_buf);
1858                 ret = write(fd, buf, strlen(buf));
1859                 if (ret < 0)
1860                         _E("write() failed (%d)", errno);
1861
1862                 snprintf(buf, sizeof(buf), "pm_status_flag: %#x\n", pm_status_flag);
1863                 ret = write(fd, buf, strlen(buf));
1864                 if (ret < 0)
1865                         _E("write() failed (%d)", errno);
1866
1867                 if (disp_plgn.get_lock_screen_state ) {
1868                         snprintf(buf, sizeof(buf), "screen lock status : %d\n",
1869                                 disp_plgn.get_lock_screen_state());
1870                         ret = write(fd, buf, strlen(buf));
1871                         if (ret < 0)
1872                                 _E("write() failed (%d)", errno);
1873                 }
1874                 print_info(fd);
1875                 close(fd);
1876         }
1877
1878         fd = open("/dev/console", O_WRONLY);
1879         if (fd != -1) {
1880                 print_info(fd);
1881                 close(fd);
1882         }
1883 }
1884
1885 /* SIGHUP signal handler
1886  * For debug... print info to syslog
1887  */
1888 static void sig_hup(int signo)
1889 {
1890         _I("received sig hub %d", signo);
1891
1892         pm_save_logdump();
1893 }
1894
1895 int check_lcdoff_direct(void)
1896 {
1897         int ret, lock, cradle;
1898         int hdmi_state;
1899
1900         if (pm_old_state != S_NORMAL)
1901                 return false;
1902
1903         if (pm_cur_state != S_LCDDIM)
1904                 return false;
1905
1906         if (!display_conf.dimming)
1907                 return true;
1908
1909         lock = __get_lock_screen_state();
1910         if (lock != VCONFKEY_IDLE_LOCK && hallic_open)
1911                 return false;
1912
1913         hdmi_state = extcon_get_status(EXTCON_CABLE_HDMI);
1914         if (hdmi_state)
1915                 return false;
1916
1917         ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle);
1918         if (ret >= 0 && cradle == DOCK_SOUND)
1919                 return false;
1920         else if (ret < 0)
1921                 _E("Failed to get vconf value for cradle status: %d", vconf_get_ext_errno());
1922
1923         _D("Goto LCDOFF direct: lock(%d) hdmi(%d) cradle(%d).", lock, hdmi_state, cradle);
1924
1925         return true;
1926 }
1927
1928 static int __check_lcdoff_lock_state(void)
1929 {
1930         if (cond_head[S_LCDOFF] != NULL)
1931                 return true;
1932
1933         return false;
1934 }
1935
1936 /*
1937  * default transition function
1938  *   1. call check
1939  *   2. transition
1940  *   3. call enter action function
1941  */
1942 static int default_trans(int evt)
1943 {
1944         struct state *st = &states[pm_cur_state];
1945         int next_state;
1946
1947         next_state = (enum state_t)trans_table[pm_cur_state][evt];
1948
1949         /* check conditions */
1950         while (st->check && !st->check(pm_cur_state, next_state)) {
1951                 /* There is a condition. */
1952                 _I("%s locked. Trans to %s failed.", states[pm_cur_state].name,
1953                        states[next_state].name);
1954                 if (!check_processes(pm_cur_state)) {
1955                         /* This is valid condition
1956                          * The application that sent the condition is running now. */
1957                         return -1;
1958                 }
1959         }
1960
1961         /* state transition */
1962         pm_old_state = pm_cur_state;
1963         pm_cur_state = next_state;
1964         st = &states[pm_cur_state];
1965
1966         /* enter action */
1967         if (st->action) {
1968                 if (pm_cur_state == S_LCDOFF)
1969                         update_lcdoff_source(VCONFKEY_PM_LCDOFF_BY_TIMEOUT);
1970
1971                 if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDOFF)
1972                         if (set_custom_lcdon_timeout(0) == true)
1973                                 update_display_time();
1974
1975                 if (check_lcdoff_direct() == true) {
1976                         /* enter next state directly */
1977                         states[pm_cur_state].trans(EVENT_TIMEOUT);
1978                 } else {
1979                         if (pm_cur_state == S_SLEEP
1980                         && (is_emulator() == true || display_conf.sleep_support == false))
1981                                 return 0;
1982
1983                         st->action(st->timeout);
1984                 }
1985         }
1986
1987         return 0;
1988 }
1989
1990 static gboolean lcd_on_expired(void *data)
1991 {
1992         int lock_state, ret;
1993
1994         if (lock_timeout_id)
1995                 lock_timeout_id = 0;
1996
1997         /* check state of lock */
1998         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
1999         if (ret > 0 && lock_state == VCONFKEY_IDLE_LOCK)
2000                 return G_SOURCE_REMOVE;
2001         else if (ret < 0)
2002                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
2003
2004         /* lock screen is not launched yet, but lcd is on */
2005         if (check_lcd_is_on() == false)
2006                 lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
2007
2008         return G_SOURCE_REMOVE;
2009 }
2010
2011 static inline void stop_lock_timer(void)
2012 {
2013         if (lock_timeout_id) {
2014                 g_source_remove(lock_timeout_id);
2015                 lock_timeout_id = 0;
2016         }
2017 }
2018
2019 static void check_lock_screen(void)
2020 {
2021         int lock_state, ret;
2022
2023         stop_lock_timer();
2024
2025         /* check state of lock */
2026         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
2027         if (ret < 0 || lock_state == VCONFKEY_IDLE_LOCK)
2028                 return;
2029
2030         /* Use time to check lock is done. */
2031         lock_timeout_id = g_timeout_add(display_conf.lock_wait_time,
2032             lcd_on_expired, NULL);
2033 }
2034
2035 /* default enter action function */
2036 static int default_action(int timeout)
2037 {
2038         int wakeup_count = -1;
2039         time_t now;
2040         double diff;
2041         static time_t last_update_time = 0;
2042         static int last_timeout = 0;
2043         struct timeval now_tv;
2044
2045         if (status != DEVICE_OPS_STATUS_START) {
2046                 _E("Display is not started.");
2047                 return -EINVAL;
2048         }
2049
2050         if (pm_cur_state != S_SLEEP) {
2051                 if (pm_cur_state == S_NORMAL &&
2052                     lcdon_tv.tv_sec != 0) {
2053                         gettimeofday(&now_tv, NULL);
2054                         timeout -= DIFF_TIMEVAL_MS(now_tv, lcdon_tv);
2055                         lcdon_tv.tv_sec = 0;
2056                 }
2057                 /* set timer with current state timeout */
2058                 reset_timeout(timeout);
2059
2060                 if (pm_cur_state == S_NORMAL) {
2061                         time(&last_update_time);
2062                         last_timeout = timeout;
2063                 } else {
2064                         _I("Timout set: %s state %d ms",
2065                             states[pm_cur_state].name, timeout);
2066                 }
2067         }
2068
2069         if (pm_cur_state != pm_old_state && pm_cur_state != S_SLEEP) {
2070                 if (power_ops.get_power_lock_support()) {
2071                         broadcast_pm_wakeup();
2072                         power_ops.power_lock();
2073                 }
2074                 set_setting_pmstate(pm_cur_state);
2075                 device_notify(DEVICE_NOTIFIER_LCD, (void *)&pm_cur_state);
2076         }
2077
2078         if (pm_old_state == S_NORMAL && pm_cur_state != S_NORMAL) {
2079                 time(&now);
2080                 diff = difftime(now, last_update_time);
2081                 _I("S_NORMAL is changed to %s (timeout=%d ms diff=%.0f s).",
2082                     states[pm_cur_state].name, last_timeout, diff);
2083         }
2084
2085         switch (pm_cur_state) {
2086         case S_NORMAL:
2087                 /*
2088                  * normal state : backlight on and restore
2089                  * the previous brightness
2090                  */
2091                 if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP)
2092                         check_lock_screen();
2093                 else if (pm_old_state == S_LCDDIM)
2094                         backlight_ops.update();
2095
2096                 if (check_lcd_is_on() == false)
2097                         lcd_on_procedure(LCD_NORMAL, NORMAL_MODE);
2098                 break;
2099
2100         case S_LCDDIM:
2101                 if (pm_old_state == S_NORMAL &&
2102                     backlight_ops.get_custom_status())
2103                         backlight_ops.save_custom_brightness();
2104                 /* lcd dim state : dim the brightness */
2105                 backlight_ops.dim();
2106
2107                 if (pm_old_state == S_LCDOFF || pm_old_state == S_SLEEP)
2108                         lcd_on_procedure(LCD_DIM, NORMAL_MODE);
2109                 break;
2110
2111         case S_LCDOFF:
2112                 if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF) {
2113                         stop_lock_timer();
2114                         /* lcd off state : turn off the backlight */
2115                         if (backlight_ops.get_lcd_power() == DPMS_ON)
2116                                 lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
2117                 }
2118
2119                 if (backlight_ops.get_lcd_power() == DPMS_ON
2120                     || lcd_paneloff_mode)
2121                         lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
2122                 break;
2123
2124         case S_SLEEP:
2125                 if (pm_old_state != S_SLEEP && pm_old_state != S_LCDOFF)
2126                         stop_lock_timer();
2127
2128                 if (backlight_ops.get_lcd_power() == DPMS_ON)
2129                         lcd_off_procedure(LCD_OFF_BY_TIMEOUT);
2130
2131                 if (!power_ops.get_power_lock_support()) {
2132                         /* sleep state : set system mode to SUSPEND */
2133                         if (power_ops.get_wakeup_count(&wakeup_count) < 0)
2134                                 _E("Wakeup count read error.");
2135
2136                         if (wakeup_count < 0) {
2137                                 _I("Wakup Event. Can not enter suspend mode.");
2138                                 goto go_lcd_off;
2139                         }
2140
2141                         if (power_ops.set_wakeup_count(wakeup_count) < 0) {
2142                                 _E("Wakeup count write error.");
2143                                 goto go_lcd_off;
2144                         }
2145                 }
2146                 goto go_suspend;
2147         }
2148
2149         return 0;
2150
2151 go_suspend:
2152 #ifdef ENABLE_PM_LOG
2153         pm_history_save(PM_LOG_SLEEP, pm_cur_state);
2154 #endif
2155         broadcast_pm_suspend();
2156         if (power_ops.get_power_lock_support()) {
2157                 if (power_ops.enable_autosleep)
2158                         power_ops.enable_autosleep();
2159
2160                 if (power_ops.power_unlock() < 0)
2161                         _E("Power unlock state error.");
2162         } else {
2163                 power_ops.suspend();
2164                 _I("system wakeup!!");
2165                 system_wakeup_flag = true;
2166                 /* Resume !! */
2167                 if (power_ops.check_wakeup_src() == EVENT_DEVICE)
2168                         /* system waked up by devices */
2169                         states[pm_cur_state].trans(EVENT_DEVICE);
2170                 else
2171                         /* system waked up by user input */
2172                         states[pm_cur_state].trans(EVENT_INPUT);
2173         }
2174         return 0;
2175
2176 go_lcd_off:
2177         if (!power_ops.get_power_lock_support()) {
2178                 /* Resume !! */
2179                 states[pm_cur_state].trans(EVENT_DEVICE);
2180         }
2181         return 0;
2182 }
2183
2184 /*
2185  * default check function
2186  *   return
2187  *    0 : can't transit, others : transitable
2188  */
2189 static int default_check(int curr, int next)
2190 {
2191         int trans_cond;
2192
2193         makeup_trans_condition();
2194
2195         trans_cond = trans_condition & MASK_BIT;
2196
2197         if (next == S_NORMAL) /* S_NORMAL is exceptional */
2198                 return 1;
2199
2200         switch (curr) {
2201         case S_NORMAL:
2202                 trans_cond = trans_cond & MASK_NORMAL;
2203                 break;
2204         case S_LCDDIM:
2205                 trans_cond = trans_cond & MASK_DIM;
2206                 break;
2207         case S_LCDOFF:
2208                 trans_cond = trans_cond & MASK_OFF;
2209                 break;
2210         default:
2211                 trans_cond = 0;
2212                 break;
2213         }
2214
2215         if (trans_cond != 0) {
2216                 print_node(curr);
2217                 return 0;
2218         }
2219
2220         return 1;               /* transitable */
2221 }
2222
2223 static void default_saving_mode(int onoff)
2224 {
2225         if (onoff)
2226                 pm_status_flag |= PWRSV_FLAG;
2227         else
2228                 pm_status_flag &= ~PWRSV_FLAG;
2229
2230         if (pm_cur_state == S_NORMAL)
2231                 backlight_ops.update();
2232 }
2233
2234 static int poll_callback(int condition, PMMsg *data)
2235 {
2236         static time_t last_t;
2237         time_t now;
2238
2239         if (status != DEVICE_OPS_STATUS_START) {
2240                 _E("Display logic is not started.");
2241                 return -ECANCELED;
2242         }
2243
2244         if (condition == INPUT_POLL_EVENT) {
2245                 if (pm_cur_state == S_LCDOFF || pm_cur_state == S_SLEEP)
2246                         _I("Input event signal at Display Off");
2247                 time(&now);
2248                 if (last_t != now ||
2249                     pm_cur_state == S_LCDOFF ||
2250                     pm_cur_state == S_SLEEP) {
2251                         states[pm_cur_state].trans(EVENT_INPUT);
2252                         last_t = now;
2253                 }
2254         }
2255
2256         if (condition == PM_CONTROL_EVENT) {
2257                 proc_condition(data);
2258
2259                 if (IS_COND_REQUEST_CHANGE(data->cond))
2260                         proc_change_state(data->cond, data->pid);
2261         }
2262
2263         return 0;
2264 }
2265
2266 static int update_setting(int key_idx, int val)
2267 {
2268         int ret;
2269
2270         switch (key_idx) {
2271         case SETTING_TO_NORMAL:
2272                 update_display_time();
2273                 states[pm_cur_state].trans(EVENT_INPUT);
2274                 break;
2275         case SETTING_HALLIC_OPEN:
2276                 hallic_open = val;
2277                 update_display_time();
2278                 if (pm_cur_state == S_NORMAL || pm_cur_state == S_LCDDIM)
2279                         states[pm_cur_state].trans(EVENT_INPUT);
2280                 else if (pm_cur_state == S_SLEEP && hallic_open)
2281                         proc_change_state(S_LCDOFF, INTERNAL_LOCK_HALLIC);
2282                 break;
2283         case SETTING_LOW_BATT:
2284                 if (low_battery_state(val)) {
2285                         if (!(pm_status_flag & CHRGR_FLAG))
2286                                 power_saving_func(true);
2287                         pm_status_flag |= LOWBT_FLAG;
2288                 } else {
2289                         if (pm_status_flag & PWRSV_FLAG)
2290                                 power_saving_func(false);
2291                         pm_status_flag &= ~LOWBT_FLAG;
2292                         pm_status_flag &= ~BRTCH_FLAG;
2293                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, false);
2294                         if (ret < 0)
2295                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
2296                 }
2297                 break;
2298         case SETTING_CHARGING:
2299                 if (val) {
2300                         if (pm_status_flag & LOWBT_FLAG) {
2301                                 power_saving_func(false);
2302                                 pm_status_flag &= ~LOWBT_FLAG;
2303                         }
2304                         pm_status_flag |= CHRGR_FLAG;
2305                 } else {
2306                         int bat_state;
2307                         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW,
2308                                 &bat_state);
2309                         if (ret < 0) {
2310                                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
2311                                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
2312                         }
2313                         if (low_battery_state(bat_state)) {
2314                                 power_saving_func(true);
2315                                 pm_status_flag |= LOWBT_FLAG;
2316                         }
2317                         pm_status_flag &= ~CHRGR_FLAG;
2318                 }
2319                 break;
2320         case SETTING_BRT_LEVEL:
2321                 if (pm_status_flag & PWRSV_FLAG) {
2322                         pm_status_flag |= BRTCH_FLAG;
2323                         ret = vconf_set_bool(VCONFKEY_PM_BRIGHTNESS_CHANGED_IN_LPM, true);
2324                         if (ret < 0)
2325                                 _E("Failed to set vconf value for brightness changed in lpm: %d", vconf_get_ext_errno());
2326                         _I("Brightness changed in low battery,"
2327                                 "escape dim state.");
2328                 }
2329                 backlight_ops.set_default_brt(val);
2330                 break;
2331         case SETTING_LOCK_SCREEN:
2332                 set_lock_screen_state(val);
2333                 if (val == VCONFKEY_IDLE_UNLOCK) {
2334                         if (CHECK_OPS(keyfilter_ops, backlight_enable))
2335                                 keyfilter_ops->backlight_enable(false);
2336                 }
2337
2338                 /* LCD on if lock screen show before waiting time */
2339                 if (pm_cur_state == S_NORMAL &&
2340                     val == VCONFKEY_IDLE_LOCK &&
2341                     backlight_ops.get_lcd_power() != DPMS_ON &&
2342                         is_lcdon_blocked() == LCDON_BLOCK_NONE)
2343                         lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
2344                 stop_lock_timer();
2345                 update_display_time();
2346                 if (pm_cur_state == S_NORMAL)
2347                         states[pm_cur_state].trans(EVENT_INPUT);
2348                 break;
2349         case SETTING_LOCK_SCREEN_BG:
2350                 set_lock_screen_bg_state(val);
2351                 update_display_time();
2352                 if (pm_cur_state == S_NORMAL)
2353                         states[pm_cur_state].trans(EVENT_INPUT);
2354                 break;
2355         case SETTING_POWEROFF:
2356                 switch (val) {
2357                 case POWEROFF_TYPE_NONE:
2358                         pm_status_flag &= ~PWROFF_FLAG;
2359                         break;
2360                 case POWEROFF_TYPE_DIRECT:
2361                 case POWEROFF_TYPE_RESTART:
2362                         pm_status_flag |= PWROFF_FLAG;
2363                         break;
2364                 }
2365                 break;
2366         case SETTING_POWER_CUSTOM_BRIGHTNESS:
2367                 if (val == VCONFKEY_PM_CUSTOM_BRIGHTNESS_ON)
2368                         backlight_ops.set_custom_status(true);
2369                 else
2370                         backlight_ops.set_custom_status(false);
2371                 break;
2372
2373         default:
2374                 return -1;
2375         }
2376         return 0;
2377 }
2378
2379 static void check_seed_status(void)
2380 {
2381         int ret = -1;
2382         int tmp = 0;
2383         int bat_state;
2384         int brt = 0;
2385         int lock_state;
2386
2387         /* Charging check */
2388         if ((get_charging_status(&tmp) == 0) && (tmp > 0))
2389                 pm_status_flag |= CHRGR_FLAG;
2390
2391         ret = get_setting_brightness(&tmp);
2392         if (ret != 0 || (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS)) {
2393                 _I("Failed to read vconf value for brightness.");
2394                 brt = display_conf.pm_default_brightness;
2395                 if (tmp < PM_MIN_BRIGHTNESS || tmp > PM_MAX_BRIGHTNESS) {
2396                         ret = vconf_set_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, brt);
2397                         if (ret < 0)
2398                                 _E("Failed to set vconf value for lcd brightness: %d", vconf_get_ext_errno());
2399                 }
2400                 tmp = brt;
2401         }
2402         _I("Set brightness(%d) from setting app.", tmp);
2403         backlight_ops.set_default_brt(tmp);
2404         backlight_ops.set_brightness(tmp);
2405
2406         ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_STATUS_LOW, &bat_state);
2407         if (ret < 0) {
2408                 bat_state = VCONFKEY_SYSMAN_BAT_NORMAL;
2409                 _E("Failed to get vconf value for battery status low: %d", vconf_get_ext_errno());
2410         }
2411         if (low_battery_state(bat_state)) {
2412                 if (!(pm_status_flag & CHRGR_FLAG)) {
2413                         power_saving_func(true);
2414                         pm_status_flag |= LOWBT_FLAG;
2415                 }
2416         }
2417
2418         /* lock screen check */
2419         ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, &lock_state);
2420         if (ret < 0) {
2421                 lock_state = -1;
2422                 _E("Failed to get vconf value for idle lock state: %d", vconf_get_ext_errno());
2423         }
2424         set_lock_screen_state(lock_state);
2425         if (lock_state == VCONFKEY_IDLE_LOCK) {
2426                 states[S_NORMAL].timeout = lock_screen_timeout;
2427                 _I("LCD NORMAL timeout(%d ms) is set"
2428                         " for lock screen.", lock_screen_timeout);
2429         }
2430
2431         return;
2432 }
2433
2434 static void init_lcd_operation(void)
2435 {
2436         const struct device_ops *ops = NULL;
2437
2438         ops = find_device("display");
2439         if (!check_default(ops))
2440                 DD_LIST_APPEND(lcdon_ops, ops);
2441
2442         ops = find_device("touchkey");
2443         if (!check_default(ops))
2444                 DD_LIST_APPEND(lcdon_ops, ops);
2445
2446         ops = find_device("touchscreen");
2447         if (!check_default(ops))
2448                 DD_LIST_APPEND(lcdon_ops, ops);
2449 }
2450
2451 static void exit_lcd_operation(void)
2452 {
2453         dd_list *l = NULL;
2454         dd_list *l_next = NULL;
2455         const struct device_ops *ops = NULL;
2456
2457         DD_LIST_FOREACH_SAFE(lcdon_ops, l, l_next, ops)
2458                 DD_LIST_REMOVE_LIST(lcdon_ops, l);
2459 }
2460
2461 enum {
2462         INIT_SETTING = 0,
2463         INIT_INTERFACE,
2464         INIT_POLL,
2465         INIT_FIFO,
2466         INIT_DBUS,
2467         INIT_END
2468 };
2469
2470 static const char *errMSG[INIT_END] = {
2471         [INIT_SETTING] = "setting init error",
2472         [INIT_INTERFACE] = "lowlevel interface(sysfs or others) init error",
2473         [INIT_POLL] = "input devices poll init error",
2474         [INIT_FIFO] = "FIFO poll init error",
2475         [INIT_DBUS] = "d-bus init error",
2476 };
2477
2478 int set_lcd_timeout(int on, int dim, int holdkey_block, const char *name)
2479 {
2480         if (on == 0 && dim == 0) {
2481                 _I("LCD timeout changed: default setting");
2482                 custom_normal_timeout = custom_dim_timeout = 0;
2483         } else if (on < 0 || dim < 0) {
2484                 _E("Failed to set value(on=%d dim=%d).", on, dim);
2485                 return -EINVAL;
2486         } else {
2487                 _I("LCD timeout changed: on=%ds dim=%ds", on, dim);
2488                 custom_normal_timeout = SEC_TO_MSEC(on);
2489                 custom_dim_timeout = SEC_TO_MSEC(dim);
2490         }
2491         /* Apply new backlight time */
2492         update_display_time();
2493         if (pm_cur_state == S_NORMAL)
2494                 states[pm_cur_state].trans(EVENT_INPUT);
2495
2496         if (holdkey_block) {
2497                 custom_holdkey_block = true;
2498                 _I("Hold key disabled.");
2499         } else {
2500                 custom_holdkey_block = false;
2501                 _I("Hold key enabled.");
2502         }
2503
2504         if (custom_change_name) {
2505                 free(custom_change_name);
2506                 custom_change_name = 0;
2507         }
2508
2509         if (custom_normal_timeout == 0 &&
2510             custom_dim_timeout == 0 &&
2511             !holdkey_block)
2512                 return 0;
2513
2514         custom_change_name = strndup(name, strlen(name));
2515         if (!custom_change_name) {
2516                 _E("Failed to malloc.");
2517                 custom_normal_timeout = custom_dim_timeout = 0;
2518                 custom_holdkey_block = false;
2519                 return -ENOMEM;
2520         }
2521
2522         return 0;
2523 }
2524
2525 void reset_lcd_timeout(GDBusConnection *conn,
2526         const gchar     *sender,
2527         const gchar     *unique_name,
2528         gpointer         data)
2529 {
2530         if (!sender)
2531                 return;
2532
2533         if (!custom_change_name)
2534                 return;
2535
2536         if (strcmp(sender, custom_change_name))
2537                 return;
2538
2539         _I("reset lcd timeout: Set default timeout. sender=%s", sender);
2540
2541         free(custom_change_name);
2542         custom_change_name = 0;
2543         custom_normal_timeout = custom_dim_timeout = 0;
2544         custom_holdkey_block = false;
2545
2546         update_display_time();
2547         if (pm_cur_state == S_NORMAL)
2548                 states[pm_cur_state].trans(EVENT_INPUT);
2549 }
2550
2551 static int booting_done(void *data)
2552 {
2553         static bool done = false;
2554
2555         if (!data)
2556                 return done;
2557
2558         done = *(int*)data;
2559         if (!done)
2560                 return done;
2561
2562         _I("Booting done, release booting lock.");
2563         if (disp_plgn.pm_unlock_internal) {
2564                 disp_plgn.pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL, PM_SLEEP_MARGIN);
2565                 disp_plgn.pm_unlock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF, PM_SLEEP_MARGIN);
2566         }
2567
2568         return done;
2569 }
2570
2571 static int process_background(void *data)
2572 {
2573         pid_t pid;
2574         PmLockNode *node;
2575
2576         pid = *(pid_t *)data;
2577
2578         node = find_node(S_NORMAL, pid);
2579         if (node) {
2580                 node->background = true;
2581                 _I("Process(%d) is background, then PM will be unlocked LCD_NORMAL.", pid);
2582         }
2583
2584         return 0;
2585 }
2586
2587 static int process_foreground(void *data)
2588 {
2589         pid_t pid;
2590         PmLockNode *node;
2591
2592         pid = *(pid_t *)data;
2593
2594         node = find_node(S_NORMAL, pid);
2595         if (node) {
2596                 node->background = false;
2597                 _I("Process(%d) is foreground, then PM will be locked LCD_NORMAL.", pid);
2598         }
2599
2600         return 0;
2601 }
2602
2603 static int battery_health_changed(void *data)
2604 {
2605         int health = DATA_VALUE_INT(data);
2606
2607         _I("battery health change %d", health);
2608
2609         if (health == HEALTH_GOOD) {
2610                 pm_status_flag &= ~BATTERY_FLAG;
2611                 pm_status_flag &= ~DIMSTAY_FLAG;
2612         } else if (health == HEALTH_LOW || health == HEALTH_HIGH || health == HEALTH_OVP) {
2613                 pm_status_flag |= BATTERY_FLAG;
2614                 pm_status_flag |= DIMSTAY_FLAG;
2615         }
2616
2617         if (backlight_ops.get_lcd_power() == DPMS_ON)
2618                 backlight_ops.update();
2619
2620         return 0;
2621 }
2622
2623 static int display_load_config(struct parse_result *result, void *user_data)
2624 {
2625         struct display_config *c = user_data;
2626
2627         _D("display_load_config: section=%s name=%s value=%s", result->section, result->name, result->value);
2628
2629         if (!c)
2630                 return -EINVAL;
2631
2632         if (!MATCH(result->section, "Display"))
2633                 return 0;
2634
2635         if (MATCH(result->name, "LockScreenWaitingTime")) {
2636                 SET_CONF(c->lock_wait_time, atof(result->value));
2637                 _D("lock wait time is %.3f", c->lock_wait_time);
2638         } else if (MATCH(result->name, "LongPressInterval")) {
2639                 SET_CONF(c->longpress_interval, atof(result->value));
2640                 _D("long press interval is %.3f", c->longpress_interval);
2641         } else if (MATCH(result->name, "LightSensorSamplingInterval")) {
2642                 SET_CONF(c->lightsensor_interval, atof(result->value));
2643                 _D("lightsensor interval is %.3f", c->lightsensor_interval);
2644         } else if (MATCH(result->name, "LCDOffTimeout")) {
2645                 SET_CONF(c->lcdoff_timeout, atoi(result->value));
2646                 _D("lcdoff timeout is %d ms", c->lcdoff_timeout);
2647         } else if (MATCH(result->name, "BrightnessChangeStep")) {
2648                 SET_CONF(c->brightness_change_step, atoi(result->value));
2649                 _D("brightness change step is %d", c->brightness_change_step);
2650         } else if (MATCH(result->name, "LCDAlwaysOn")) {
2651                 c->lcd_always_on = (MATCH(result->value, "yes") ? 1 : 0);
2652                 _D("LCD always on is %d", c->lcd_always_on);
2653         } else if (MATCH(result->name, "Dimming")) {
2654                 c->dimming = (MATCH(result->value, "yes") ? 1 : 0);
2655                  _D("Dimming is %d", c->dimming);
2656         } else if (MATCH(result->name, "ChangedFrameRateAllowed")) {
2657                 if (strstr(result->value, "setting")) {
2658                         c->framerate_app[REFRESH_SETTING] = 1;
2659                         _D("framerate app is Setting");
2660                 }
2661                 if (strstr(result->value, "all")) {
2662                         memset(c->framerate_app, 1, sizeof(c->framerate_app));
2663                         _D("framerate app is All");
2664                 }
2665         } else if (MATCH(result->name, "ControlDisplay")) {
2666                 c->control_display = (MATCH(result->value, "yes") ? 1 : 0);
2667                 _D("ControlDisplay is %d", c->control_display);
2668         } else if (MATCH(result->name, "PowerKeyDoublePressSupport")) {
2669                 c->powerkey_doublepress = (MATCH(result->value, "yes") ? 1 : 0);
2670                 _D("PowerKeyDoublePressSupport is %d", c->powerkey_doublepress);
2671         } else if (MATCH(result->name, "AccelSensorOn")) {
2672                 c->accel_sensor_on = (MATCH(result->value, "yes") ? 1 : 0);
2673                 _D("AccelSensorOn is %d", c->accel_sensor_on);
2674         } else if (MATCH(result->name, "ContinuousSampling")) {
2675                 c->continuous_sampling = (MATCH(result->value, "yes") ? 1 : 0);
2676                 _D("ContinuousSampling is %d", c->continuous_sampling);
2677         } else if (MATCH(result->name, "TimeoutEnable")) {
2678                 c->timeout_enable = (MATCH(result->value, "yes") ? true : false);
2679                 _D("Timeout is %s", c->timeout_enable ? "enalbed" : "disabled");
2680         } else if (MATCH(result->name, "InputSupport")) {
2681                 c->input_support = (MATCH(result->value, "yes") ? true : false);
2682                 _D("Input is %s", c->input_support ? "supported" : "NOT supported");
2683         } else if (MATCH(result->name, "LockCheckTimeout")) {
2684                 SET_CONF(c->lockcheck_timeout, atoi(result->value));
2685                 _D("LockCheckTimeout is %d", c->lockcheck_timeout);
2686         } else if (MATCH(result->name, "AODTSP")) {
2687                 c->aod_tsp = (MATCH(result->value, "yes") ? true : false);
2688                 _D("TSP control at is %d at aod", c->aod_tsp);
2689         } else if (MATCH(result->name, "SleepSupport")) {
2690                 c->sleep_support = (MATCH(result->value, "yes") ? true : false);
2691                 _D("SleepSupport is %d", c->sleep_support);
2692         }
2693
2694         return 0;
2695 }
2696
2697 static gboolean delayed_init_dpms(gpointer data)
2698 {
2699         int timeout;
2700
2701         if (!init_dpms())
2702                 return G_SOURCE_CONTINUE;
2703
2704         switch (pm_cur_state) {
2705         case S_NORMAL:
2706         case S_LCDDIM:
2707                 lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
2708                 if (display_conf.timeout_enable) {
2709                         timeout = states[S_NORMAL].timeout;
2710                         /* check minimun lcd on time */
2711                         if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
2712                                 timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
2713                         reset_timeout(timeout);
2714                 }
2715                 break;
2716         case S_LCDOFF:
2717                 lcd_off_procedure(LCD_OFF_BY_EVENT);
2718                 timeout = display_conf.lcdoff_timeout;
2719                 reset_timeout(timeout);
2720                 break;
2721         default:
2722                 break;
2723         }
2724
2725         return G_SOURCE_REMOVE;
2726 }
2727
2728 static void add_timer_for_init_dpms(void)
2729 {
2730         guint id = g_timeout_add(500/* milliseconds */, delayed_init_dpms, NULL);
2731         if (id == 0)
2732                 _E("Failed to add init_dpms timeout.");
2733 }
2734
2735 /**
2736  * Power manager Main
2737  *
2738  */
2739 static int display_probe(void *data)
2740 {
2741         int ret;
2742
2743         /**
2744          * load display service
2745          * if there is no display shared library,
2746          * deviced does not provide any method and function of display.
2747          */
2748         ret = display_service_load();
2749         if (ret)
2750                 return ret;
2751
2752         /* display_plugin instance initialization */
2753         init_pm_internal();
2754         disp_plgn.check_lcdoff_lock_state = __check_lcdoff_lock_state;
2755
2756         return 0;
2757 }
2758
2759 static int input_init_handler(void)
2760 {
2761         if (!display_conf.input_support)
2762                 return 0;
2763
2764         g_idle_add(init_input, NULL);
2765
2766         return 0;
2767 }
2768
2769 static void esd_action(void)
2770 {
2771         const struct device_ops *touchscreen_ops = NULL;
2772
2773         _I("ESD on");
2774
2775         touchscreen_ops = find_device("touchscreen");
2776
2777         if (!check_default(touchscreen_ops))
2778                 touchscreen_ops->stop(NORMAL_MODE);
2779         backlight_ops.off(NORMAL_MODE);
2780         backlight_ops.on(NORMAL_MODE);
2781         if (!check_default(touchscreen_ops))
2782                 touchscreen_ops->start(NORMAL_MODE);
2783 }
2784
2785 static void lcd_uevent_changed(struct udev_device *dev)
2786 {
2787         const char *devpath;
2788         const char *action;
2789
2790         devpath = udev_device_get_devpath(dev);
2791         if (!devpath)
2792                 return;
2793
2794         if (!fnmatch(LCD_ESD_PATH, devpath, 0)) {
2795                 action = udev_device_get_action(dev);
2796                 if (!strcmp(action, UDEV_CHANGE))
2797                         esd_action();
2798         }
2799 }
2800
2801 static const struct uevent_handler lcd_uevent_ops = {
2802         .subsystem      = LCD_EVENT_SUBSYSTEM,
2803         .uevent_func    = lcd_uevent_changed,
2804         .data           = NULL,
2805 };
2806
2807 static void display_init(void *data)
2808 {
2809         int ret, i;
2810         unsigned int flags = (WITHOUT_STARTNOTI | FLAG_X_DPMS);
2811         int timeout = 0;
2812
2813         _I("Start power manager.");
2814
2815         signal(SIGHUP, sig_hup);
2816
2817         power_saving_func = default_saving_mode;
2818
2819         /* load configutation */
2820         ret = config_parse(DISPLAY_CONF_FILE, display_load_config, &display_conf);
2821         if (ret < 0)
2822                 _W("Failed to load '%s', use default value: %d",
2823                     DISPLAY_CONF_FILE, ret);
2824
2825         register_kernel_uevent_control(&lcd_uevent_ops);
2826
2827         register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
2828         register_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background);
2829         register_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground);
2830         register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed);
2831         register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed);
2832         register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing);
2833
2834         init_save_userlock();
2835
2836         for (i = INIT_SETTING; i < INIT_END; i++) {
2837                 switch (i) {
2838                 case INIT_SETTING:
2839                         ret = init_setting(update_setting);
2840                         break;
2841                 case INIT_INTERFACE:
2842                         if (display_conf.timeout_enable)
2843                                 get_lcd_timeout_from_settings();
2844                         ret = init_sysfs(flags);
2845                         break;
2846                 case INIT_POLL:
2847                         _I("input init");
2848                         pm_callback = poll_callback;
2849                         ret = input_init_handler();
2850
2851                         pm_lock_detector_init();
2852                         break;
2853                 case INIT_DBUS:
2854                         _I("Dbus init.");
2855                         ret = init_pm_dbus();
2856                         break;
2857                 }
2858                 if (ret != 0) {
2859                         _E("Failed to init: %s", errMSG[i]);
2860                         break;
2861                 }
2862         }
2863
2864         if (i == INIT_END) {
2865                 display_ops_init(NULL);
2866 #ifdef ENABLE_PM_LOG
2867                 pm_history_init();
2868 #endif
2869                 init_lcd_operation();
2870                 check_seed_status();
2871
2872                 /* In smd test, TSP should be turned off if display panel is not existed. */
2873                 if (backlight_ops.get_lcd_power() == -ENOENT) {
2874                         _I("Display panel is not existed.");
2875                         lcd_direct_control(DPMS_OFF, NORMAL_MODE);
2876                         exit_lcd_operation();
2877                 }
2878
2879                 /* wm_ready needs to be checked
2880                  * since display manager can be launched later than deviced.
2881                  * In the case, display cannot be turned on at the first booting */
2882                 // wm_ready = check_wm_ready();
2883                 if (init_dpms()) {
2884                         lcd_on_procedure(LCD_NORMAL, LCD_ON_BY_EVENT);
2885                         if (is_lcdon_blocked() != LCDON_BLOCK_NONE)
2886                                 lcd_off_procedure(LCD_OFF_BY_EVENT);
2887                 } else {
2888                         add_timer_for_init_dpms();
2889                 }
2890
2891                 if (display_conf.lcd_always_on) {
2892                         _I("LCD always on.");
2893                         trans_table[S_NORMAL][EVENT_TIMEOUT] = S_NORMAL;
2894                 }
2895
2896                 if (flags & WITHOUT_STARTNOTI) {        /* start without noti */
2897                         _I("Start Power managing without noti");
2898                         if (power_ops.get_power_lock_support()) {
2899                                 broadcast_pm_wakeup();
2900                                 power_ops.power_lock();
2901                         }
2902                         /*
2903                          * Lock lcd off until booting is done.
2904                          * deviced guarantees all booting script is executing.
2905                          * Last script of booting unlocks this suspend blocking state.
2906                          */
2907                         if (disp_plgn.pm_lock_internal)
2908                                 disp_plgn.pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_OFF,
2909                                                 STAY_CUR_STATE, BOOTING_DONE_WATING_TIME);
2910
2911                         /* Initial display state right after the booting done */
2912                         if (is_lcdon_blocked())
2913                                 pm_cur_state = S_LCDOFF;
2914                         else
2915                                 pm_cur_state = S_NORMAL;
2916                         ret = vconf_set_int(VCONFKEY_PM_STATE, pm_cur_state);
2917                         if (ret < 0)
2918                                 _E("Failed to set vconf value for pm cur state: %d", vconf_get_ext_errno());
2919
2920                         status = DEVICE_OPS_STATUS_START;
2921                         if (display_conf.timeout_enable) {
2922                                 timeout = states[S_NORMAL].timeout;
2923                                 /* check minimun lcd on time */
2924                                 if (timeout < SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT))
2925                                         timeout = SEC_TO_MSEC(DEFAULT_NORMAL_TIMEOUT);
2926
2927                                 if (disp_plgn.pm_lock_internal)
2928                                         disp_plgn.pm_lock_internal(INTERNAL_LOCK_BOOTING, LCD_NORMAL,
2929                                                         STAY_CUR_STATE, timeout);
2930                         }
2931
2932                 }
2933
2934                 if (display_conf.input_support)
2935                         if (CHECK_OPS(keyfilter_ops, init))
2936                                 keyfilter_ops->init();
2937         }
2938 }
2939
2940 static void display_exit(void *data)
2941 {
2942         int i = INIT_END;
2943
2944         status = DEVICE_OPS_STATUS_STOP;
2945
2946         /* Set current state to S_NORMAL */
2947         pm_cur_state = S_NORMAL;
2948         set_setting_pmstate(pm_cur_state);
2949         /* timeout is not needed */
2950         reset_timeout(TIMEOUT_NONE);
2951
2952         if (CHECK_OPS(keyfilter_ops, exit))
2953                 keyfilter_ops->exit();
2954
2955         unregister_kernel_uevent_control(&lcd_uevent_ops);
2956
2957         display_ops_exit(NULL);
2958
2959         for (i = i - 1; i >= INIT_SETTING; i--) {
2960                 switch (i) {
2961                 case INIT_SETTING:
2962                         exit_setting();
2963                         break;
2964                 case INIT_INTERFACE:
2965                         exit_sysfs();
2966                         break;
2967                 case INIT_POLL:
2968                         unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done);
2969                         unregister_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background);
2970                         unregister_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground);
2971                         unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed);
2972                         unregister_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed);
2973
2974                         exit_input();
2975                         break;
2976                 }
2977         }
2978
2979         exit_lcd_operation();
2980         free_lock_info_list();
2981
2982         /* free display service */
2983         display_service_free();
2984
2985         _I("Stop power manager.");
2986 }
2987
2988 static int display_start(enum device_flags flags)
2989 {
2990         const struct display_ops *enhance_ops = NULL;
2991         bool on = true;
2992
2993         /* NORMAL MODE */
2994         if (flags & NORMAL_MODE) {
2995                 if (flags & LCD_PANEL_OFF_MODE)
2996                         /* standby on */
2997                         backlight_ops.standby(true);
2998                 else
2999                         /* normal lcd on */
3000                         backlight_ops.on(flags);
3001                 FIND_DISPLAY(enhance_ops, "enhance");
3002                 if (enhance_ops && enhance_ops->func)
3003                         enhance_ops->func(RESTORE_ENHANCE_OUTDOOR, &on);
3004                 return 0;
3005         }
3006
3007         /* CORE LOGIC MODE */
3008         if (!(flags & CORE_LOGIC_MODE))
3009                 return 0;
3010
3011         if (status == DEVICE_OPS_STATUS_START)
3012                 return -EALREADY;
3013
3014         if (display_probe(NULL) < 0)
3015                 return -EPERM;
3016
3017         display_init(NULL);
3018
3019         return 0;
3020 }
3021
3022 static int display_stop(enum device_flags flags)
3023 {
3024         /* NORMAL MODE */
3025         if (flags & NORMAL_MODE || flags & FORCE_OFF_MODE) {
3026                 backlight_ops.off(flags);
3027                 return 0;
3028         }
3029
3030         /* CORE LOGIC MODE */
3031         if (!(flags & CORE_LOGIC_MODE))
3032                 return 0;
3033
3034         if (status == DEVICE_OPS_STATUS_STOP)
3035                 return -EALREADY;
3036
3037         display_exit(NULL);
3038
3039         return 0;
3040 }
3041
3042 static int display_status(void)
3043 {
3044         return status;
3045 }
3046
3047 static const struct device_ops display_device_ops = {
3048         .priority = DEVICE_PRIORITY_HIGH,
3049         DECLARE_NAME_LEN("display"),
3050         .probe    = display_probe,
3051         .init     = display_init,
3052         .exit     = display_exit,
3053         .start    = display_start,
3054         .stop     = display_stop,
3055         .status   = display_status,
3056 };
3057
3058 DEVICE_OPS_REGISTER(&display_device_ops)
3059
3060 /**
3061  * @}
3062  */