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