4 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * @file display-state-transition.c
21 * @brief This file has functions related to display state transition
24 #include "core/udev.h"
25 #include "device-interface.h"
26 #include "display-state-transition.h"
27 #include "display-lock.h"
28 #include "display-plugin.h"
29 #include "extcon/extcon.h"
30 #include "power/power-suspend.h"
31 #include "shared/log.h"
33 #define ALWAYS_ON_TIMEOUT 360000000
35 static guint state_transition_timer_id;
36 static unsigned int custom_normal_timeout = 0;
37 static unsigned int custom_dim_timeout = 0;
38 static int lock_screen_timeout = LOCK_SCREEN_INPUT_TIMEOUT;
40 static int trans_table[S_END][EVENT_END] = {
42 { S_START, S_START }, /* S_START */
43 { S_LCDDIM, S_NORMAL }, /* S_NORMAL */
44 { S_LCDOFF, S_NORMAL }, /* S_LCDDIM */
45 { S_SLEEP, S_NORMAL }, /* S_LCDOFF */
46 { S_SLEEP, S_STANDBY }, /* S_STANDBY */
47 { S_LCDOFF, S_NORMAL }, /* S_SLEEP */
48 { S_POWEROFF, S_POWEROFF }, /* S_POWEROFF */
51 static bool is_display_state_valid(enum state_t display_state)
53 return (display_state >= S_START && display_state < S_END);
56 static bool is_device_event_type_valid(int event_type)
58 return (event_type >= EVENT_TIMEOUT && event_type < EVENT_END);
61 int display_state_transition_get_next_transition_display_state(enum state_t from_state, enum state_t *to_state, int evt_type)
63 if (!to_state || !is_display_state_valid(from_state) || !is_device_event_type_valid(evt_type))
66 *to_state = trans_table[from_state][evt_type];
70 int display_state_transition_set_transition_table_display_state(enum state_t display_state, enum state_t set_state, int evt_type)
72 if (!is_display_state_valid(display_state) || !is_device_event_type_valid(evt_type) || !is_display_state_valid(set_state))
75 trans_table[display_state][evt_type] = set_state;
79 static void remove_state_transition(void)
81 if (state_transition_timer_id) {
82 g_source_remove(state_transition_timer_id);
83 state_transition_timer_id = 0;
87 static gboolean state_transition_timeout_handler(void *data)
89 const char *state_name = NULL;
90 display_plugin_state_get_name(get_pm_cur_state(), &state_name);
91 _I("Time out state %s", state_name);
93 remove_state_transition();
95 display_plugin_state_do_default_trans(get_pm_cur_state(), EVENT_TIMEOUT);
96 return G_SOURCE_REMOVE;
99 bool display_state_transition_is_there_state_transition_timer(void)
101 return (state_transition_timer_id != 0);
104 int display_state_transition_reset_state_transition_timeout(int timeout)
107 if (!display_plugin_config_get_timeout_enable(&timeout_enable) && (!timeout_enable))
110 if ((get_pm_cur_state() == S_LCDOFF)
111 && (is_emulator() == true || timeout_sleep_support == false))
114 _I("Reset timeout(%d ms) pm_cur_state(%d).", timeout, get_pm_cur_state());
115 remove_state_transition();
117 if (trans_table[get_pm_cur_state()][EVENT_TIMEOUT] == get_pm_cur_state())
121 state_transition_timer_id = g_timeout_add(timeout,
122 state_transition_timeout_handler, NULL);
123 else if (timeout == 0)
124 display_plugin_state_do_default_trans(get_pm_cur_state(), EVENT_TIMEOUT);
129 int display_state_transition_set_custom_timeout(enum state_t state, unsigned int timeout)
131 const char *state_name = NULL;
135 custom_normal_timeout = timeout;
138 custom_dim_timeout = timeout;
141 display_plugin_state_get_name(state, &state_name);
142 _W("%s state has no custom timeout", state_name);
148 int display_state_transition_get_custom_timeout(enum state_t state, unsigned int *timeout)
153 const char *state_name = NULL;
157 *timeout = custom_normal_timeout;
160 *timeout = custom_dim_timeout;
164 display_plugin_state_get_name(state, &state_name);
165 _W("There is no specific timeout value for %s state", state_name);
171 int display_state_transition_set_lock_screen_timeout(int timeout)
173 lock_screen_timeout = timeout;
177 int display_state_transition_get_lock_screen_timeout(int *timeout)
182 *timeout = lock_screen_timeout;
186 void display_state_transition_update_display_state_timeout_by_priority(void)
188 int run_timeout, val;
189 int lcd_always_on = 0;
190 int normal_state_timeout = 0;
191 int dim_state_timeout = 0;
193 /* first priority : custom timeout */
194 if (custom_normal_timeout > 0) {
195 display_plugin_state_set_timeout(S_NORMAL, custom_normal_timeout);
196 display_plugin_state_set_timeout(S_LCDDIM, custom_dim_timeout);
197 _I("CUSTOM : timeout is set by normal(%u ms), dim(%u ms)",
198 custom_normal_timeout, custom_dim_timeout);
202 /* second priority : lock state */
203 if ((__get_lock_screen_state() == VCONFKEY_IDLE_LOCK) &&
204 !get_lock_screen_bg_state()) {
205 /* timeout is different according to key or event. */
206 display_plugin_state_set_timeout(S_NORMAL, lock_screen_timeout);
207 _I("LOCK: Timeout(%d ms) is set by normal.",
208 lock_screen_timeout);
212 /* default setting */
213 get_run_timeout(&run_timeout);
216 * if the run_timeout is zero, it regards AlwaysOn state
218 display_plugin_config_get_lcd_always_on(&lcd_always_on);
219 if (run_timeout == 0 || lcd_always_on) {
220 run_timeout = ALWAYS_ON_TIMEOUT;
221 _I("LCD always on.");
224 display_plugin_state_set_timeout(S_NORMAL, run_timeout);
226 get_dim_timeout(&val);
227 display_plugin_state_set_timeout(S_LCDDIM, val);
229 display_plugin_state_get_timeout(S_NORMAL, &normal_state_timeout);
230 display_plugin_state_get_timeout(S_LCDDIM, &dim_state_timeout);
231 _I("Normal: NORMAL timeout is set by %d ms", normal_state_timeout);
232 _I("Normal: DIM timeout is set by %d ms", dim_state_timeout);
235 static bool is_display_state_valid_for_transition(enum state_t state)
250 int display_state_transition_check_state_transition_condition(enum state_t cur_state, enum state_t next_state)
254 if (!is_display_state_valid_for_transition(cur_state))
257 makeup_trans_condition();
259 trans_cond = get_trans_condition() & MASK_BIT;
261 if (next_state == S_NORMAL) /* S_NORMAL is exceptional */
266 trans_cond = trans_cond & MASK_NORMAL;
269 trans_cond = trans_cond & MASK_DIM;
272 trans_cond = trans_cond & MASK_OFF;
279 if (trans_cond != 0) {
280 print_node(cur_state);
284 return 0; /* transitable */
287 int display_state_transition_update_lcdoff_reason(int source)
292 case VCONFKEY_PM_LCDOFF_BY_TIMEOUT:
293 _I("LCD OFF by timeout.");
295 case VCONFKEY_PM_LCDOFF_BY_POWERKEY:
296 _I("LCD OFF by powerkey.");
299 _E("Invalid value(%d).", source);
302 ret = vconf_set_int(VCONFKEY_PM_LCDOFF_SOURCE, source);
304 _E("Failed to set vconf value for lcd off source: %d", vconf_get_ext_errno());
311 /* FIXME: In this function, extcon checking should be considered after relocating this. */
312 bool display_state_transition_is_possible_to_go_lcdoff(void)
314 int ret, lock, cradle;
318 if (get_pm_old_state() != S_NORMAL)
321 if (get_pm_cur_state() != S_LCDDIM)
324 display_plugin_config_get_dimming(&dimming);
328 lock = __get_lock_screen_state();
329 if (lock != VCONFKEY_IDLE_LOCK)
332 hdmi_state = extcon_get_status(EXTCON_CABLE_HDMI);
336 ret = vconf_get_int(VCONFKEY_SYSMAN_CRADLE_STATUS, &cradle);
337 if (ret >= 0 && cradle == DOCK_SOUND)
340 _E("Failed to get vconf value for cradle status: %d", vconf_get_ext_errno());
342 _D("Goto LCDOFF direct: lock(%d) hdmi(%d) cradle(%d).", lock, hdmi_state, cradle);