From a3c2a44af4d13ae1bcc3de197f189187a5fabb21 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 12 Oct 2020 14:33:32 +0900 Subject: [PATCH 01/16] Fix dbus call of default_pmlock_check() For non-killable daemons, the return of resourced's CheckAppStatus is always ignored. Therefore, fix not to call CheckAppStatus when the pmlock_check is checking non-killable daemon, not app. Change-Id: Ifeef32754c9d94a18ad302b97927407de91b83d8 Signed-off-by: Youngjae Cho Signed-off-by: lokilee73 --- src/display/display-lock.c | 48 ++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/display/display-lock.c b/src/display/display-lock.c index c7d88c7..2df1497 100644 --- a/src/display/display-lock.c +++ b/src/display/display-lock.c @@ -64,15 +64,34 @@ static void refresh_app_cond() trans_condition |= MASK_OFF; } +static void broadcast_pmlock_expired(pid_t pid, enum state_t state, const char* appid, time_t locktime) +{ + time_t now; + double diff; + int ret; + + time(&now); + diff = difftime(now, locktime); + + CRITICAL_LOG("%s(%d) has held %s lock for a long time(%.0f s).", + appid ? appid : "NULL", pid, state_st(state)->name + 2, diff); + + ret = dbus_handle_emit_dbus_signal(NULL, + DEVICED_PATH_DISPLAY, + DEVICED_INTERFACE_DISPLAY, + "pmlock_expired", + g_variant_new("(ii)", pid, (int)diff)); + if (ret < 0) + _E("Failed to send dbus pmlock_expired"); +} + static void default_pmlock_check_cb(GVariant *var, void *user_data, GError *err) { pid_t pid = 0; - int ret, detected = 0; + int detected = 0; char *app_id = NULL; enum state_t state = (enum state_t) user_data; PmLockNode *node; - time_t now; - double diff; if (!var) return; @@ -82,26 +101,14 @@ static void default_pmlock_check_cb(GVariant *var, void *user_data, GError *err) goto out; } - if (is_app(pid) == 1 && !detected) + if (!detected) goto out; node = find_node(state, pid); if (!node) goto out; - time(&now); - diff = difftime(now, node->time); - - CRITICAL_LOG("%s(%d) has held %s lock for a long time(%.0f s).", - app_id, pid, state_st(state)->name + 2, diff); - - ret = dbus_handle_emit_dbus_signal(NULL, - DEVICED_PATH_DISPLAY, - DEVICED_INTERFACE_DISPLAY, - "pmlock_expired", - g_variant_new("(ii)", pid, (int)diff)); - if (ret < 0) - _E("Failed to send dbus pmlock_expired"); + broadcast_pmlock_expired(pid, state, app_id, node->time); out: if (app_id) @@ -140,6 +147,13 @@ static gboolean default_pmlock_check(void *data) return G_SOURCE_REMOVE; } + if (!is_app(pid)) { + /* For (non-killable) daemon, + * no need to ask resourced if it is abnormal lock */ + broadcast_pmlock_expired(pid, state, NULL, node->time); + return G_SOURCE_CONTINUE; + } + snprintf(chr_pid, sizeof(chr_pid), "%d", pid); arr[0] = chr_pid; switch (state) { -- 2.7.4 From 5fc02e79c7be0e6cf372ecf8f09ccd2f67147519 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 13 Oct 2020 12:28:30 +0900 Subject: [PATCH 02/16] Apply dpms cache globally Existing get_lcd_power() accesses to node directly, but it now uses dpms_get_cached_state() instead. Accessing to the node is separated into another function, get_lcd_power_node(). Change-Id: Ic05ce15d0fd1ec603c88db470144631a7e1b3ebd Signed-off-by: Youngjae Cho --- plugins/iot/display/device-interface.c | 14 +++----------- plugins/mobile/display/device-interface.c | 14 +++----------- plugins/tv/display/device-interface.c | 14 +++----------- plugins/wearable/display/device-interface.c | 14 +++----------- src/display/device-interface.h | 2 +- src/touchscreen/touchscreen.c | 7 ++----- 6 files changed, 15 insertions(+), 50 deletions(-) diff --git a/plugins/iot/display/device-interface.c b/plugins/iot/display/device-interface.c index 06ca0ad..ea407fb 100644 --- a/plugins/iot/display/device-interface.c +++ b/plugins/iot/display/device-interface.c @@ -153,14 +153,6 @@ static int get_lcd_power_node(void) } } -static int get_lcd_power(void) -{ - if (display_dev && display_dev->get_state) - return get_lcd_power_node(); - else - return dpms_get_state(); -} - bool display_dimstay_check(void) { if (get_pm_status_flag() & DIM_FLAG) @@ -357,7 +349,7 @@ static int backlight_standby(int force) { int ret = -1; - if ((get_lcd_power() == DPMS_ON) || force) { + if ((dpms_get_cached_state() == DPMS_ON) || force) { _I("LCD standby"); ret = bl_onoff(DPMS_STANDBY, 0); } @@ -740,8 +732,8 @@ static struct _backlight_ops backlight_ops = { .standby = backlight_standby, .set_default_brt = set_default_brt, .get_default_brt = get_default_brt, - .get_lcd_power = get_lcd_power, - .get_lcd_power_cached = dpms_get_cached_state, + .get_lcd_power = dpms_get_cached_state, + .get_lcd_power_node = get_lcd_power_node, .set_custom_status = set_custom_status, .get_custom_status = get_custom_status, .save_custom_brightness = save_custom_brightness, diff --git a/plugins/mobile/display/device-interface.c b/plugins/mobile/display/device-interface.c index b1a1356..d4ef77b 100644 --- a/plugins/mobile/display/device-interface.c +++ b/plugins/mobile/display/device-interface.c @@ -152,14 +152,6 @@ static int get_lcd_power_node(void) } } -static int get_lcd_power(void) -{ - if (display_dev && display_dev->get_state) - return get_lcd_power_node(); - else - return dpms_get_state(); -} - bool display_dimstay_check(void) { if (get_pm_status_flag() & DIM_FLAG) @@ -356,7 +348,7 @@ static int backlight_standby(int force) { int ret = -1; - if ((get_lcd_power() == DPMS_ON) || force) { + if ((dpms_get_cached_state() == DPMS_ON) || force) { _I("LCD standby"); ret = bl_onoff(DPMS_STANDBY, 0); } @@ -739,8 +731,8 @@ static struct _backlight_ops backlight_ops = { .standby = backlight_standby, .set_default_brt = set_default_brt, .get_default_brt = get_default_brt, - .get_lcd_power = get_lcd_power, - .get_lcd_power_cached = dpms_get_cached_state, + .get_lcd_power = dpms_get_cached_state, + .get_lcd_power_node = get_lcd_power_node, .set_custom_status = set_custom_status, .get_custom_status = get_custom_status, .save_custom_brightness = save_custom_brightness, diff --git a/plugins/tv/display/device-interface.c b/plugins/tv/display/device-interface.c index 9a47571..da6583c 100644 --- a/plugins/tv/display/device-interface.c +++ b/plugins/tv/display/device-interface.c @@ -153,14 +153,6 @@ static int get_lcd_power_node(void) } } -static int get_lcd_power(void) -{ - if (display_dev && display_dev->get_state) - return get_lcd_power_node(); - else - return dpms_get_state(); -} - bool display_dimstay_check(void) { if (get_pm_status_flag() & DIM_FLAG) @@ -357,7 +349,7 @@ static int backlight_standby(int force) { int ret = -1; - if ((get_lcd_power() == DPMS_ON) || force) { + if ((dpms_get_cached_state() == DPMS_ON) || force) { _I("LCD standby"); ret = bl_onoff(DPMS_STANDBY, 0); } @@ -740,8 +732,8 @@ static struct _backlight_ops backlight_ops = { .standby = backlight_standby, .set_default_brt = set_default_brt, .get_default_brt = get_default_brt, - .get_lcd_power = get_lcd_power, - .get_lcd_power_cached = dpms_get_cached_state, + .get_lcd_power = dpms_get_cached_state, + .get_lcd_power_node = get_lcd_power_node, .set_custom_status = set_custom_status, .get_custom_status = get_custom_status, .save_custom_brightness = save_custom_brightness, diff --git a/plugins/wearable/display/device-interface.c b/plugins/wearable/display/device-interface.c index d2ee406..655a102 100644 --- a/plugins/wearable/display/device-interface.c +++ b/plugins/wearable/display/device-interface.c @@ -167,14 +167,6 @@ static int get_lcd_power_node(void) } } -static int get_lcd_power(void) -{ - if (display_dev && display_dev->get_state) - return get_lcd_power_node(); - else - return dpms_get_state(); -} - bool display_dimstay_check(void) { if (get_pm_status_flag() & DIM_FLAG) @@ -368,7 +360,7 @@ static int backlight_standby(int force) { int ret = -1; - if ((get_lcd_power() == DPMS_ON) || force) { + if ((dpms_get_cached_state() == DPMS_ON) || force) { _I("LCD standby"); ret = bl_onoff(DPMS_STANDBY, 0); } @@ -805,8 +797,8 @@ static struct _backlight_ops backlight_ops = { .standby = backlight_standby, .set_default_brt = set_default_brt, .get_default_brt = get_default_brt, - .get_lcd_power = get_lcd_power, - .get_lcd_power_cached = dpms_get_cached_state, + .get_lcd_power = dpms_get_cached_state, + .get_lcd_power_node = get_lcd_power_node, .set_custom_status = set_custom_status, .get_custom_status = get_custom_status, .save_custom_brightness = save_custom_brightness, diff --git a/src/display/device-interface.h b/src/display/device-interface.h index 4193de8..161c528 100644 --- a/src/display/device-interface.h +++ b/src/display/device-interface.h @@ -69,7 +69,7 @@ struct _backlight_ops { int (*set_default_brt)(int level); int (*get_default_brt)(void); int (*get_lcd_power)(void); - int (*get_lcd_power_cached)(void); + int (*get_lcd_power_node)(void); int (*set_custom_status)(bool on); bool (*get_custom_status)(void); int (*save_custom_brightness)(void); diff --git a/src/touchscreen/touchscreen.c b/src/touchscreen/touchscreen.c index b2c8182..5ec95d1 100644 --- a/src/touchscreen/touchscreen.c +++ b/src/touchscreen/touchscreen.c @@ -193,9 +193,6 @@ static int touchscreen_start(enum device_flags flags) if (touchscreen_enable != DEVICE_OPS_STATUS_START) return 0; - if (!backlight_ops || !backlight_ops->get_lcd_power) - return -ENOTSUP; - /* Do not enable touchscreen during silent boot mode */ if (silent_boot && !booting_done(NULL)) return -ENOTSUP; @@ -206,8 +203,8 @@ static int touchscreen_start(enum device_flags flags) ret = touchscreen_set_state(TOUCHSCREEN_ON); state = -1; - if (backlight_ops && backlight_ops->get_lcd_power_cached) - state = backlight_ops->get_lcd_power_cached(); + if (backlight_ops && backlight_ops->get_lcd_power) + state = backlight_ops->get_lcd_power(); if (state == DPMS_OFF) touchscreen_powersaving(POWERSAVING_ON); -- 2.7.4 From 1adb706ea7a06ac1eb879324442d6d498555a9f7 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 14 Sep 2020 11:49:48 +0900 Subject: [PATCH 03/16] Use definitions of libsyscommon instead of device api device api now uses libsyscommon library for dbus communication. To get in line with this change, Deviced is required to use the callback function of libsyscommon instead of that of api/device. Change-Id: I5c8f8025ba215ec2fb9a6722ee66ca4b2d8fbea2 Signed-off-by: Youngjae Cho --- src/auto-test/display.c | 2 +- src/auto-test/test.c | 2 +- src/auto-test/test.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auto-test/display.c b/src/auto-test/display.c index 0b92d84..df4631e 100644 --- a/src/auto-test/display.c +++ b/src/auto-test/display.c @@ -398,7 +398,7 @@ static bool set_display_brightness_state(display_state_e state, int brightness) return TRUE; } -static bool set_display_state_by_reason(display_state_e type, const char *reason, int timeout, device_dbus_pending_cb cb) +static bool set_display_state_by_reason(display_state_e type, const char *reason, int timeout, dbus_pending_cb cb) { int ret; diff --git a/src/auto-test/test.c b/src/auto-test/test.c index 6039944..0deda46 100644 --- a/src/auto-test/test.c +++ b/src/auto-test/test.c @@ -82,7 +82,7 @@ void test_exit(void *data) } } -void __cb(void *data, GVariant *result, GError *err) +void __cb(GVariant *result, void *data, GError *err) { int temp = 0; diff --git a/src/auto-test/test.h b/src/auto-test/test.h index 65dbd44..848a646 100644 --- a/src/auto-test/test.h +++ b/src/auto-test/test.h @@ -105,7 +105,7 @@ void remove_test(const struct test_ops *c); const struct test_ops *find_test(const char *name); void config_test(); void _R(const char *format, ...); -void __cb(void *data, GVariant *result, GError *err); +void __cb(GVariant *result, void *data, GError *err); bool capi_result(const char *method, int val); bool capi_reboot_result(const char *method, int val); #endif -- 2.7.4 From dbdb329932fd9c3ea7af71d09e1ead093789a1dc Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Tue, 13 Oct 2020 16:02:06 +0900 Subject: [PATCH 04/16] Skip running animation if option is silent Change-Id: Iaccd10955d02a129ad352b0a13192ed47042ffa9 Signed-off-by: lokilee73 (cherry picked from commit ca9d81149e324e49efc033810b25ce787f7c4c00) --- conf/power.conf | 1 + src/power/power-handler.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/conf/power.conf b/conf/power.conf index e99b94d..7a753c2 100644 --- a/conf/power.conf +++ b/conf/power.conf @@ -3,3 +3,4 @@ Option=recovery Option=download Option=wdownload Option=debug +Option=silent diff --git a/src/power/power-handler.c b/src/power/power-handler.c index 0a672c7..342868e 100644 --- a/src/power/power-handler.c +++ b/src/power/power-handler.c @@ -502,7 +502,11 @@ static int power_execute_pid(const char *typename, const char *option) system_shutdown_send_system_event(); poweroff_send_broadcast(poweroff_opt.type); - poweroff_start_animation(); + /* Skip running animation if option is silent */ + if (poweroff_opt.option != NULL && !strcmp(poweroff_opt.option, "silent")) + _D("Skip running poweroff animation."); + else + poweroff_start_animation(); /* Spare time for AddPowerOffWait requests */ g_timeout_add_seconds(1, poweroff_start_timers, NULL); -- 2.7.4 From 3f5cfc102de3e2f39bf8003999023cd4447ee0c8 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 26 Oct 2020 15:10:10 +0900 Subject: [PATCH 05/16] Fix restart option to on-failure This prevents restarting deviced when the deviced is returning main() through poweroff sequence. Change-Id: Icbb4a8c306721a1613c04d41060fbbd323c5e62b Signed-off-by: Youngjae Cho --- systemd/deviced.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemd/deviced.service b/systemd/deviced.service index 0f07bff..817c32d 100644 --- a/systemd/deviced.service +++ b/systemd/deviced.service @@ -11,7 +11,7 @@ Type=notify SmackProcessLabel=System::Privileged Environment=XDG_RUNTIME_DIR=/run ExecStart=/usr/bin/deviced -Restart=always +Restart=on-failure RestartSec=0 KillSignal=SIGUSR1 -- 2.7.4 From 70fb77b91baa00fa154071334f1fc699c05edc72 Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Tue, 27 Oct 2020 11:29:56 +0900 Subject: [PATCH 06/16] Add comments for DEVICE_NOTIFIER_POWEROFF Change-Id: If4f2dbcbc66a6579612016b16207339bfe14a37b Signed-off-by: lokilee73 --- src/power/power-handler.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/power/power-handler.c b/src/power/power-handler.c index 342868e..8b6684f 100644 --- a/src/power/power-handler.c +++ b/src/power/power-handler.c @@ -251,6 +251,19 @@ void poweroff_prepare(void) disable_display(); + /* Below functions follow after notifying DEVICE_NOTIFIER_POWEROFF + 1. pmlock + - pmlock_detector_poweroff_cb() + - cleanup_pmlock_statistics() + - do_copy_force() + - save_display_log() + 2. tzip + - tzip_poweroff() + - tzip_server_exit() + 3. udev + - device_change_poweroff() + - uevent_control_stop() + */ device_notify(DEVICE_NOTIFIER_POWEROFF, &off); } -- 2.7.4 From 8768b01a896da204957a86071cc07b3494476297 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 27 Oct 2020 15:05:03 +0900 Subject: [PATCH 07/16] Rearrange PWROFF_FLAG flag setting Set PWROFF_FLAG when the poweroff enters POWEROFF_TRIGGERED stage. Change-Id: I4129f654792e6ad090774cbc46e0f5a64692e64a Signed-off-by: Youngjae Cho --- plugins/iot/display/key-filter.c | 1 - plugins/mobile/display/key-filter.c | 1 - plugins/tv/display/key-filter.c | 1 - plugins/wearable/display/key-filter.c | 1 - src/power/power-handler.c | 5 ++--- 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/plugins/iot/display/key-filter.c b/plugins/iot/display/key-filter.c index 11821a6..bc9d0dd 100644 --- a/plugins/iot/display/key-filter.c +++ b/plugins/iot/display/key-filter.c @@ -122,7 +122,6 @@ static void pwroff_popup(void) { int ret; - clear_pm_status_flag(PWROFF_FLAG); ret = launch_system_app(APP_POWERKEY, 2, APP_KEY_TYPE, APP_POWERKEY); if (ret < 0) _E("Failed to launch power off popup."); diff --git a/plugins/mobile/display/key-filter.c b/plugins/mobile/display/key-filter.c index 7998b16..7a57a98 100644 --- a/plugins/mobile/display/key-filter.c +++ b/plugins/mobile/display/key-filter.c @@ -138,7 +138,6 @@ static void longkey_pressed(void) _D("No poweroff capability!"); return; } - clear_pm_status_flag(PWROFF_FLAG); } static gboolean longkey_restore_cb(void *data) diff --git a/plugins/tv/display/key-filter.c b/plugins/tv/display/key-filter.c index b28d7ec..68fcf78 100644 --- a/plugins/tv/display/key-filter.c +++ b/plugins/tv/display/key-filter.c @@ -122,7 +122,6 @@ static void pwroff_popup(void) { int ret; - clear_pm_status_flag(PWROFF_FLAG); ret = launch_system_app(APP_POWERKEY, 2, APP_KEY_TYPE, APP_POWERKEY); if (ret < 0) _E("Failed to launch power off popup."); diff --git a/plugins/wearable/display/key-filter.c b/plugins/wearable/display/key-filter.c index 32691f8..cdea506 100644 --- a/plugins/wearable/display/key-filter.c +++ b/plugins/wearable/display/key-filter.c @@ -138,7 +138,6 @@ static void longkey_pressed(void) _D("No poweroff capability!"); return; } - clear_pm_status_flag(PWROFF_FLAG); } static gboolean longkey_restore_cb(void *data) diff --git a/src/power/power-handler.c b/src/power/power-handler.c index 8b6684f..693c4a4 100644 --- a/src/power/power-handler.c +++ b/src/power/power-handler.c @@ -356,9 +356,6 @@ static gboolean poweroff_wait_timeout_cb(void *data) poweroff_prepare(); poweroff_request_shutdown(); - - if (disp_plgn->update_pm_setting) - disp_plgn->update_pm_setting(SETTING_POWEROFF, poweroff_opt.type); } else { _D("Poweroff wait timer for pid %d is expired, but keep waiting for others...", pid); } @@ -510,6 +507,8 @@ static int power_execute_pid(const char *typename, const char *option) _E("Failed to set vconf value for power off status: %d", vconf_get_ext_errno()); poweroff_stage = POWEROFF_TRIGGERED; + if (disp_plgn->update_pm_setting) + disp_plgn->update_pm_setting(SETTING_POWEROFF, poweroff_opt.type); /* Poweroff event broadcasting */ system_shutdown_send_system_event(); -- 2.7.4 From c493cc911313bad8af96bd11776d153a39eadc90 Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Thu, 29 Oct 2020 17:24:40 +0900 Subject: [PATCH 08/16] Fix wrong condition for halt halt and poweroff are different command. exit is the same as halt. So, change condition. Change-Id: I837260224d8fe10907f89f435774c8c7d4e46758 Signed-off-by: lokilee73 --- src/power-shutdown/shutdown.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/power-shutdown/shutdown.c b/src/power-shutdown/shutdown.c index e1a5d33..7934d9f 100644 --- a/src/power-shutdown/shutdown.c +++ b/src/power-shutdown/shutdown.c @@ -146,9 +146,9 @@ int main(int ac, char *av[]) if (strcmp(cmd_name, "reboot") == 0) cmd = CMD_REBOOT; - else if (strcmp(cmd_name, "halt") == 0 || strcmp(cmd_name, "poweroff") == 0) + else if (strcmp(cmd_name, "poweroff") == 0) cmd = CMD_POWEROFF; - else if (strcmp(cmd_name, "exit") == 0) + else if (strcmp(cmd_name, "exit") == 0 || strcmp(cmd_name, "halt") == 0) cmd = CMD_EXIT; else // XXX this is critical failure - we are pid1 already -- 2.7.4 From a25eb5e44fd394887658026c4916e8909e286932 Mon Sep 17 00:00:00 2001 From: Mateusz Majewski Date: Thu, 17 Sep 2020 13:24:07 +0200 Subject: [PATCH 09/16] Implement shutdown et al. using deviced DBus interface Change-Id: Idf7cd364bedf7dfcd7024ece67b360745343b984 Co-authored-by: Michal Bloch --- CMakeLists.txt | 5 + packaging/deviced.spec | 19 +++ src/power-command/command.c | 363 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 387 insertions(+) create mode 100644 src/power-command/command.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 45d8cab..8d00ac6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -247,6 +247,11 @@ IF(POWER_MODULE STREQUAL on) SET(deviced-shutdown_LDFLAGS ${pkgs_LDFLAGS}) TARGET_LINK_LIBRARIES(deviced-shutdown ${pkgs_LDFLAGS} "-lrt -ldl -lm" shared) INSTALL(TARGETS deviced-shutdown DESTINATION /usr/lib/systemd) + + ADD_EXECUTABLE(deviced-power-command src/power-command/command.c) + SET(deviced-power-command_LDFLAGS ${pkgs_LDFLAGS}) + TARGET_LINK_LIBRARIES(deviced-power-command ${pkgs_LDFLAGS} "-lrt -ldl -lm" shared) + INSTALL(TARGETS deviced-power-command DESTINATION /usr/sbin) ENDIF() INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/src/deviced/ DESTINATION include/${PROJECT_NAME} diff --git a/packaging/deviced.spec b/packaging/deviced.spec index f23b4da..f27ae50 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -186,9 +186,19 @@ rm -rf %{buildroot} mkdir -p %{buildroot}%{TZ_SYS_DUMPGEN} install -m 775 scripts/dump_pmstate_log.sh %{buildroot}%{TZ_SYS_DUMPGEN}/dump_pmstate_log.sh +# Assume power module is on (-DPOWER_MODULE=on) +touch %{buildroot}%{_sbindir}/reboot +touch %{buildroot}%{_sbindir}/halt +touch %{buildroot}%{_sbindir}/poweroff +touch %{buildroot}%{_sbindir}/shutdown + %post # Assume power module is on (-DPOWER_MODULE=on) update-alternatives --install %{_prefix}/lib/systemd/systemd-shutdown systemd-shutdown %{_prefix}/lib/systemd/deviced-shutdown 500 +update-alternatives --install %{_sbindir}/reboot reboot %{_sbindir}/deviced-power-command 500 +update-alternatives --install %{_sbindir}/halt halt %{_sbindir}/deviced-power-command 500 +update-alternatives --install %{_sbindir}/poweroff poweroff %{_sbindir}/deviced-power-command 500 +update-alternatives --install %{_sbindir}/shutdown shutdown %{_sbindir}/deviced-power-command 500 #memory type vconf key init users_gid=$(getent group %{TZ_SYS_USER_GROUP} | cut -f3 -d':') @@ -201,6 +211,10 @@ fi %preun # Assume power module is on (-DPOWER_MODULE=on) update-alternatives --remove systemd-shutdown %{_prefix}/lib/systemd/deviced-shutdown +update-alternatives --remove reboot %{_sbindir}/deviced-power-command +update-alternatives --remove halt %{_sbindir}/deviced-power-command +update-alternatives --remove poweroff %{_sbindir}/deviced-power-command +update-alternatives --remove shutdown %{_sbindir}/deviced-power-command %postun systemctl daemon-reload @@ -264,6 +278,11 @@ mv %{_libdir}/iot-display.so %{_libdir}/deviced/display.so # Assume power module is on (-DPOWER_MODULE=on) %{_prefix}/lib/systemd/deviced-shutdown +%{_sbindir}/deviced-power-command +%ghost %{_sbindir}/reboot +%ghost %{_sbindir}/halt +%ghost %{_sbindir}/poweroff +%ghost %{_sbindir}/shutdown %files -n libdeviced %manifest deviced.manifest diff --git a/src/power-command/command.c b/src/power-command/command.c new file mode 100644 index 0000000..629a1fc --- /dev/null +++ b/src/power-command/command.c @@ -0,0 +1,363 @@ +/* + * deviced + * + * Copyright (c) 2020 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +enum application { + APP_UNKNOWN, + APP_SHUTDOWN, + APP_REBOOT, + APP_HALT, + APP_POWEROFF, +}; + +struct { + const char *name; + enum application application; +} apps[] = { + { .name = "reboot", .application = APP_REBOOT, }, + { .name = "halt", .application = APP_HALT, }, + { .name = "poweroff", .application = APP_POWEROFF, }, + { .name = "shutdown", .application = APP_SHUTDOWN, }, +}; + +enum application parse_path(const char *name) +{ + const char *base = strrchr(name, '/'); + base = base ? base + 1 : name; + for (size_t i = 0; i < ARRAY_SIZE(apps); ++i) { + const char *target = apps[i].name; + + /* NB: We only check if the prefix matches, + * so that we can run "reboot" as, for example "reboot-custom". */ + if (strncmp(base, target, strlen(target)) == 0) + return apps[i].application; + } + return APP_UNKNOWN; +} + +/* NB: we are emulating different programs: the "shutdown" program, and the trio of "reboot", "halt" + * and "poweroff". These two cases have different option sets, so they need separate parsing methods + * and separate usage strings. */ + +struct parse_result { + enum { + DO_NOTHING, + SHOW_SHUTDOWN_PARSE_ERROR, + SHOW_REBOOT_ET_AL_PARSE_ERROR, + SHOW_SHUTDOWN_HELP, + SHOW_REBOOT_ET_AL_HELP, + DO_POWEROFF, + DO_EXIT, + DO_REBOOT, + } operation; + + const char *extra_option; + + bool show_sync_warning; + bool show_timings_warning; + bool show_wall_warning; + bool show_wtmp_warning; +}; + +struct parse_result parse_shutdown(int argc, char **argv) { + enum { + ACT_HALT, + ACT_REBOOT, + ACT_POWEROFF, + } action = ACT_POWEROFF; + bool will_do_nothing = false; + bool show_timings_warning = false; + bool show_wall_warning = false; + + for (;;) { + switch (getopt_long(argc, argv, "HPrhkc", (struct option []) { + { "help", no_argument, NULL, 0, }, + { "no-wall", no_argument, NULL, 1, }, + { "halt", no_argument, NULL, 'H', }, + { "poweroff", no_argument, NULL, 'P', }, + { "reboot", no_argument, NULL, 'r', }, + { NULL, 0, NULL, 0, }, + }, NULL)) { + case -1: + switch (argc - optind) { + case 2: + show_wall_warning = true; + show_timings_warning = true; + break; + + case 1: + show_timings_warning = true; + break; + + case 0: + break; + + default: + return (struct parse_result) { .operation = SHOW_SHUTDOWN_PARSE_ERROR, }; + } + + return (struct parse_result) { + .operation = will_do_nothing ? DO_NOTHING + : action == ACT_REBOOT ? DO_REBOOT + : action == ACT_HALT ? DO_EXIT // don't ask difficult questions like "why not DO_HALT" + : DO_POWEROFF, + .extra_option = NULL, + .show_sync_warning = false, + .show_timings_warning = show_timings_warning, + .show_wall_warning = show_wall_warning, + .show_wtmp_warning = false, + }; + + case 0: + return (struct parse_result) { .operation = SHOW_SHUTDOWN_HELP, }; + + case 1: + show_wall_warning = true; + break; + + case 'H': + action = ACT_HALT; + break; + + case 'P': + action = ACT_POWEROFF; + break; + + case 'r': + action = ACT_REBOOT; + break; + + case 'h': + if (action == ACT_REBOOT) + action = ACT_POWEROFF; + break; + + case 'k': + will_do_nothing = true; + show_wall_warning = true; + break; + + case 'c': + will_do_nothing = true; + show_timings_warning = true; + break; + + case '?': + return (struct parse_result) { .operation = SHOW_SHUTDOWN_PARSE_ERROR, }; + + default: + assert(false); + } + } +} + +struct parse_result parse_reboot_et_al(enum application application, int argc, char **argv) { + enum { + ACT_HALT, + ACT_REBOOT, + ACT_POWEROFF, + } action; + switch (application) { + case APP_REBOOT: + action = ACT_REBOOT; + break; + + case APP_HALT: + action = ACT_HALT; + break; + + case APP_POWEROFF: + action = ACT_POWEROFF; + break; + + default: + assert(false); + } + + bool will_do_nothing = false; + bool show_sync_warning = false; + bool show_timings_warning = false; + bool show_wall_warning = false; + bool show_wtmp_warning = false; + char *extra_option = NULL; + + for (;;) { + switch (getopt_long(argc, argv, "-pfwdn", (struct option []) { + { "help", no_argument, NULL, 0, }, + /* 1 reserved for options not in -foo format */ + { "halt", no_argument, NULL, 2, }, + { "reboot", no_argument, NULL, 3, }, + { "no-wall", no_argument, NULL, 4, }, + { "poweroff", no_argument, NULL, 'p', }, + { "force", no_argument, NULL, 'f', }, + { "wtmp-only", no_argument, NULL, 'w', }, + { "no-wtmp", no_argument, NULL, 'd', }, + { "no-sync", no_argument, NULL, 'n', }, + { NULL, 0, NULL, 0, }, + }, NULL)) { + case -1: + if (optind != argc) + return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_PARSE_ERROR, }; + + return (struct parse_result) { + .operation = will_do_nothing ? DO_NOTHING + : action == ACT_REBOOT ? DO_REBOOT + : action == ACT_HALT ? DO_EXIT + : DO_POWEROFF, + .extra_option = extra_option, + .show_sync_warning = show_sync_warning, + .show_timings_warning = show_timings_warning, + .show_wall_warning = show_wall_warning, + .show_wtmp_warning = show_wtmp_warning, + }; + + case 0: + return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_HELP, }; + + case 1: + if (extra_option) + return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_PARSE_ERROR, }; + extra_option = optarg; + break; + + case 2: + action = ACT_HALT; + break; + + case 3: + action = ACT_REBOOT; + break; + + case 4: + show_wall_warning = true; + break; + + case 'p': + action = ACT_POWEROFF; + break; + + case 'f': + show_timings_warning = false; + break; + + case 'w': + will_do_nothing = true; + show_wtmp_warning = true; + break; + + case 'd': + show_wtmp_warning = true; + break; + + case 'n': + show_sync_warning = true; + break; + + case '?': + return (struct parse_result) { .operation = SHOW_REBOOT_ET_AL_PARSE_ERROR, }; + + default: + assert(false); + } + } +} + +int call_deviced_poweroff(const char *type, const char *extra_option, const char *message) +{ + const char *command[2] = { type, extra_option }; + int ret = extra_option + ? dbus_handle_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF, "PowerOffWithOption", "ss", command) + : dbus_handle_method_sync(DEVICED_BUS_NAME, DEVICED_PATH_POWEROFF, DEVICED_INTERFACE_POWEROFF, "PowerOff", "s", command) + ; + if (ret != 0) { + errno = -ret; + fprintf(stderr, "Error: %m"); + return EXIT_FAILURE; + } + + fprintf(stderr, "%s", message); + for (;;) + pause(); + return EXIT_SUCCESS; +} + +int main(int argc, char **argv) +{ + enum application application = parse_path(argv[0]); + struct parse_result parse_result; + switch (application) { + case APP_UNKNOWN: + fprintf(stderr, "This program can only be used as a symlink to 'reboot', 'halt', 'poweroff' or 'shutdown'.\n"); + return EXIT_FAILURE; + + case APP_SHUTDOWN: + parse_result = parse_shutdown(argc, argv); + break; + + case APP_REBOOT: + case APP_HALT: + case APP_POWEROFF: + parse_result = parse_reboot_et_al(application, argc, argv); + break; + + default: + // This shouldn't be needed, but GCC complains otherwise. + assert(false); + return EXIT_FAILURE; + } + + if (parse_result.show_sync_warning) + fprintf(stderr, "Warning: Tizen always syncs, sync options ignored.\n"); + if (parse_result.show_timings_warning) + fprintf(stderr, "Warning: %s doesn't take care of delayed and pending operations on Tizen.\n", argv[0]); + if (parse_result.show_wall_warning) + fprintf(stderr, "Warning: %s doesn't take care of wall messages on Tizen.\n", argv[0]); + if (parse_result.show_wtmp_warning) + fprintf(stderr, "Warning: %s doesn't take care of wtmp entries on Tizen.\n", argv[0]); + + switch (parse_result.operation) { + case DO_NOTHING: + return EXIT_SUCCESS; + + case SHOW_SHUTDOWN_HELP: + case SHOW_SHUTDOWN_PARSE_ERROR: + fprintf(stderr, "Usage: %s [-HPrh]\n", argv[0]); + return parse_result.operation == SHOW_SHUTDOWN_HELP ? EXIT_SUCCESS : EXIT_FAILURE; + + case SHOW_REBOOT_ET_AL_HELP: + case SHOW_REBOOT_ET_AL_PARSE_ERROR: + fprintf(stderr, "Usage: %s [-p] [--halt|--poweroff|--reboot] [extra]\n", argv[0]); // FIXME: do we say something about the extras? if yes, do we mention deviced, the configs etc? + return parse_result.operation == SHOW_REBOOT_ET_AL_HELP ? EXIT_SUCCESS : EXIT_FAILURE; + + case DO_POWEROFF: + return call_deviced_poweroff("poweroff", parse_result.extra_option, "Shutting down...\n"); // should be "Powering off" really, "shutting down" is the generic term also encompassing halt/reboot >_> + case DO_EXIT: + return call_deviced_poweroff("exit", parse_result.extra_option, "Shutting down...\n"); // ditto: exit ultimately boils down to poweroff, too + case DO_REBOOT: + return call_deviced_poweroff("reboot", parse_result.extra_option, "Rebooting...\n"); + } + + assert(false); // unreachable + return EXIT_FAILURE; +} -- 2.7.4 From e44eeff203cfb8f8b3dab212388f1c15523374a8 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Mon, 26 Oct 2020 15:33:52 +0100 Subject: [PATCH 10/16] packaging: Align alternatives setup with fedora-recommended scheme Change-Id: I707e0a565322a97c23ce19ec3f5e9dd6aa7b5e8a --- packaging/deviced.spec | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/packaging/deviced.spec b/packaging/deviced.spec index f27ae50..db438a9 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -204,22 +204,21 @@ update-alternatives --install %{_sbindir}/shutdown shutdown %{_sbindir}/deviced- users_gid=$(getent group %{TZ_SYS_USER_GROUP} | cut -f3 -d':') systemctl daemon-reload -if [ "$1" == "1" ]; then +if [ $1 -eq 1 ]; then systemctl restart deviced.service fi -%preun -# Assume power module is on (-DPOWER_MODULE=on) -update-alternatives --remove systemd-shutdown %{_prefix}/lib/systemd/deviced-shutdown -update-alternatives --remove reboot %{_sbindir}/deviced-power-command -update-alternatives --remove halt %{_sbindir}/deviced-power-command -update-alternatives --remove poweroff %{_sbindir}/deviced-power-command -update-alternatives --remove shutdown %{_sbindir}/deviced-power-command - %postun -systemctl daemon-reload -if [ "$1" == "0" ]; then - systemctl stop deviced.service +# Assume power module is on (-DPOWER_MODULE=on) +if [ $1 -eq 0 ] ; then + update-alternatives --remove systemd-shutdown %{_prefix}/lib/systemd/deviced-shutdown + update-alternatives --remove reboot %{_sbindir}/deviced-power-command + update-alternatives --remove halt %{_sbindir}/deviced-power-command + update-alternatives --remove poweroff %{_sbindir}/deviced-power-command + update-alternatives --remove shutdown %{_sbindir}/deviced-power-command + + systemctl daemon-reload + systemctl stop deviced.service fi %post -n libdeviced -p /sbin/ldconfig -- 2.7.4 From b05672efde824ad4037f829b1b27eea19471c5c2 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 23 Oct 2020 13:08:28 +0200 Subject: [PATCH 11/16] power: Print warning when `exit' is requested Change-Id: If73feb43cc7c4322fc8aa9d53c8397e2d76ca3d3 --- src/power-shutdown/shutdown.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/power-shutdown/shutdown.c b/src/power-shutdown/shutdown.c index 7934d9f..010ac0b 100644 --- a/src/power-shutdown/shutdown.c +++ b/src/power-shutdown/shutdown.c @@ -97,15 +97,18 @@ static void autoboot(void) static void handle_exit(void) { - /* systemd default behviour for handling exit in system manager - * is to treat is as poweroff. Exiting from PID1 would cause - * system to panic, so it's not really "supported. Poweroff is - * sane default, but it's also implementation detail and something - * user should depend on. + /* systemd default behviour for handling exit in system + * manager is to treat is as poweroff. Exiting from PID1 + * would cause system to panic, so exitting is not really + * "supported. Poweroff is the default in systemd-shutdown. + * However, it's implementation detail sane default, but it's + * also implementation detail and something users should + * better not depend on. * * In Tizen we put shutdown binary to sleep, rather than powering * it off. This functionaliy has been requested by test team. */ + printf("%s: `exit' action requested - not doing final shutdown, sleeping. Non-standard behaviour requested by test team.\n" , progname); for (;;) pause(); } -- 2.7.4 From 7952f9f960397d8d0f8965a0cb517505b7f6e2c3 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 9 Nov 2020 15:48:21 +0900 Subject: [PATCH 12/16] Add bitmap functions Change-Id: I8c39533fa77e6830881062b525b72eec3386342e Signed-off-by: Youngjae Cho --- CMakeLists.txt | 1 + src/core/bitmap.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/bitmap.h | 60 +++++++++++++++++++++ src/core/common.h | 24 ++++++--- src/extcon/hdmi.c | 44 +++++++++++----- 5 files changed, 261 insertions(+), 20 deletions(-) create mode 100644 src/core/bitmap.c create mode 100644 src/core/bitmap.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d00ac6..6bfcc69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,7 @@ SET(SRCS src/core/main.c src/core/sig-handler.c src/core/udev.c + src/core/bitmap.c src/proc/cpu-info.c src/time/time-handler.c ) diff --git a/src/core/bitmap.c b/src/core/bitmap.c new file mode 100644 index 0000000..d528188 --- /dev/null +++ b/src/core/bitmap.c @@ -0,0 +1,152 @@ +/* + * deviced + * + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "bitmap.h" +#include "log.h" + +static void bitmap_alloc_size(struct dd_bitmap *bm, unsigned int nbits) +{ + unsigned int bytes = ROUNDUP_BITS_TO_LONGS(nbits) * BYTES_PER_LONG; + + bytes += BITMAP_MARGIN; + + bm->b = (unsigned long *) malloc(bytes); + if (!bm->b) + return; + + bm->size = nbits; +} + +void set_all_bits(struct dd_bitmap *bm) +{ + unsigned long complete_longs = bm->size / BITS_PER_LONG; + unsigned long complete_bytes = complete_longs * BYTES_PER_LONG; + unsigned long residue_bits = bm->size % BITS_PER_LONG; + + /* set all bits of the long element except the last long element */ + memset(bm->b, ~0, complete_bytes); + + /* set residue bits in the last long element */ + if (residue_bits) + bm->b[complete_longs] = (1UL << residue_bits) - 1; +} + +void clear_all_bits(struct dd_bitmap *bm) +{ + unsigned int bytes = ROUNDUP_BITS_TO_LONGS(bm->size) * BYTES_PER_LONG; + memset(bm->b, 0, bytes); +} + +void set_bit(struct dd_bitmap *bm, unsigned long nr) +{ + if (!bm) + return; + + if (nr >= bm->size) { + _E("Requested nr=%lu exceeds max bit=%lu", nr, bm->size - 1); + return; + } + + bm->b[BIT_WORD(nr)] |= BIT_MASK(nr); +} + +void clear_bit(struct dd_bitmap *bm, unsigned long nr) +{ + if (!bm) + return; + + if (nr >= bm->size) { + _E("Requested nr=%lu exceeds max bit=%lu", nr, bm->size - 1); + return; + } + + bm->b[BIT_WORD(nr)] &= ~BIT_MASK(nr); +} + +bool test_bit(struct dd_bitmap *bm, unsigned long nr) +{ + if (!bm) + return false; + + if (nr >= bm->size) { + _E("Requested nr=%lu exceeds max bit=%lu", nr, bm->size - 1); + return false; + } + + return bm->b[BIT_WORD(nr)] & BIT_MASK(nr); +} + +int count_set_bit(struct dd_bitmap *bm) +{ + int i; + int count = 0; + + if (!bm) + return -1; + + for (i = 0; i < ROUNDUP_BITS_TO_LONGS(bm->size); ++i) + count += __builtin_popcountl(bm->b[i]); + + return count; +} + +int count_unset_bit(struct dd_bitmap *bm) +{ + if (!bm) + return -1; + + return bm->size - count_set_bit(bm); +} + +struct dd_bitmap* init_bitmap(unsigned int nbits) +{ + struct dd_bitmap *bm = NULL; + + if (nbits == 0) + return NULL; + + bm = (struct dd_bitmap *) malloc(sizeof(struct dd_bitmap)); + if (!bm) + return NULL; + + bm->b = NULL; + bm->size = 0; + + bitmap_alloc_size(bm, nbits); + if (!bm->b) { + free(bm); + return NULL; + } + + clear_all_bits(bm); + bm->size = nbits; + + return bm; +} + +void deinit_bitmap(struct dd_bitmap *bm) +{ + if (!bm) + return; + + free(bm->b); + free(bm); +} diff --git a/src/core/bitmap.h b/src/core/bitmap.h new file mode 100644 index 0000000..6135b7c --- /dev/null +++ b/src/core/bitmap.h @@ -0,0 +1,60 @@ +/* + * deviced + * + * Copyright (c) 2020 - 2021 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DD_BITMAP_H__ +#define __DD_BITMAP_H__ + +#include + +#include "common.h" + +/* Align bits by size of long, and convert it to long, + * for example, if long is 64bit then, + * ROUNDUP_BITS_TO_LONGS(0) -> 0 + * ROUNDUP_BITS_TO_LONGS(1) -> 1 + * ROUNDUP_BITS_TO_LONGS(64) -> 1 + * ROUNDUP_BITS_TO_LONGS(65) -> 2 + * ROUNDUP_BITS_TO_LONGS(128) -> 2 + * ROUNDUP_BITS_TO_LONGS(129) -> 3 + * ... */ +#define ROUNDUP_BITS_TO_LONGS(nbits) (roundup(nbits, BITS_PER_LONG) / BITS_PER_LONG) + +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BITMAP_MARGIN (BYTES_PER_LONG * 2) /* trailing margin for safety, bytes */ + +struct dd_bitmap { + /* bitmap */ + unsigned long *b; + + /* number of bits, not the maximum bit. + * maximum bit is size - 1 */ + unsigned long size; +}; + +void set_bit(struct dd_bitmap *bm, unsigned long nr); +void clear_bit(struct dd_bitmap *bm, unsigned long nr); +bool test_bit(struct dd_bitmap *bm, unsigned long nr); +void set_all_bits(struct dd_bitmap *bm); +void clear_all_bits(struct dd_bitmap *bm); +int count_set_bit(struct dd_bitmap *bm); +int count_unset_bit(struct dd_bitmap *bm); +struct dd_bitmap* init_bitmap(unsigned int nbits); +void deinit_bitmap(struct dd_bitmap *bm); + +#endif diff --git a/src/core/common.h b/src/core/common.h index b49e52b..04597ff 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -27,13 +27,12 @@ #include #include -#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) -#define BITS_PER_LONG (sizeof(long) * 8) -#define BITS_PER_CHAR (sizeof(char) * 8) -#define OFFSET(x) ((x) & (BITS_PER_LONG - 1)) -#define BIT(x) (1UL << OFFSET(x)) -#define LONG(x) ((x) / BITS_PER_LONG) -#define test_bit(bit, array) ((array[LONG(bit)] >> OFFSET(bit)) & 1) +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) +#define BYTES_PER_LONG (sizeof(unsigned long)) +#define BITS_PER_LONG (BYTES_PER_LONG * 8) +#define OFFSET(x) ((x) & (BITS_PER_LONG - 1)) +#define BIT(x) (1UL << OFFSET(x)) +#define LONG(x) ((x) / BITS_PER_LONG) /* * One byte digit has 3 position in decimal representation @@ -91,6 +90,17 @@ }) #endif +/* Round up x to a multiple of y. + * y must be a power of 2, if not, use roundup() */ +#ifndef round_up +#define round_up(x, y) ((((x) - 1 ) | (typeof(x))((y) - 1)) + 1) +#endif + +/* Round up n to a multiple of d. */ +#ifndef roundup +#define roundup(n, d) ((((n) + (d) - 1) / (d)) * (d)) +#endif + #ifndef SEC_TO_MSEC #define SEC_TO_MSEC(x) ((x)*1000) #endif diff --git a/src/extcon/hdmi.c b/src/extcon/hdmi.c index c2cc3af..15a3cf9 100644 --- a/src/extcon/hdmi.c +++ b/src/extcon/hdmi.c @@ -21,6 +21,7 @@ #include #include "core/log.h" #include "core/list.h" +#include "core/bitmap.h" #include "core/device-notifier.h" #include "display/core.h" #include "display/display-ops.h" @@ -31,15 +32,8 @@ #define SIGNAL_HDMI_STATE "ChangedHDMI" #define HDMI_NUMBER_MAX (64) // max number of supported hdmi -#define HDMI_BITMAP_T (sizeof(hdmi_bitmap_t) * BITS_PER_CHAR) // size of hdmi_bitmap_t -/* macro to set/unset bit */ -#define HDMI_SET_BIT(num) (hdmi_bitmap |= (1ULL << ((num) % HDMI_BITMAP_T))) -#define HDMI_UNSET_BIT(num) (hdmi_bitmap &= ~(1ULL << ((num) % HDMI_BITMAP_T))) - -typedef unsigned long long hdmi_bitmap_t; - -static hdmi_bitmap_t hdmi_bitmap; +static struct dd_bitmap *bm_hdmi; static struct display_plugin *disp_plgn; static struct extcon_ops hdmi_extcon_ops; @@ -66,7 +60,12 @@ static void hdmi_send_broadcast(int status) /* if hdmi_bitmap is bigger than 0, we assume hdmi is connected */ static int get_hdmi_status(void) { - if (hdmi_bitmap > 0) + if (!bm_hdmi) { + _E("bm_hdmi is not initialized."); + return HDMI_DISCONNECTED; + } + + if (count_set_bit(bm_hdmi) > 0) return HDMI_CONNECTED; return HDMI_DISCONNECTED; @@ -75,18 +74,28 @@ static int get_hdmi_status(void) static void update_hdmi_bitmap(int index, int status) { + if (!bm_hdmi) { + _E("bm_hdmi is not initialized."); + return; + } + if (status == HDMI_CONNECTED) - HDMI_SET_BIT(index); + set_bit(bm_hdmi, index); else - HDMI_UNSET_BIT(index); + clear_bit(bm_hdmi, index); } static void update_all_hdmi_bitmap(int status) { + if (!bm_hdmi) { + _E("bm_hdmi is not initialized."); + return; + } + if (status == HDMI_CONNECTED) - hdmi_bitmap = ULLONG_MAX; + set_all_bits(bm_hdmi); else - hdmi_bitmap = 0; + clear_all_bits(bm_hdmi); } static int hdmi_update(const char *index, int status) @@ -95,6 +104,11 @@ static int hdmi_update(const char *index, int status) int num = -1; int hdmi_status; + if (!bm_hdmi) { + _E("bm_hdmi is not initialized."); + return -ENODEV; + } + _I("Hdmi changed"); if (disp_plgn->pm_change_internal) disp_plgn->pm_change_internal(INTERNAL_LOCK_HDMI, LCD_NORMAL); @@ -178,11 +192,15 @@ static void hdmi_init(void *data) ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_SYSNOTI, &dbus_interface); if (ret < 0) _E("Failed to init dbus method: %d", ret); + + bm_hdmi = init_bitmap(HDMI_NUMBER_MAX); } static void hdmi_exit(void *data) { unregister_notifier(DEVICE_NOTIFIER_LCD, display_changed); + + deinit_bitmap(bm_hdmi); } static struct extcon_ops hdmi_extcon_ops = { -- 2.7.4 From 1e6745de813f943b1a2aa5e881490bb68de5a4d0 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 10 Nov 2020 18:22:45 +0900 Subject: [PATCH 13/16] Manage application state: foreground, background, terminated Foreground / Background An application's lock is managed more strictly from the point when the application requires it. Now determine the memeber variable 'background' of PmLockNode based on the application's fg/bg state when adding lock as a new PmLockNode. Terminated When an application is terminated without releasing lock, deviced unlocks it right away. At the same time, deviced decides whether to change state or not. At before, for this situation, it was responsible for pmlock_check() to release lingering lock of terminated application. Change-Id: I70e66b69a5f3cdbfa54a2deb2e53ddf15d5456e1 Signed-off-by: Youngjae Cho Signed-off-by: lokilee73 --- plugins/iot/display/core.c | 15 ++++++--- plugins/mobile/display/core.c | 15 ++++++--- plugins/tv/display/core.c | 15 ++++++--- plugins/wearable/display/core.c | 15 ++++++--- src/apps/apps.c | 45 +++++++++++++++++++++++++ src/apps/apps.h | 9 ++++- src/core/device-notifier.c | 5 +-- src/core/device-notifier.h | 5 +-- src/display/core.h | 1 + src/display/display-dbus.c | 36 ++++++++++++++++++-- src/display/display-lock.c | 74 +++++++++++++++++++++++++++++++++-------- src/display/display-lock.h | 8 ++--- 12 files changed, 202 insertions(+), 41 deletions(-) diff --git a/plugins/iot/display/core.c b/plugins/iot/display/core.c index 228ac67..13f389e 100644 --- a/plugins/iot/display/core.c +++ b/plugins/iot/display/core.c @@ -221,6 +221,11 @@ inline struct state* state_st(enum state_t state) return &states[state]; } +guint get_transition_timer(void) +{ + return timeout_src_id; +} + void change_state_action(enum state_t state, int (*func)(int timeout)) { _I("[%s] 'action' is changed.", states[state].name); @@ -2095,8 +2100,9 @@ static void display_init(void *data) register_kernel_uevent_control(&lcd_uevent_ops); register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - register_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - register_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + register_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); @@ -2237,8 +2243,9 @@ static void display_exit(void *data) break; case INIT_POLL: unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); unregister_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); diff --git a/plugins/mobile/display/core.c b/plugins/mobile/display/core.c index 3a3b7ce..29050cb 100644 --- a/plugins/mobile/display/core.c +++ b/plugins/mobile/display/core.c @@ -224,6 +224,11 @@ inline struct state* state_st(enum state_t state) return &states[state]; } +guint get_transition_timer(void) +{ + return timeout_src_id; +} + void change_state_action(enum state_t state, int (*func)(int timeout)) { _I("[%s] 'action' is changed.", states[state].name); @@ -2106,8 +2111,9 @@ static void display_init(void *data) register_kernel_uevent_control(&lcd_uevent_ops); register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - register_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - register_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + register_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); @@ -2248,8 +2254,9 @@ static void display_exit(void *data) break; case INIT_POLL: unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); unregister_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); diff --git a/plugins/tv/display/core.c b/plugins/tv/display/core.c index 94a6503..41cecfd 100644 --- a/plugins/tv/display/core.c +++ b/plugins/tv/display/core.c @@ -222,6 +222,11 @@ inline struct state* state_st(enum state_t state) return &states[state]; } +guint get_transition_timer(void) +{ + return timeout_src_id; +} + void change_state_action(enum state_t state, int (*func)(int timeout)) { _I("[%s] 'action' is changed.", states[state].name); @@ -2097,8 +2102,9 @@ static void display_init(void *data) register_kernel_uevent_control(&lcd_uevent_ops); register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - register_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - register_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + register_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); @@ -2239,8 +2245,9 @@ static void display_exit(void *data) break; case INIT_POLL: unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); unregister_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); diff --git a/plugins/wearable/display/core.c b/plugins/wearable/display/core.c index 3d13b4c..6596a70 100644 --- a/plugins/wearable/display/core.c +++ b/plugins/wearable/display/core.c @@ -244,6 +244,11 @@ inline struct state *state_st(enum state_t state) return &states[state]; } +guint get_transition_timer(void) +{ + return timeout_src_id; +} + void change_state_action(enum state_t state, int (*func)(int timeout)) { _I("[%s] 'action' is changed.", states[state].name); @@ -2440,8 +2445,9 @@ static void display_init(void *data) register_kernel_uevent_control(&sec_dsim_uevent_ops); register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - register_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - register_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + register_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + register_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); register_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); register_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); register_notifier(DEVICE_NOTIFIER_LCD_AUTOBRT_SENSING, display_auto_brightness_sensing); @@ -2583,8 +2589,9 @@ static void display_exit(void *data) break; case INIT_POLL: unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_BACKGROUND, process_background); - unregister_notifier(DEVICE_NOTIFIER_PROCESS_FOREGROUND, process_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, display_app_background); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, display_app_foreground); + unregister_notifier(DEVICE_NOTIFIER_APPLICATION_TERMINATED, display_app_terminated); unregister_notifier(DEVICE_NOTIFIER_BATTERY_HEALTH, battery_health_changed); unregister_notifier(DEVICE_NOTIFIER_DISPLAY_BRIGHTNESS, display_brightness_changed); diff --git a/src/apps/apps.c b/src/apps/apps.c index 1debfa6..8e1923b 100644 --- a/src/apps/apps.c +++ b/src/apps/apps.c @@ -21,11 +21,14 @@ #include "core/common.h" #include "apps.h" #include "shared/plugin.h" +#include "core/bitmap.h" #define POPUP_METHOD "PopupLaunch" #define BUFF_MAX 255 static struct display_plugin *disp_plgn; +static struct dd_bitmap *bm_background; +static int pid_max; static const struct app_dbus_match { const char *type; @@ -173,9 +176,51 @@ int remove_notification(char *type, int id) __cb, -1, NULL); } +bool is_app_background(pid_t pid) +{ + return test_bit(bm_background, pid); +} + +void init_bm_background(void) +{ + int ret; + + ret = sys_get_int("/proc/sys/kernel/pid_max", &pid_max); + if (ret < 0) + pid_max = 32768; + + /* need (pid_max + 1) bits to represent pid 0 ~ pid_max */ + bm_background = init_bitmap(pid_max + 1); + if (!bm_background) + _E("Failed to allock bm_background."); +} + +void set_app_state(pid_t pid, enum application_state as) +{ + if (!bm_background) + return; + + if (pid < 0 || pid > pid_max) + return; + + if (as == APPLICATION_BACKGROUND) + set_bit(bm_background, pid); + else if (as == APPLICATION_FOREGROUND || as == APPLICATION_TERMINATED) + clear_bit(bm_background, pid); + else + _E("Invalid as=%d", as); +} + static void __CONSTRUCTOR__ initialize(void) { disp_plgn = get_var_display_plugin(); if (!disp_plgn) _E("Failed to get display plugin variable."); + + init_bm_background(); +} + +static void __DESTRUCTOR__ finalize(void) +{ + deinit_bitmap(bm_background); } diff --git a/src/apps/apps.h b/src/apps/apps.h index 5e1b393..80daf7d 100644 --- a/src/apps/apps.h +++ b/src/apps/apps.h @@ -32,10 +32,17 @@ #define APP_REMOVE "remove" #define APP_KEY_TYPE "_SYSPOPUP_CONTENT_" +enum application_state { + APPLICATION_TERMINATED = 0, + APPLICATION_FOREGROUND, + APPLICATION_BACKGROUND, /* deactivate NORMAL, DIM lock */ +}; + int launch_system_app(char *type, int num, ...); int launch_message_post(char *type); int add_async_notification(char *type, dbus_pending_cb func, char *sig, ...); int remove_notification(char *type, int id); - +void set_app_state(pid_t pid, enum application_state as); +bool is_app_background (pid_t pid); #endif /* __APPS_H__ */ diff --git a/src/core/device-notifier.c b/src/core/device-notifier.c index 3f8d1b6..78dc63a 100644 --- a/src/core/device-notifier.c +++ b/src/core/device-notifier.c @@ -60,8 +60,9 @@ static const char *device_notifier_type_str[DEVICE_NOTIFIER_MAX] = { NOTIFY_STR(DEVICE_NOTIFIER_DISPLAY_LOCK), NOTIFY_STR(DEVICE_NOTIFIER_POWER_RESUME), NOTIFY_STR(DEVICE_NOTIFIER_POWEROFF), - NOTIFY_STR(DEVICE_NOTIFIER_PROCESS_BACKGROUND), - NOTIFY_STR(DEVICE_NOTIFIER_PROCESS_FOREGROUND), + NOTIFY_STR(DEVICE_NOTIFIER_APPLICATION_BACKGROUND), + NOTIFY_STR(DEVICE_NOTIFIER_APPLICATION_FOREGROUND), + NOTIFY_STR(DEVICE_NOTIFIER_APPLICATION_TERMINATED), NOTIFY_STR(DEVICE_NOTIFIER_USB_DEBUG_MODE), NOTIFY_STR(DEVICE_NOTIFIER_USB_TETHERING_MODE), NOTIFY_STR(DEVICE_NOTIFIER_EVENT_HANDLER), diff --git a/src/core/device-notifier.h b/src/core/device-notifier.h index 6362a82..f8f190d 100644 --- a/src/core/device-notifier.h +++ b/src/core/device-notifier.h @@ -39,8 +39,9 @@ enum device_notifier_type { DEVICE_NOTIFIER_DISPLAY_LOCK, DEVICE_NOTIFIER_POWER_RESUME, DEVICE_NOTIFIER_POWEROFF, - DEVICE_NOTIFIER_PROCESS_BACKGROUND, - DEVICE_NOTIFIER_PROCESS_FOREGROUND, + DEVICE_NOTIFIER_APPLICATION_BACKGROUND, + DEVICE_NOTIFIER_APPLICATION_FOREGROUND, + DEVICE_NOTIFIER_APPLICATION_TERMINATED, DEVICE_NOTIFIER_USB_DEBUG_MODE, DEVICE_NOTIFIER_USB_TETHERING_MODE, DEVICE_NOTIFIER_EVENT_HANDLER, diff --git a/src/display/core.h b/src/display/core.h index 00c3e27..a819135 100644 --- a/src/display/core.h +++ b/src/display/core.h @@ -214,6 +214,7 @@ bool touch_event_blocked(void); void broadcast_lcd_off_late(enum device_flags flags); void set_dim_state(bool on); void reset_timeout(int timeout); +guint get_transition_timer(void); /* auto-brightness.c */ void set_brightness_changed_state(void); diff --git a/src/display/display-dbus.c b/src/display/display-dbus.c index 846c67e..5fa2168 100644 --- a/src/display/display-dbus.c +++ b/src/display/display-dbus.c @@ -43,10 +43,12 @@ #include "display-ops.h" #include "display.h" #include "shared/plugin.h" +#include "display-lock.h" #define AUL_APPSTATUS_PATH "/Org/Tizen/Aul/AppStatus" #define AUL_APPSTATUS_INTERFACE "org.tizen.aul.AppStatus" #define APP_CHANGE_STATE "AppStatusChange" +#define APP_TERMINATED "AppTerminated" #define TELEPHONY_PATH "/org/tizen/telephony" #define TELEPHONY_INTERFACE_SIM "org.tizen.telephony.Manager" @@ -1302,10 +1304,12 @@ static void changestate_signal_handler(GDBusConnection *conn, if (!strcmp(state, "bg")) { _D("process(%d) was going background.", pid); - device_notify(DEVICE_NOTIFIER_PROCESS_BACKGROUND, &pid); + set_app_state(pid, APPLICATION_BACKGROUND); + device_notify(DEVICE_NOTIFIER_APPLICATION_BACKGROUND, &pid); } else if (!strcmp(state, "fg")) { _D("process(%d) was going foreground.", pid); - device_notify(DEVICE_NOTIFIER_PROCESS_FOREGROUND, &pid); + set_app_state(pid, APPLICATION_FOREGROUND); + device_notify(DEVICE_NOTIFIER_APPLICATION_FOREGROUND, &pid); } out: @@ -1313,6 +1317,25 @@ out: g_free(state); } +static void app_terminate_signal_handler(GDBusConnection *conn, + const gchar *sender, + const gchar *path, + const gchar *iface, + const gchar *name, + GVariant *param, + gpointer data) +{ + pid_t pid; + + if (!g_variant_get_safe(param, "(i)", &pid)) { + _E("failed to get params from gvariant. expected:%s, type:%s", "(i)", g_variant_get_type_string(param)); + return; + } + + set_app_state(pid, APPLICATION_TERMINATED); + device_notify(DEVICE_NOTIFIER_APPLICATION_TERMINATED, &pid); +} + /* * Default capability * api := LCDON | LCDOFF | BRIGHTNESS @@ -1351,6 +1374,15 @@ int init_pm_dbus(void) if (ret <= 0) _E("Failed to register signal handler: %d", ret); + ret = subscribe_dbus_signal(NULL, + AUL_APPSTATUS_PATH, + AUL_APPSTATUS_INTERFACE, + APP_TERMINATED, + app_terminate_signal_handler, + NULL, NULL); + if (ret <= 0) + _E("Failed to register signal handler: %d", ret); + return 0; } diff --git a/src/display/display-lock.c b/src/display/display-lock.c index 2df1497..ade3cd1 100644 --- a/src/display/display-lock.c +++ b/src/display/display-lock.c @@ -24,15 +24,20 @@ #include "core/common.h" #include "device-interface.h" #include "poll.h" +#include "display.h" #include "display-signal.h" #include "lock-detector.h" #include "display-lock.h" #include "shared/log-macro.h" +#include "apps/apps.h" #define METHOD_APP_STATUS "CheckAppStatus" #define PID_MAX 6 #define LOCK_TIME_WARNING 60 /* 60 seconds */ +#define no_transition_timer() (get_transition_timer() == 0) +#define no_foreground_lock(st) (check_lock_state(st) == false) + static struct _backlight_ops *backlight_ops; static dd_list *cond_head[S_END]; static int trans_condition; @@ -45,14 +50,14 @@ bool check_lock_state(int state) PmLockNode *t; DD_LIST_FOREACH(cond_head[state], elem, t) { - if (t->background == false) + if (t->app_background == false) return true; } return false; } -static void refresh_app_cond() +static void refresh_app_cond(void) { trans_condition = 0; @@ -216,7 +221,12 @@ PmLockNode *add_node(enum state_t s_index, pid_t pid, guint timeout_id, n->timeout_id = timeout_id; n->time = now; n->holdkey_block = holdkey_block; - n->background = false; + /* LCDOFF lock should be maintained regardless of fg/bg state */ + if (n->state == S_NORMAL || n->state == S_LCDDIM) { + n->app_background = is_app_background(n->pid); + if (n->app_background) + _W("App(%d) requested %d lock in background.", n->pid, n->state); + } n->broadcast_warning = true; if (pid < INTERNAL_LOCK_BASE) { @@ -274,7 +284,7 @@ int check_lock_condition(enum state_t state) _D("check holdkey block : state of %s", state_st(state)->name); DD_LIST_FOREACH(cond_head[state], elem, t) { - if (t->pid != owner && t->background == false) { + if (t->pid != owner && t->app_background == false) { ret = true; _I("state change was blocked by pid(%d)!", t->pid); break; @@ -411,7 +421,7 @@ dd_list *get_cond_head(enum state_t s_index) return cond_head[s_index]; } -int process_background(void *data) +int display_app_background(void *data) { pid_t pid; PmLockNode *node; @@ -420,20 +430,20 @@ int process_background(void *data) node = find_node(S_NORMAL, pid); if (node) { - node->background = true; - _I("Process(%d) goes background. LCD_NORMAL will be unlocked.", pid); + node->app_background = true; + _I("App(%d) goes background. LCD_NORMAL will be unlocked.", pid); } node = find_node(S_LCDDIM, pid); if (node) { - node->background = true; - _I("Process(%d) goes background. LCD_DIM will be unlocked.", pid); + node->app_background = true; + _I("App(%d) goes background. LCD_DIM will be unlocked.", pid); } return 0; } -int process_foreground(void *data) +int display_app_foreground(void *data) { pid_t pid; PmLockNode *node; @@ -442,19 +452,55 @@ int process_foreground(void *data) node = find_node(S_NORMAL, pid); if (node) { - node->background = false; - _I("Process(%d) goes foreground. LCD_NORMAL will be locked.", pid); + node->app_background = false; + _I("App(%d) goes foreground. LCD_NORMAL will be locked.", pid); } node = find_node(S_LCDDIM, pid); if (node) { - node->background = false; - _I("Process(%d) goes foreground. LCD_DIM will be locked.", pid); + node->app_background = false; + _I("App(%d) goes foreground. LCD_DIM will be locked.", pid); } return 0; } +int display_app_terminated(void *data) +{ + pid_t pid; + PmLockNode *node; + enum state_t state; + enum state_t cur = get_pm_cur_state(); + bool current_unlocked = false; + + pid = *(pid_t *)data; + + /* release lock if it is holding locks */ + for (state = S_START; state < S_END; ++state) { + node = find_node(state, pid); + if (node) { + _W("App=%d is terminated without releasing lockstate=%d. deviced unlocks it.", pid, state); + del_node(state, node); + set_unlock_time(pid, state); + if (state == cur) + current_unlocked = true; + } + } + + /* Change state only when all three conditions below are satisfied. + * 1. the lock released due to the termination of the application + * must be a lock for the current state + * 2. after releasing the lock, there is no foreground lock + * for the current state + * 3. there should be no running state-transition timer + * + * This emulates already expired transition timer */ + if (current_unlocked && no_foreground_lock(cur) && no_transition_timer()) + reset_timeout(0); + + return 0; +} + /* update transition condition for application requrements */ void update_lock_timer(PMMsg *data, PmLockNode *node, guint timeout_id) diff --git a/src/display/display-lock.h b/src/display/display-lock.h index 42c1853..3e83771 100644 --- a/src/display/display-lock.h +++ b/src/display/display-lock.h @@ -34,7 +34,7 @@ typedef struct _pm_lock_node { GVariant *warning_param; time_t time; bool holdkey_block; - bool background; + bool app_background; bool broadcast_warning; /* Set true when the lock holder is an entry of @@ -62,10 +62,10 @@ void makeup_trans_condition(void); int check_processes(enum state_t prohibit_state); int get_trans_condition(void); dd_list *get_cond_head(enum state_t s_index); -int process_background(void *data); -int process_foreground(void *data); +int display_app_background(void *data); +int display_app_foreground(void *data); +int display_app_terminated(void *data); void update_lock_timer(PMMsg *data, PmLockNode *node, guint timeout_id); - extern int custom_holdkey_block; #endif /* __DISPLAY_LOCK_H__ */ -- 2.7.4 From 86777773919c53dfd5d2b8abe406f4e64c5998fb Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 24 Nov 2020 13:59:59 +0900 Subject: [PATCH 14/16] Make critical-log configurable Change-Id: I67eb3788a78f5ce02dacb85f8c3398d5f54fd947 Signed-off-by: Youngjae Cho --- CMakeLists.txt | 2 +- conf/critical-log.conf | 13 ------------- packaging/deviced.spec | 1 + src/shared/log-macro.h | 6 ++++++ 4 files changed, 8 insertions(+), 14 deletions(-) delete mode 100644 conf/critical-log.conf diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bfcc69..b104d6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -282,7 +282,7 @@ IF(USB_MODULE STREQUAL on) ENDIF() IF(CRITICAL_LOG_MODULE STREQUAL on) - INSTALL_CONF(conf critical-log) + ADD_DEFINITIONS("-DCRITICAL_LOG_ON") ENDIF() CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY) diff --git a/conf/critical-log.conf b/conf/critical-log.conf deleted file mode 100644 index 0f76445..0000000 --- a/conf/critical-log.conf +++ /dev/null @@ -1,13 +0,0 @@ -#Critical Log will be saved under the /var/log/ghost/boot/#booting_count -#Critical Log Format is "Section|String Value" -#Limit means Last Critical Log Logging Count -[Common] -Limit=100 -[Battery] -Limit=20 -[BatteryHealth] -Limit=10 -[PowerHandle] -Limit=10 -[CoolDown] -Limit=10 diff --git a/packaging/deviced.spec b/packaging/deviced.spec index db438a9..bd7d771 100644 --- a/packaging/deviced.spec +++ b/packaging/deviced.spec @@ -165,6 +165,7 @@ Plugin libraries for IoT devices -DTOUCH_SENSITIVITY_MODULE=on \ -DDUMP_MODULE=on \ -DDEVICE_BOARD_MODULE=on \ + -DCRITICAL_LOG_MODULE=on \ #eol %build diff --git a/src/shared/log-macro.h b/src/shared/log-macro.h index 773ea44..440300f 100644 --- a/src/shared/log-macro.h +++ b/src/shared/log-macro.h @@ -22,9 +22,14 @@ #ifdef ENABLE_DLOG #include + /* critical log */ +#ifdef CRITICAL_LOG_ON #define CRITICAL_LOG(fmt, arg...) \ do { CRITICAL_LOG_(LOG_ID_SYSTEM, DLOG_INFO, LOG_TAG, fmt, ##arg); } while (0) +#else +#define CRITICAL_LOG(fmt, arg...) _I(fmt, ##arg) +#endif #define _D(fmt, arg...) \ do { SLOGD(fmt, ##arg); } while (0) @@ -43,6 +48,7 @@ #define _SE(fmt, arg...) \ do { SECURE_SLOGE(fmt, ##arg); } while (0) #else +#define CRITICAL_LOG(...) do { } while (0) #define _D(...) do { } while (0) #define _I(...) do { } while (0) #define _W(...) do { } while (0) -- 2.7.4 From 61ee007663fa4a0dccfde0a4de0ae6163d335bed Mon Sep 17 00:00:00 2001 From: INSUN PYO Date: Fri, 27 Nov 2020 19:06:00 +0900 Subject: [PATCH 15/16] usb: change usb initialization - skip usb hal operation when usb is disconnected. If USB is initialized without a USB connection, only initialize the internal usb state and skip usb hal operation. To support sdb over BT, sdbd.service should start automatically at boot time. If usb cable is not connected, usb hal stops sdbd.service when initializing usb. Change-Id: I936d0a62b5d3a0e8229ff02760e1a6d23081a003 --- src/usb/usb.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/usb/usb.c b/src/usb/usb.c index 407edde..f85bba3 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -386,7 +386,7 @@ int usb_change_mode(unsigned int new_mode, bool change_debug_mode) static int usb_state_changed(const char *index, int new_status) { int ret = -1; - static int old_status = -1; + static int old_status = -1; /* -1: Uninitialized, 0: disconnected, 1: connected */ /* For debugging. Do not move the location. */ _I("USB state is changed by extcon from (%d) to (%d).", old_status, new_status); @@ -400,7 +400,21 @@ static int usb_state_changed(const char *index, int new_status) break; case USB_DISCONNECTED: - ret = usb_disconnected(); + if (old_status == -1) { + /* only initialize the internal data state and skip usb hal operation. */ + _I("USB is initialized without USB connection"); + + /* From usb_disconnected() */ + usb_state_set_connection(USB_DISCONNECTED); + send_usb_state_changed_event(VCONFKEY_SYSMAN_USB_DISCONNECTED); + + /* From usb_disable() */ + (void)usb_state_set_current_mode(USB_FUNCTION_NONE); + change_usb_state_notification_handler(USB_FUNCTION_NONE); + + ret = 0; + } else + ret = usb_disconnected(); break; default: -- 2.7.4 From 0358d4d97b46271901ba866260504f81a8b0b32e Mon Sep 17 00:00:00 2001 From: lokilee73 Date: Thu, 3 Dec 2020 17:00:46 +0900 Subject: [PATCH 16/16] Remove unused function low-power low-power.c is not used and duplicated with powersaver.c Change-Id: I8e93891c41d83710d26e6d4ecbc2c9a5a77bc7bd Signed-off-by: lokilee73 --- conf/org.tizen.system.deviced.conf | 2 - src/auto-test/power.c | 90 +--------------- src/power/low-power.c | 212 ------------------------------------- 3 files changed, 2 insertions(+), 302 deletions(-) delete mode 100644 src/power/low-power.c diff --git a/conf/org.tizen.system.deviced.conf b/conf/org.tizen.system.deviced.conf index 4d99362..bafc8fa 100644 --- a/conf/org.tizen.system.deviced.conf +++ b/conf/org.tizen.system.deviced.conf @@ -60,8 +60,6 @@ - - diff --git a/src/auto-test/power.c b/src/auto-test/power.c index 2a88a98..29b6a3c 100644 --- a/src/auto-test/power.c +++ b/src/auto-test/power.c @@ -20,10 +20,6 @@ #define METHOD_POWEROFF "PowerOff" #define METHOD_POWEROFF_WITH_OPTION "PowerOffWithOption" -#define METHOD_LOWPOWER_START "Start" -#define METHOD_LOWPOWER_STOP "Stop" -#define METHOD_LOWPOWER_GETSTATE "GetState" - static bool set_reboot_method(const char *method, GVariant *param) { GVariant *msg; @@ -68,77 +64,6 @@ static bool set_reboot_with_option(char *type, char *option) return set_reboot_method(METHOD_POWEROFF_WITH_OPTION, g_variant_new("(ss)", type, option)); } -static bool request_lowpower_method(const char *method, GVariant *param) -{ - GVariant *msg; - int val; - bool ret = FALSE; - int retry = 0; - - while (retry++ < 3) { - msg = dbus_handle_method_sync_with_reply_var(DEVICED_BUS_NAME, - DEVICED_PATH_LOWPOWER, - DEVICED_INTERFACE_LOWPOWER, - method, - param); - if (!msg) { - _E("fail (%s): no reply", method); - return ret; - } - - if (!g_variant_get_safe(msg, "(i)", &val)) - _E("fail (%s): no message", method); - else { - if (val == -EAGAIN) { - g_variant_unref(msg); - _I("wait! will try again! (%s): %d", method, val); - sleep(3); - continue; - } else if ((val == -ENOTSUP) || (val == -ENOSYS)) { - _I("Not supported feature! (%s): %d", method, val); - ret = TRUE; - } else if (val < 0) { - _E("fail (%s): returned fail (%d)", method, val); - } else { - _I("success (%s): %d", method, val); - ret = TRUE; - } - } - g_variant_unref(msg); - break; - } - - return ret; -} - -static bool set_lowpower_start() -{ - return request_lowpower_method(METHOD_LOWPOWER_START, NULL); -} - -static bool set_lowpower_stop() -{ - return request_lowpower_method(METHOD_LOWPOWER_STOP, NULL); -} - -static bool set_lowpower_getstate() -{ - return request_lowpower_method(METHOD_LOWPOWER_GETSTATE, NULL); -} - -void lowpower_test_all(int *success, int *fail) -{ - int s = 0; - int f = 0; - - (set_lowpower_start()) ? s++ : f++; - (set_lowpower_stop()) ? s++ : f++; - (set_lowpower_getstate()) ? s++ : f++; - - if (NULL != success) *success = s; - if (NULL != fail) *fail = f; -} - static void power_init(void *data) { int success = 0; @@ -146,8 +71,6 @@ static void power_init(void *data) _I("start test"); - lowpower_test_all(&success, &fail); - _I("Total: %d, Success: %d, Fail: %d", success+fail, success, fail); } @@ -163,22 +86,13 @@ static int power_unit(int argc, char **argv) int fail = 0; _I("start test"); - lowpower_test_all(&success, &fail); + _I("Total: %d, Success: %d, Fail: %d", success+fail, success, fail); } else if (0 == strcmp(argv[3], METHOD_POWEROFF)) set_reboot(argv[4]); else if (0 == strcasecmp(argv[3], METHOD_POWEROFF_WITH_OPTION)) set_reboot_with_option(argv[4], argv[5]); - else if (0 == strcasecmp(argv[3], "lowpower")) { - if (0 == strcasecmp(argv[4], METHOD_LOWPOWER_START)) - set_lowpower_start(); - else if (0 == strcasecmp(argv[4], METHOD_LOWPOWER_STOP)) - set_lowpower_stop(); - else if (0 == strcasecmp(argv[4], METHOD_LOWPOWER_GETSTATE)) - set_lowpower_getstate(); - else - _E("Unknown test case!!!"); - } else + else _E("Unknown test case!!!"); return 0; diff --git a/src/power/low-power.c b/src/power/low-power.c deleted file mode 100644 index 9e77a79..0000000 --- a/src/power/low-power.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * deviced - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#include -#include -#include -#include -#include -#include - -#include "core/log.h" -#include "core/device-notifier.h" -#include "core/device-idler.h" -#include "core/common.h" -#include "core/devices.h" - -#ifndef VCONFKEY_SYSMAN_LOW_POWER_MODE -#define VCONFKEY_SYSMAN_LOW_POWER_MODE "db/sysman/low_power_mode" -#define VCONFKEY_SYSMAN_LOW_POWER_MODE_OFF 0 -#define VCONFKEY_SYSMAN_LOW_POWER_MODE_ON 1 -#endif - -static bool low_power_enabled; - -static int low_power_start(void *data) -{ - int ret; - - if (low_power_enabled) - return 0; - - ret = vconf_set_int(VCONFKEY_SYSMAN_LOW_POWER_MODE, - VCONFKEY_SYSMAN_LOW_POWER_MODE_ON); - if (ret < 0) { - _E("Failed to set vconf value for low power mode: %d", vconf_get_ext_errno()); - return -ENOMEM; - } - - low_power_enabled = true; - _I("Low Power Mode Start."); - - return 0; -} - -static int low_power_stop(void *data) -{ - int ret; - - if (!low_power_enabled) - return 0; - - ret = vconf_set_int(VCONFKEY_SYSMAN_LOW_POWER_MODE, - VCONFKEY_SYSMAN_LOW_POWER_MODE_OFF); - if (ret < 0) { - _E("Failed to set vconf value for low power mode: %d", vconf_get_ext_errno()); - return -ENOMEM; - } - - low_power_enabled = false; - _I("Low Power Mode Stop."); - - return 0; -} - -static int booting_done(void *data) -{ - static int done = 0; - int mode, ret; - - if (data == NULL) - goto out; - if (done) - goto out; - - done = *(int*)data; - - ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_POWER_MODE, &mode); - if (ret == 0 && mode == VCONFKEY_SYSMAN_LOW_POWER_MODE_ON) { - _I("Low Power Mode Start."); - low_power_enabled = true; - } else if (ret < 0) - _E("Failed to get vconf value for low power mode: %d", vconf_get_ext_errno()); - -out: - return done; -} - -static GVariant *dbus_low_power_start(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) -{ - int ret; - pid_t pid; - - if (!booting_done(NULL)) { - _I("Booting is not done yet."); - ret = -EAGAIN; - goto out; - } - - pid = dbus_connection_get_sender_pid(conn, sender); - if (pid == -1 || kill(pid, 0) == -1) { - _E("Sender(%d) does not exist.", pid); - ret = -EINVAL; - goto out; - } - - _I("Low Power Mode started by PID(%d).", pid); - ret = low_power_start(NULL); - if (ret < 0) - _E("Failed to start Low Power Mode(%d).", ret); - -out: - return g_variant_new("(i)", ret); -} - -static GVariant *dbus_low_power_stop(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) -{ - int ret; - pid_t pid; - - if (!booting_done(NULL)) { - _I("Booting is not done yet."); - ret = -EAGAIN; - goto out; - } - - pid = dbus_connection_get_sender_pid(conn, sender); - if (pid == -1 || kill(pid, 0) == -1) { - _E("Sender(%d) does not exist.", pid); - ret = -EINVAL; - goto out; - } - - _I("Low Power Mode stopped by PID(%d).", pid); - ret = low_power_stop(NULL); - if (ret < 0) - _E("Failed to stop Low Power Mode(%d).", ret); - -out: - return g_variant_new("(i)", ret); -} - -static GVariant *dbus_low_power_get_state(GDBusConnection *conn, - const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, - GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) -{ - return g_variant_new("(i)", (low_power_enabled ? 1 : 0)); -} - -static const dbus_method_s dbus_methods[] = { - { "Start", NULL, "i", dbus_low_power_start }, - { "Stop", NULL, "i", dbus_low_power_stop }, - { "GetState", NULL, "i", dbus_low_power_get_state }, - /* Add methods here */ -}; - -static const dbus_interface_u dbus_interface = { - .oh = NULL, - .name = DEVICED_INTERFACE_LOWPOWER, - .methods = dbus_methods, - .nr_methods = ARRAY_SIZE(dbus_methods), -}; - -static void low_power_init(void *data) -{ - int ret; - - /* init dbus interface */ - ret = dbus_handle_add_dbus_object(NULL, DEVICED_PATH_LOWPOWER, &dbus_interface); - if (ret < 0) - _E("Failed to init dbus method(%d).", ret); - - register_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); -} - -static void low_power_exit(void *data) -{ - int ret; - - ret = low_power_stop(NULL); - if (ret < 0) - _E("Failed to stop Low Power Mode(%d).", ret); - - unregister_notifier(DEVICE_NOTIFIER_BOOTING_DONE, booting_done); -} - -static const struct device_ops low_power_device_ops = { - .name = "low-power", - .init = low_power_init, - .exit = low_power_exit, -}; - -DEVICE_OPS_REGISTER(&low_power_device_ops) -- 2.7.4