From 3ae0cab3228895407a1462338c54f03636a4e049 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Wed, 9 Nov 2022 10:39:59 +0900 Subject: [PATCH 01/16] display: remove unused code It has been removed since ce471ec18f19bb184848f4c84e813b834ef4bdee. Change-Id: I5b74f4907bc7e6b9a04f3b3960470fb984446737 Signed-off-by: Youngjae Cho --- plugins/tv/display/state-tv.c | 580 ------------------------------------------ 1 file changed, 580 deletions(-) delete mode 100644 plugins/tv/display/state-tv.c diff --git a/plugins/tv/display/state-tv.c b/plugins/tv/display/state-tv.c deleted file mode 100644 index 96d7331..0000000 --- a/plugins/tv/display/state-tv.c +++ /dev/null @@ -1,580 +0,0 @@ -/* - * deviced - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. - * - * 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 "shared/common.h" -#include "core/log.h" -#include "shared/device-notifier.h" -#include "shared/devices.h" -#include "display/display-ops.h" -#include "display/display-lock.h" -#include "power/power.h" -#include "power/power-off.h" -#include "power/power-suspend.h" -#include "core.h" -#include "poll.h" -#include "device-interface.h" -#include "util.h" -#include "shared/plugin.h" - -#define PRE_STATE_CHANGE_TIMEOUT 500*1000 /* 500ms */ -#define SIGNAL_CHANGE_STATE "ChangeState" -#define SIGNAL_PRE_CHANGE_STATE "PreChangeState" -#define SIGNAL_WAKEUP "WakeUp" -#define SIGNAL_PRE_WAKEUP "PreWakeUp" -#define SIGNAL_POST_WAKEUP "PostWakeUp" -#define SIGNAL_EARLY_WAKEUP "EarlyWakeUp" - -static struct display_plugin *disp_plgn; -static struct _backlight_ops *backlight_ops; -static guint standby_timer; - -static int change_state(pid_t pid, int type, enum state_t st) -{ - int ret; - - if (type == PM_CONTROL_EVENT && state_st(st)->check) { - ret = state_st(get_pm_cur_state())->check(get_pm_cur_state(), st); - if (ret != 0) { - _E("(%s) State Locked. Cannot be changed to (%s)", - state_st(get_pm_cur_state())->name, state_st(st)->name); - return ret; - } - } - - if (state_st(st)->trans) { - ret = state_st(st)->trans(type); - if (ret < 0) { - _E("Failed to trans state (%s, ret:%d)", state_st(st)->name, ret); - return ret; - } - } - - _I("Success to change state (%s) requested by pid(%d)", state_st(st)->name, pid); - - return 0; -} - -static int tv_proc_change_state(unsigned int cond, pid_t pid) -{ - enum state_t next; - int ret; - - next = GET_COND_STATE(cond); - if (get_pm_cur_state() == next) { - _I("current state (%d) == next state (%d)", get_pm_cur_state(), next); - return 0; - } - - if (pid < INTERNAL_LOCK_BASE) { /* Request from other process*/ - if (next == S_SUSPEND || next == S_POWEROFF) { - _E("Do not change to suspend or power off directly"); - return -EPERM; - } - } - - _I("Change State to %s (%d)", state_st(next)->name, pid); - - ret = change_state(pid, PM_CONTROL_EVENT, next); - if (ret != 0) { - _E("Failed to change state (%d)", ret); - return ret; - } - - return 0; -} - -unsigned long long get_uptime(void) -{ - struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); - return t.tv_sec; -} - -static int lcdon_check(int curr, int next) -{ - /* do not changed to next state if who lock the normal mode */ - check_processes(get_pm_cur_state()); - if (check_lock_state(get_pm_cur_state())) { - _I("S_LCDON Lock state"); - return 1; - } - - return 0; -} - -static int lcdon_pre(void *data) -{ - int ret; - /* TODO: cancel suspend */ - - /* That will unlock callback registration in case of getting back to normal - * from partial poweroff. If someone start poweroff with standby lock and then - * unlock, change state to lcdon, registration of poweroff callback would be blocked - * as unblocking is done when resuming from suspend. - */ - device_notify(DEVICE_NOTIFIER_POWER_RESUME, NULL); - - if (get_pm_cur_state() == S_STANDBY) { - _I("send pre state change NORMAL"); - ret = gdbus_signal_emit(NULL, - DEVICED_PATH_DISPLAY, - DEVICED_INTERFACE_DISPLAY, - SIGNAL_PRE_CHANGE_STATE, - g_variant_new("(s)", state_st(S_LCDON)->name)); - if (ret < 0) - _E("Failed to send dbus signal(%s)", SIGNAL_PRE_CHANGE_STATE); - /*Give time to process callback */ - usleep(PRE_STATE_CHANGE_TIMEOUT); - } - - return 0; -} - -static int lcdon_post(void *data) -{ - int ret; - - ret = gdbus_signal_emit(NULL, - DEVICED_PATH_DISPLAY, - DEVICED_INTERFACE_DISPLAY, - SIGNAL_CHANGE_STATE, - g_variant_new("(s)", state_st(S_LCDON)->name)); - if (ret < 0) - _E("Failed to send dbus signal(%s)", SIGNAL_CHANGE_STATE); - - /* TODO: set_power */ - - return 0; -} - -static int lcdon_action(int timeout) -{ - if ((get_pm_cur_state() != get_pm_old_state()) && - (get_pm_cur_state() != S_SLEEP)) - set_setting_pmstate(get_pm_cur_state()); - - if ((get_pm_old_state() != S_LCDOFF) && - (get_pm_old_state() != S_SLEEP)) { - _I("pm_old_state (%s). Skip lcd on", state_st(get_pm_old_state())->name); - return 0; - } - - /* TODO: post resume */ - - backlight_ops->on(0); - - return 0; -} - -static int lcdon_trans(int evt) -{ - int ret; - struct state *st; - - ret = lcdon_pre(NULL); - if (ret < 0) { - _E("S_LCDON pre-operation failed(%d)", ret); - return ret; - } - - /* state transition */ - set_pm_old_state(get_pm_cur_state()); - set_pm_cur_state(S_LCDON); - st = state_st(get_pm_cur_state()); - - if (st->action) - st->action(0); - - ret = lcdon_post(NULL); - if (ret < 0) - _E("S_LCDON post-operation failed(%d)", ret); - - return 0; -} - -static int lcdoff_check(int curr, int next) -{ - /* LCD OFF can change to LCD ON and STANDBY state */ - return 0; -} - -static int lcdoff_pre(void *data) -{ - return 0; -} - -static int lcdoff_post(void *data) -{ - int ret; - - /* broadcast to other application */ - ret = gdbus_signal_emit(NULL, - DEVICED_PATH_DISPLAY, - DEVICED_INTERFACE_DISPLAY, - SIGNAL_CHANGE_STATE, - g_variant_new("(s)", state_st(S_LCDOFF)->name)); - if (ret < 0) - _E("Failed to send dbus signal(%s)", SIGNAL_CHANGE_STATE); - - return 0; -} - -static int lcdoff_action(int timeout) -{ - if ((get_pm_cur_state() != get_pm_old_state()) && - (get_pm_cur_state() != S_SLEEP)) - set_setting_pmstate(get_pm_cur_state()); - - if ((get_pm_old_state() == S_SUSPEND) || - (get_pm_old_state() == S_LCDOFF)) - return 0; - - backlight_ops->off(0); - - return 0; -} - -static int lcdoff_trans(int evt) -{ - int ret; - struct state *st; - - ret = lcdoff_pre(NULL); - if (ret < 0) { - _E("S_LCDOFF pre-operation failed (%d)", ret); - return ret; - } - - /* state transition */ - set_pm_old_state(get_pm_cur_state()); - set_pm_cur_state(S_LCDOFF); - st = state_st(get_pm_cur_state()); - - if (st->action) - st->action(0); - - ret = lcdoff_post(NULL); - if (ret < 0) - _E("S_LCDOFF post-operation failed (%d)", ret); - - return 0; -} - -static int standby_check(int curr, int next) -{ - /* STANDBY can change to LCD ON or POWER OFF state */ - if (next == S_LCDOFF) - return -EPERM; - - /* do not change to next state if who lock the standby mode */ - check_processes(S_LCDOFF); - if (check_lock_state(S_LCDOFF)) { - _I("S_LCDOFF Lock state"); - return 1; - } - - /* TODO: Instant on timer */ - - return 0; -} - -static int standby_pre(void *data) -{ - return 0; -} - -static int standby_post(void *data) -{ - int ret; - - /* broadcast to other application */ - ret = gdbus_signal_emit(NULL, - DEVICED_PATH_DISPLAY, - DEVICED_INTERFACE_DISPLAY, - SIGNAL_CHANGE_STATE, - g_variant_new("(s)", state_st(S_STANDBY)->name)); - if (ret < 0) - _E("Failed to send dbus signal(%s)", SIGNAL_CHANGE_STATE); - - backlight_ops->off(0); - - /* Set power */ - - return 0; -} - -static int poweroff_trans(int evt); - -static gboolean standby_go_next_state(void *data) -{ - int ret = 0; - - if (standby_timer) { - g_source_remove(standby_timer); - standby_timer = 0; - } - - if (disp_plgn->pm_change_internal) - ret = disp_plgn->pm_change_internal(INTERNAL_LOCK_SUSPEND, SUSPEND); - if (ret < 0) { - _E("Failed to change state to S_SUSPEND. Now Power off !!"); - poweroff_trans(0); - } - - return G_SOURCE_REMOVE; -} - -static int standby_action(int timeout) -{ - if ((get_pm_cur_state() != get_pm_old_state()) && - (get_pm_cur_state() != S_SLEEP)) - set_setting_pmstate(get_pm_cur_state()); - - backlight_ops->off(0); - - standby_timer = g_timeout_add_seconds(0, - standby_go_next_state, NULL); - if (!standby_timer) - _E("Failed to add timer to go to next state of S_STANDBY"); - - return 0; -} - -static int standby_trans(int evt) -{ - int ret; - struct state *st; - - ret = standby_pre(NULL); - if (ret < 0) { - _E("S_STANDBY pre-operation failed(%d)", ret); - return ret; - } - - /* state transition */ - set_pm_old_state(get_pm_cur_state()); - set_pm_cur_state(S_STANDBY); - st = state_st(get_pm_cur_state()); - - if (st->action) - st->action(0); - - ret = standby_post(NULL); - if (ret < 0) - _E("S_STANDBY post-operation failed(%d)", ret); - - return 0; -} - -static int suspend_check(int curr, int next) -{ - /* DO NOT USE THIS FUNCTION */ - return 0; -} - -static int suspend_pre(void *data) -{ - return 0; -} - -static int suspend_post(void *data) -{ - int ret; - unsigned int cond = 0; - - /* TODO: count InstandOn */ - - cond = S_LCDON; - ret = tv_proc_change_state(cond, INTERNAL_LOCK_SUSPEND); - if (ret < 0) - _E("Fail to change state to next_state(%s)", state_st(cond)->name); - - /* Broadcast pre-wakeup signal */ - ret = gdbus_signal_emit(NULL, - DEVICED_PATH_POWER, - DEVICED_INTERFACE_POWER, - SIGNAL_PRE_WAKEUP, - g_variant_new("(i)", 0)); - if (ret < 0) - _E("Failed to send dbus signal(%s)", SIGNAL_PRE_WAKEUP); - - /* Notify resume state */ - device_notify(DEVICE_NOTIFIER_POWER_RESUME, NULL); - - return 0; -} - -static int suspend_action(int timeout) -{ - struct state *st; - - if ((get_pm_cur_state() != get_pm_old_state()) && - (get_pm_cur_state() != S_SLEEP)) - set_setting_pmstate(get_pm_cur_state()); - - /* TODO: set wakeup count */ - - /* sleep state : set system mode to SUSPEND */ - pm_suspend(); - - _I("system wakeup!!"); - - /* Resume !! */ - /* system waked up by devices */ - set_pm_old_state(get_pm_cur_state()); - set_pm_cur_state(S_LCDOFF); - st = state_st(get_pm_cur_state()); - - if (st->action) - st->action(0); - - return 0; -} - -static int suspend_trans(int evt) -{ - int ret; - struct state *st; - - ret = suspend_pre(NULL); - if (ret < 0) { - _E("S_SUSPEND pre-operation failed(%d)", ret); - return ret; - } - - /* state transition */ - set_pm_old_state(get_pm_cur_state()); - set_pm_cur_state(S_LCDOFF); - st = state_st(get_pm_cur_state()); - - if (st->action) - st->action(0); - - set_pm_old_state(get_pm_cur_state()); - set_pm_cur_state(S_SUSPEND); - st = state_st(get_pm_cur_state()); - - if (st->action) - st->action(0); - - ret = suspend_post(NULL); - if (ret < 0) - _E("S_SUSPEND post-operation failed(%d)", ret); - - return 0; -} - -static int poweroff_check(int curr, int next) -{ - /* DO NOT USE THIS FUNCTION */ - return 0; -} - -static int poweroff_action(int timeout) -{ - power_request_change_state(POWER_STATE_POWEROFF, 9000); - - return 0; -} - -static int poweroff_trans(int evt) -{ - struct state *st; - st = state_st(S_POWEROFF); - if (st->action) - st->action(0); - return 0; -} - -static int display_lock_changed(void *data) -{ - bool state = (bool)data; - - if (get_pm_cur_state() != S_STANDBY) - return 0; - - if (!state) - standby_go_next_state(NULL); - - return 0; -} - -static void set_tv_operations(enum state_t st, - char *name, - int (*check) (int curr, int next), - int (*trans) (int evt), - int (*action) (int timeout)) -{ - change_state_name(st, name); - change_state_check(st, check); - change_state_trans(st, trans); - change_state_action(st, action); -} - -static struct _tv_states { - enum state_t state; - char *name; - int (*check)(int curr, int next); - int (*trans)(int evt); - int (*action)(int timeout); -} tv_states[] = { - { S_LCDON, "S_LCDON", lcdon_check, lcdon_trans, lcdon_action }, - { S_LCDDIM, "S_LCDDIM", NULL, NULL, NULL }, - { S_LCDOFF, "S_LCDOFF", lcdoff_check, lcdoff_trans, lcdoff_action }, - { S_STANDBY, "S_STANDBY", standby_check, standby_trans, standby_action }, - { S_SUSPEND, "S_SUSPEND", suspend_check, suspend_trans, suspend_action }, - { S_POWEROFF, "S_POWEROFF", poweroff_check, poweroff_trans, poweroff_action }, -}; - -void state_tv_init(void) -{ - int i; - - _I("TV Profile !!"); - - for (i = 0 ; i < ARRAY_SIZE(tv_states) ; i++) - set_tv_operations(tv_states[i].state, - tv_states[i].name, - tv_states[i].check, - tv_states[i].trans, - tv_states[i].action); - - change_proc_change_state(tv_proc_change_state); - - register_notifier(DEVICE_NOTIFIER_DISPLAY_LOCK, display_lock_changed); -} - -void state_tv_deinit(void) -{ - unregister_notifier(DEVICE_NOTIFIER_DISPLAY_LOCK, display_lock_changed); -} - -static void __CONSTRUCTOR__ initialize(void) -{ - disp_plgn = get_var_display_plugin(); - if (!disp_plgn) - _E("Failed to get display plugin variable."); - - backlight_ops = get_var_backlight_ops(); - if (!backlight_ops) - _E("Failed to get backlight operator variable."); -} -- 2.7.4 From 0b807395978a911334d6204ba383d5ea5a244f5d Mon Sep 17 00:00:00 2001 From: Yunhee Seo Date: Thu, 10 Nov 2022 17:12:45 +0900 Subject: [PATCH 02/16] display: add getter/setter function for white balance Add a dbus/plugin getter and setter function of display white balance which controls RGB gain and offset. White balancing is adjusting standard point of white color, this because the light source is different for each device. gain value is a value to be multiplied for RGB value calculation. offset value is a value to be added for RGB value calculation. white balancing getter/setter dbus methods 1. Set white balance path: /Org/Tizen/System/DeviceD/Display interface: org.tizen.system.deviced.display member: SetWhiteBalance parameter: "(ii)", white balance enum type to be set, value to be set return: "(i)", 0 on success, negative on error. 2. Get white balance path: /Org/Tizen/System/DeviceD/Display interface: org.tizen.system.deviced.display member: GetWhiteBalance parameter: "(i)", white balance enum type to be get return: "(i)", value for that white balance type, negative on error. plugin implementation is referring to this enum type enum hal_display_white_balance { HAL_DISPLAY_WHITE_BALANCE_R_GAIN, HAL_DISPLAY_WHITE_BALANCE_G_GAIN, HAL_DISPLAY_WHITE_BALANCE_B_GAIN, HAL_DISPLAY_WHITE_BALANCE_R_OFFSET, HAL_DISPLAY_WHITE_BALANCE_G_OFFSET, HAL_DISPLAY_WHITE_BALANCE_B_OFFSET, }; Change-Id: I972bdb468806b442b221634a166645764c7c2ec9 Signed-off-by: Yunhee Seo --- plugins/iot-headed/display/core.c | 5 ++ plugins/iot-headed/display/device-interface.c | 87 +++++++++++++++++++++++++++ plugins/mobile/display/core.c | 5 ++ plugins/mobile/display/device-interface.c | 87 +++++++++++++++++++++++++++ plugins/tv/display/core.c | 5 ++ plugins/tv/display/device-interface.c | 87 +++++++++++++++++++++++++++ plugins/wearable/display/core.c | 5 ++ plugins/wearable/display/device-interface.c | 87 +++++++++++++++++++++++++++ src/display/device-interface.h | 7 +++ src/display/display-dbus.c | 53 ++++++++++++++++ 10 files changed, 428 insertions(+) diff --git a/plugins/iot-headed/display/core.c b/plugins/iot-headed/display/core.c index b6edf04..6bd21d0 100644 --- a/plugins/iot-headed/display/core.c +++ b/plugins/iot-headed/display/core.c @@ -92,6 +92,7 @@ extern void init_save_userlock(void); static struct display_plugin *disp_plgn; static struct _backlight_ops *backlight_ops; +static struct _display_white_balance_ops *display_white_balance_ops; static struct battery_plugin *battery_plgn; static int (*fp_get_charging_status) (int *val); static void (*power_saving_func) (int onoff); @@ -2350,6 +2351,10 @@ static void __CONSTRUCTOR__ initialize(void) if (!backlight_ops) _E("Failed to get backlight operator variable."); + display_white_balance_ops = get_var_display_white_balance_ops(); + if (!display_white_balance_ops) + _E("Failed to get display white balance operator variable."); + battery_plgn = get_var_battery_plugin(); if (!battery_plgn) _E("Failed to get battery plugin variable."); diff --git a/plugins/iot-headed/display/device-interface.c b/plugins/iot-headed/display/device-interface.c index bef99b0..f07018d 100644 --- a/plugins/iot-headed/display/device-interface.c +++ b/plugins/iot-headed/display/device-interface.c @@ -55,6 +55,11 @@ #define LCD_PHASED_DELAY 10000 /* microsecond */ #define DUMP_MODE_WAITING_TIME 600000 /* milisecond */ +#define MAX_WHITE_BALANCE_GAIN 2047 +#define MAX_WHITE_BALANCE_OFFSET 2047 +#define DEFAULT_WHITE_BALANCE_GAIN 1024 +#define DEFAULT_WHITE_BALANCE_OFFSET 0 + #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so" #define GESTURE_STR "gesture" @@ -69,6 +74,7 @@ #define FREEZER_VITAL_WAKEUP_CGROUP "/sys/fs/cgroup/freezer/vital_wakeup/freezer.state" static struct _backlight_ops backlight_ops; +static struct _display_white_balance_ops display_white_balance_ops; static bool custom_status; static int custom_brightness; static int force_brightness; @@ -83,6 +89,11 @@ inline struct _backlight_ops *get_var_backlight_ops(void) return &backlight_ops; } +inline struct _display_white_balance_ops *get_var_display_white_balance_ops(void) +{ + return &display_white_balance_ops; +} + bool display_dev_ready(void) { return display_dev_available; @@ -739,6 +750,77 @@ static void release_blink(void) release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL); } +static int set_white_balance(enum hal_display_white_balance white_balance_type, int value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + if (value > MAX_WHITE_BALANCE_GAIN) + value = DEFAULT_WHITE_BALANCE_GAIN; + break; + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + if (value > MAX_WHITE_BALANCE_OFFSET) + value = DEFAULT_WHITE_BALANCE_OFFSET; + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_set_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Set white balance is not supported."); + else + _E("Failed to set white balance value."); + } + + return ret; +} + +static int get_white_balance(enum hal_display_white_balance white_balance_type, int* value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_get_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Get white balance is not supported."); + else + _E("Failed to get white balance value."); + } + + return ret; +} + static void restore_brightness_func(void) { backlight_ops.set_brightness = set_brightness; @@ -777,6 +859,11 @@ static struct _backlight_ops backlight_ops = { .release_blink = release_blink, }; +static struct _display_white_balance_ops display_white_balance_ops = { + .set_white_balance = set_white_balance, + .get_white_balance = get_white_balance, +}; + int display_service_load(void) { int r; diff --git a/plugins/mobile/display/core.c b/plugins/mobile/display/core.c index 2e2d569..ddb7e58 100644 --- a/plugins/mobile/display/core.c +++ b/plugins/mobile/display/core.c @@ -93,6 +93,7 @@ extern void init_save_userlock(void); static struct display_plugin *disp_plgn; static struct _backlight_ops *backlight_ops; +static struct _display_white_balance_ops *display_white_balance_ops; static struct battery_plugin *battery_plgn; static int (*fp_get_charging_status) (int *val); @@ -2361,6 +2362,10 @@ static void __CONSTRUCTOR__ initialize(void) if (!backlight_ops) _E("Failed to get backlight operator variable."); + display_white_balance_ops = get_var_display_white_balance_ops(); + if (!display_white_balance_ops) + _E("Failed to get display white balance operator variable."); + battery_plgn = get_var_battery_plugin(); if (!battery_plgn) _E("Failed to get battery plugin variable."); diff --git a/plugins/mobile/display/device-interface.c b/plugins/mobile/display/device-interface.c index 28d4f1c..1c3c8dd 100644 --- a/plugins/mobile/display/device-interface.c +++ b/plugins/mobile/display/device-interface.c @@ -56,6 +56,11 @@ #define LCD_PHASED_DELAY 10000 /* microsecond */ #define DUMP_MODE_WAITING_TIME 600000 /* milisecond */ +#define MAX_WHITE_BALANCE_GAIN 2047 +#define MAX_WHITE_BALANCE_OFFSET 2047 +#define DEFAULT_WHITE_BALANCE_GAIN 1024 +#define DEFAULT_WHITE_BALANCE_OFFSET 0 + #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so" #define GESTURE_STR "gesture" @@ -68,6 +73,7 @@ #define UNKNOWN_STR "unknown" static struct _backlight_ops backlight_ops; +static struct _display_white_balance_ops display_white_balance_ops; static bool custom_status; static int custom_brightness; static int force_brightness; @@ -82,6 +88,11 @@ inline struct _backlight_ops *get_var_backlight_ops(void) return &backlight_ops; } +inline struct _display_white_balance_ops *get_var_display_white_balance_ops(void) +{ + return &display_white_balance_ops; +} + bool display_dev_ready(void) { return display_dev_available; @@ -738,6 +749,77 @@ static void release_blink(void) release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL); } +static int set_white_balance(enum hal_display_white_balance white_balance_type, int value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + if (value > MAX_WHITE_BALANCE_GAIN) + value = DEFAULT_WHITE_BALANCE_GAIN; + break; + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + if (value > MAX_WHITE_BALANCE_OFFSET) + value = DEFAULT_WHITE_BALANCE_OFFSET; + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_set_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Set white balance is not supported."); + else + _E("Failed to set white balance value."); + } + + return ret; +} + +static int get_white_balance(enum hal_display_white_balance white_balance_type, int* value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_get_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Get white balance is not supported."); + else + _E("Failed to get white balance value."); + } + + return ret; +} + static void restore_brightness_func(void) { backlight_ops.set_brightness = set_brightness; @@ -776,6 +858,11 @@ static struct _backlight_ops backlight_ops = { .release_blink = release_blink, }; +static struct _display_white_balance_ops display_white_balance_ops = { + .set_white_balance = set_white_balance, + .get_white_balance = get_white_balance, +}; + int display_service_load(void) { int r; diff --git a/plugins/tv/display/core.c b/plugins/tv/display/core.c index d8ba642..3dc8fc8 100644 --- a/plugins/tv/display/core.c +++ b/plugins/tv/display/core.c @@ -91,6 +91,7 @@ extern void init_save_userlock(void); static struct display_plugin *disp_plgn; static struct _backlight_ops *backlight_ops; +static struct _display_white_balance_ops *display_white_balance_ops; static struct battery_plugin *battery_plgn; static int (*fp_get_charging_status) (int *val); @@ -2347,6 +2348,10 @@ static void __CONSTRUCTOR__ initialize(void) if (!backlight_ops) _E("Failed to get backlight operator variable."); + display_white_balance_ops = get_var_display_white_balance_ops(); + if (!display_white_balance_ops) + _E("Failed to get display white balance operator variable."); + battery_plgn = get_var_battery_plugin(); if (!battery_plgn) _E("Failed to get battery plugin variable."); diff --git a/plugins/tv/display/device-interface.c b/plugins/tv/display/device-interface.c index d377ac8..a5500ca 100644 --- a/plugins/tv/display/device-interface.c +++ b/plugins/tv/display/device-interface.c @@ -55,6 +55,11 @@ #define LCD_PHASED_DELAY 10000 /* microsecond */ #define DUMP_MODE_WAITING_TIME 600000 /* milisecond */ +#define MAX_WHITE_BALANCE_GAIN 2047 +#define MAX_WHITE_BALANCE_OFFSET 2047 +#define DEFAULT_WHITE_BALANCE_GAIN 1024 +#define DEFAULT_WHITE_BALANCE_OFFSET 0 + #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so" #define GESTURE_STR "gesture" @@ -69,6 +74,7 @@ #define FREEZER_VITAL_WAKEUP_CGROUP "/sys/fs/cgroup/freezer/vital_wakeup/freezer.state" static struct _backlight_ops backlight_ops; +static struct _display_white_balance_ops display_white_balance_ops; static bool custom_status; static int custom_brightness; static int force_brightness; @@ -83,6 +89,11 @@ inline struct _backlight_ops *get_var_backlight_ops(void) return &backlight_ops; } +inline struct _display_white_balance_ops *get_var_display_white_balance_ops(void) +{ + return &display_white_balance_ops; +} + bool display_dev_ready(void) { return display_dev_available; @@ -739,6 +750,77 @@ static void release_blink(void) release_timer = g_timeout_add(DUMP_MODE_WAITING_TIME, release_blink_cb, NULL); } +static int set_white_balance(enum hal_display_white_balance white_balance_type, int value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + if (value > MAX_WHITE_BALANCE_GAIN) + value = DEFAULT_WHITE_BALANCE_GAIN; + break; + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + if (value > MAX_WHITE_BALANCE_OFFSET) + value = DEFAULT_WHITE_BALANCE_OFFSET; + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_set_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Set white balance is not supported."); + else + _E("Failed to set white balance value."); + } + + return ret; +} + +static int get_white_balance(enum hal_display_white_balance white_balance_type, int* value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_get_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Get white balance is not supported."); + else + _E("Failed to get white balance value."); + } + + return ret; +} + static void restore_brightness_func(void) { backlight_ops.set_brightness = set_brightness; @@ -777,6 +859,11 @@ static struct _backlight_ops backlight_ops = { .release_blink = release_blink, }; +static struct _display_white_balance_ops display_white_balance_ops = { + .set_white_balance = set_white_balance, + .get_white_balance = get_white_balance, +}; + int display_service_load(void) { int r; diff --git a/plugins/wearable/display/core.c b/plugins/wearable/display/core.c index 1506958..56275ad 100644 --- a/plugins/wearable/display/core.c +++ b/plugins/wearable/display/core.c @@ -99,6 +99,7 @@ extern void init_save_userlock(void); static struct display_plugin *disp_plgn; static struct _backlight_ops *backlight_ops; +static struct _display_white_balance_ops *display_white_balance_ops; static struct battery_plugin *battery_plgn; static int (*fp_get_charging_status) (int *val); @@ -2683,6 +2684,10 @@ static void __CONSTRUCTOR__ initialize(void) if (!backlight_ops) _E("Failed to get backlight operator variable."); + display_white_balance_ops = get_var_display_white_balance_ops(); + if (!display_white_balance_ops) + _E("Failed to get display white balance operator variable."); + battery_plgn = get_var_battery_plugin(); if (!battery_plgn) _E("Failed to get battery plugin variable."); diff --git a/plugins/wearable/display/device-interface.c b/plugins/wearable/display/device-interface.c index 8ff62de..cb77833 100644 --- a/plugins/wearable/display/device-interface.c +++ b/plugins/wearable/display/device-interface.c @@ -58,6 +58,11 @@ #define LCD_PHASED_DELAY 10000 /* microsecond */ #define DUMP_MODE_WAITING_TIME 600000 /* milisecond */ +#define MAX_WHITE_BALANCE_GAIN 2047 +#define MAX_WHITE_BALANCE_OFFSET 2047 +#define DEFAULT_WHITE_BALANCE_GAIN 1024 +#define DEFAULT_WHITE_BALANCE_OFFSET 0 + #define DISPLAY_HAL_LIB_PATH "/usr/lib/libdisplay-hal.so" #define GESTURE_STR "gesture" @@ -74,6 +79,7 @@ static struct _backlight_ops backlight_ops; +static struct _display_white_balance_ops display_white_balance_ops; static struct battery_plugin *battery_plgn; static bool custom_status; static int custom_brightness; @@ -95,6 +101,11 @@ inline struct _backlight_ops *get_var_backlight_ops(void) return &backlight_ops; } +inline struct _display_white_balance_ops *get_var_display_white_balance_ops(void) +{ + return &display_white_balance_ops; +} + bool display_dev_ready(void) { return display_dev_available; @@ -811,6 +822,77 @@ static void restore_brightness_func(void) backlight_ops.transit_brt = change_brightness; } +static int set_white_balance(enum hal_display_white_balance white_balance_type, int value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + if (value > MAX_WHITE_BALANCE_GAIN) + value = DEFAULT_WHITE_BALANCE_GAIN; + break; + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + if (value > MAX_WHITE_BALANCE_OFFSET) + value = DEFAULT_WHITE_BALANCE_OFFSET; + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_set_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Set white balance is not supported."); + else + _E("Failed to set white balance value."); + } + + return ret; +} + +static int get_white_balance(enum hal_display_white_balance white_balance_type, int* value) +{ + int ret = 0; + + if (!display_dev_available) { + _E("There is no display device."); + return -ENOENT; + } + + switch (white_balance_type) { + case HAL_DISPLAY_WHITE_BALANCE_R_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_G_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_B_GAIN: + case HAL_DISPLAY_WHITE_BALANCE_R_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_G_OFFSET: + case HAL_DISPLAY_WHITE_BALANCE_B_OFFSET: + break; + default: + _E("Unknown white balance type"); + return -EINVAL; + } + + ret = hal_device_display_get_white_balance(white_balance_type, value); + if (ret < 0) { + if (ret == -ENODEV) + _E("Get white balance is not supported."); + else + _E("Failed to get white balance value."); + } + + return ret; +} + static struct _backlight_ops backlight_ops = { .off = backlight_off, .dim = backlight_dim, @@ -844,6 +926,11 @@ static struct _backlight_ops backlight_ops = { .get_brightness_raw = get_brightness, /* always fetch brightness from node even LBM mode */ }; +static struct _display_white_balance_ops display_white_balance_ops = { + .set_white_balance = set_white_balance, + .get_white_balance = get_white_balance, +}; + int display_service_load(void) { int r; diff --git a/src/display/device-interface.h b/src/display/device-interface.h index 759ff50..56b41e4 100644 --- a/src/display/device-interface.h +++ b/src/display/device-interface.h @@ -94,6 +94,13 @@ struct _backlight_ops { struct _backlight_ops *get_var_backlight_ops(void); +struct _display_white_balance_ops { + int (*set_white_balance)(enum hal_display_white_balance white_balance_type, int value); + int (*get_white_balance)(enum hal_display_white_balance white_balance_type, int* out_val); +}; + +struct _display_white_balance_ops *get_var_display_white_balance_ops(void); + enum dpms_state { DPMS_ON, /* In use */ DPMS_STANDBY, /* Blanked, low power */ diff --git a/src/display/display-dbus.c b/src/display/display-dbus.c index 9b73ba9..197260a 100644 --- a/src/display/display-dbus.c +++ b/src/display/display-dbus.c @@ -71,6 +71,7 @@ static struct display_plugin *disp_plgn; static struct _backlight_ops *backlight_ops; +static struct _display_white_balance_ops *display_white_balance_ops; static struct display_config *display_conf; static GVariant *dbus_start(GDBusConnection *conn, @@ -1198,6 +1199,52 @@ static GVariant *dbus_getbrightnessinfo(GDBusConnection *conn, return g_variant_new("(ii)", default_brightness, current_brightness); } +static GVariant *dbus_setwhitebalance(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int white_balance_type, value; + int ret = 0, ret_val; + pid_t pid; + + g_variant_get(param, "(ii)", &white_balance_type, &value); + + ret_val = display_white_balance_ops->set_white_balance(white_balance_type, value); + if (ret_val < 0) { + _E("Failed to set white balance"); + ret = -EPERM; + } + + pid = gdbus_connection_get_sender_pid(conn, sender); + _I("Set white balance pid=%d white balance type=%d value=%d", pid, white_balance_type, value); + + return g_variant_new("(i)", ret); +} + +static GVariant *dbus_getwhitebalance(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int white_balance_type; + int ret = 0, ret_val; + pid_t pid; + + g_variant_get(param, "(i)", &white_balance_type); + + ret = display_white_balance_ops->get_white_balance(white_balance_type, &ret_val); + if (ret < 0) { + _E("Failed to get white balance"); + ret = -EPERM; + } + else + ret = ret_val; + + pid = gdbus_connection_get_sender_pid(conn, sender); + _I("Get white balance pid=%d white balance type=%d", pid, white_balance_type); + + return g_variant_new("(i)", ret); +} + static const dbus_method_s dbus_methods[] = { { "start", NULL, NULL, dbus_start }, { "stop", NULL, NULL, dbus_stop }, @@ -1235,6 +1282,8 @@ static const dbus_method_s dbus_methods[] = { { "LockTimeoutInput", "si", "i", dbus_locktimeout_input }, { "DimStayControl", "i", "i", dbus_dimstay_control }, { "GetBrightnessInfo", NULL, "ii", dbus_getbrightnessinfo}, + { "SetWhiteBalance", "ii", "i", dbus_setwhitebalance}, + { "GetWhiteBalance", "i", "i", dbus_getwhitebalance}, /* Add methods here */ }; @@ -1363,6 +1412,10 @@ static void __CONSTRUCTOR__ initialize(void) if (!backlight_ops) _E("Failed to get backlight operator variable."); + display_white_balance_ops = get_var_display_white_balance_ops(); + if (!display_white_balance_ops) + _E("Failed to get display white balance operator variable."); + display_conf = get_var_display_config(); if (!display_conf) _E("Failed to get display configuration variable."); -- 2.7.4 From 7d138e274e8c62aa49fc31615af98eea83d0f929 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 22 Nov 2022 19:52:02 +0900 Subject: [PATCH 03/16] power: check operation is null The iot-headless profile has been changed to have display module. - display: add dummy display for iot-headless (1985b78991d1fe925b827ded4fdae58d1b4e1d7a) Prevent crash on accessing not existing operation. Change-Id: I601e4cb8412423ed8ecca9d9c022b366e039690e Signed-off-by: Youngjae Cho --- src/power/power-off.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/power/power-off.c b/src/power/power-off.c index 89f9b19..91c8e52 100644 --- a/src/power/power-off.c +++ b/src/power/power-off.c @@ -88,7 +88,8 @@ static void disable_display(void) { const struct device_ops *display_device_ops = NULL; FIND_DEVICE_VOID(display_device_ops, "display"); - display_device_ops->stop(NORMAL_MODE); + if (display_device_ops->stop) + display_device_ops->stop(NORMAL_MODE); } static int disable_systemd_journald(void) -- 2.7.4 From 0850fa700466f27ca2ddcf7d721700859a3107be Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 22 Nov 2022 17:27:36 +0900 Subject: [PATCH 04/16] power: revamp power module - Integrate power-state-wait.c into power.c - Transition is not preemptive anymore : Previosuly, transitions can cancel and intercept ongoing one. But it has changed to be enqueued if there is ongoing transition. It will be handled after handling all the other pending transitions. Change-Id: Ifbe92098ea4c69f09f744609405dfb1e5e67f75f Signed-off-by: Youngjae Cho --- src/power/power-dbus.c | 1 - src/power/power-event-lock.c | 17 +- src/power/power-event-lock.h | 16 ++ src/power/power-off.c | 23 +- src/power/power-off.h | 2 +- src/power/power-state-wait.c | 248 ----------------- src/power/power-state-wait.h | 33 --- src/power/power.c | 619 ++++++++++++++++++++++++++++++++----------- src/power/power.h | 3 + 9 files changed, 493 insertions(+), 469 deletions(-) delete mode 100644 src/power/power-state-wait.c delete mode 100644 src/power/power-state-wait.h diff --git a/src/power/power-dbus.c b/src/power/power-dbus.c index a0c6cfa..89162cc 100644 --- a/src/power/power-dbus.c +++ b/src/power/power-dbus.c @@ -32,7 +32,6 @@ #include "power-suspend.h" #include "power.h" -#include "power-state-wait.h" #ifndef PROCESS_CHECK_TIMEOUT #define PROCESS_CHECK_TIMEOUT 600000 /* milisecond, 10 minute */ diff --git a/src/power/power-event-lock.c b/src/power/power-event-lock.c index 70bb44c..cca7921 100644 --- a/src/power/power-event-lock.c +++ b/src/power/power-event-lock.c @@ -35,23 +35,10 @@ * of an event from going to sleep regardless of the power state. */ #define EVENT_LOCK "eventlock" -enum eventlock_type { - EL_MIN, - /* On receiving key event, expands EL_KEY to EL_KEY_* according to keycode */ - EL_KEY, - EL_KEY_POWER = EL_KEY, - EL_KEY_BLUETOOTH, - - EL_CHARGER, - EL_EVENT_ACTION, - /* add eventlock type here */ - EL_MAX, -}; - static struct dd_bitmap *eventlock; static int notifier_id[EL_MAX][2]; -static void event_wake_lock(enum eventlock_type type) +void event_wake_lock(enum eventlock_type type) { int setcount; @@ -69,7 +56,7 @@ static void event_wake_lock(enum eventlock_type type) } } -static void event_wake_unlock(enum eventlock_type type) +void event_wake_unlock(enum eventlock_type type) { int setcount; diff --git a/src/power/power-event-lock.h b/src/power/power-event-lock.h index e2943dd..e054ec1 100644 --- a/src/power/power-event-lock.h +++ b/src/power/power-event-lock.h @@ -19,7 +19,23 @@ #ifndef __POWER_EVENT_LOCK_H__ #define __POWER_EVENT_LOCK_H__ +enum eventlock_type { + EL_MIN, + /* On receiving key event, expands EL_KEY to EL_KEY_* according to keycode */ + EL_KEY, + EL_KEY_POWER = EL_KEY, + EL_KEY_BLUETOOTH, + + EL_CHARGER, + EL_EVENT_ACTION, + EL_POWER_TRANSITION_STATE, + /* add eventlock type here */ + EL_MAX, +}; + void power_event_lock_init(void); +void event_wake_lock(enum eventlock_type type); +void event_wake_unlock(enum eventlock_type type); #endif //__POWER_EVENT_LOCK_H__ diff --git a/src/power/power-off.c b/src/power/power-off.c index 91c8e52..2cf17c6 100644 --- a/src/power/power-off.c +++ b/src/power/power-off.c @@ -205,24 +205,21 @@ int poweroff_check_revived(void) return POWER_STATE_NORMAL; } -static void mark_poweroff_option(const struct trans_info *ti) +static void mark_poweroff_option(uint64_t state, const char *option) { int fd; ssize_t len; const char *optpath; - const char *option; - if (ti->next == POWER_STATE_POWEROFF) + if (state == POWER_STATE_POWEROFF) optpath = POWEROFF_OPTPATH_POWEROFF; - else if (ti->next == POWER_STATE_REBOOT) + else if (state == POWER_STATE_REBOOT) optpath = POWEROFF_OPTPATH_REBOOT; - else if (ti->next == POWER_STATE_EXIT) + else if (state == POWER_STATE_EXIT) optpath = POWEROFF_OPTPATH_EXIT; else return; - option = (char *) ti->data; - fd = open(optpath, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { _E("Failed to create '%s'.", optpath); @@ -294,18 +291,18 @@ static void system_shutdown_send_system_event(void) bundle_free(b); } -void poweroff_prepare(const struct trans_info *ti) +void poweroff_prepare(uint64_t state, void *option) { int vconf = VCONFKEY_SYSMAN_POWER_OFF_NONE; - if (!is_poweroff_state(ti->next)) + if (!is_poweroff_state(state)) return; - mark_poweroff_option(ti); + mark_poweroff_option(state, option); - if (ti->next == POWER_STATE_POWEROFF) + if (state == POWER_STATE_POWEROFF) vconf = VCONFKEY_SYSMAN_POWER_OFF_DIRECT; - else if (ti->next == POWER_STATE_REBOOT) + else if (state == POWER_STATE_REBOOT) vconf = VCONFKEY_SYSMAN_POWER_OFF_RESTART; vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, vconf); @@ -316,7 +313,7 @@ void poweroff_prepare(const struct trans_info *ti) system_shutdown_send_system_event(); /* Skip running animation if it is silent reboot */ - if (ti->data && strncmp(ti->data, "silent", sizeof("silent")) == 0) + if (option && strncmp(option, "silent", sizeof("silent")) == 0) return; poweroff_start_animation(); diff --git a/src/power/power-off.h b/src/power/power-off.h index a3c3466..7e961f7 100644 --- a/src/power/power-off.h +++ b/src/power/power-off.h @@ -34,7 +34,7 @@ void power_off_init(void); int poweroff_check_revived(void); void poweroff_request_shutdown(int state); -void poweroff_prepare(const struct trans_info *ti); +void poweroff_prepare(uint64_t state, void *option); void poweroff_main(void *udata); #endif /* __DEVICED_POWER_OFF_H__ */ diff --git a/src/power/power-state-wait.c b/src/power/power-state-wait.c deleted file mode 100644 index a1c3f65..0000000 --- a/src/power/power-state-wait.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * deviced - * - * Copyright (c) 2022 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 "shared/log.h" -#include "shared/device-notifier.h" -#include "shared/common.h" - -#include "power.h" -#include "power-state-wait.h" - -#define POWER_CONF_FILE "/etc/deviced/power.conf" -#define MAX_WAIT_SECOND 5 /* second */ - -static int max_wait_timeout = 5; /* second */ - -struct proc_info { - pid_t pid; - char comm[128]; - guint64 state_bitmap; - int killed; -}; - -struct change_state_wait { - struct proc_info *pi; - guint64 id; - int state; -}; - -static GList *proc_list; -static GList *waiting_list; -static int max_wait_timer; -static void (*__change_state_wait_done) (void *); -static void *udata; -static int waiting_state = POWER_STATE_START; - -static void change_state_wait_done(void) -{ - _D("%s wait done", state_name(waiting_state)); - - if (max_wait_timer) { - g_source_remove(max_wait_timer); - max_wait_timer = 0; - } - - if (__change_state_wait_done) { - __change_state_wait_done(udata); - } -} - -static gboolean max_wait_expired_cb(void *data) -{ - struct change_state_wait *csw; - struct proc_info *pi; - GList *elem, *elem_next; - - max_wait_timer = 0; - - SYS_G_LIST_FOREACH_SAFE(waiting_list, elem, elem_next, csw) { - if (kill(csw->pi->pid, 0) != 0) - csw->pi->killed = 1; - else - _E("pid=%d(%s) hasn't confirmed id=%"PRIu64"(%s)", csw->pi->pid, csw->pi->comm, csw->id, state_name(csw->state)); - waiting_list = g_list_remove_link(waiting_list, elem); - g_list_free(elem); - free(csw); - } - - SYS_G_LIST_FOREACH_SAFE(proc_list, elem, elem_next, pi) { - if (pi->killed) { - _D("Clean up not existing pid=%d(%s)", pi->pid, pi->comm); - proc_list = g_list_remove_link(proc_list, elem); - g_list_free(elem); - free(pi); - } - } - - change_state_wait_done(); - - return G_SOURCE_REMOVE; -} - -int add_change_state_wait(pid_t pid, guint64 state) -{ - struct proc_info *pi; - GList *elem; - - SYS_G_LIST_FOREACH(proc_list, elem, pi) { - if (pi->pid == pid) { - pi->state_bitmap |= state; - _D("pid=%d(%s) updated csw for %#"PRIx64, pid, pi->comm, state); - return 0; - } - } - - pi = calloc(1, sizeof(struct proc_info)); - if (!pi) - return -ENOMEM; - - pi->pid = pid; - pi->state_bitmap = state; - get_command(pid, pi->comm, sizeof(pi->comm)); - SYS_G_LIST_APPEND(proc_list, pi); - - _D("pid=%d(%s) added csw for %#"PRIx64, pid, pi->comm, state); - - return 0; -} - -void remove_change_state_wait(pid_t pid, guint64 state) -{ - struct proc_info *pi; - GList *elem, *elem_next; - - _D("pid=%d removed csw for %#"PRIx64, pid, state); - - SYS_G_LIST_FOREACH_SAFE(proc_list, elem, elem_next, pi) { - if (pi->pid == pid) { - pi->state_bitmap &= ~state; - if (pi->state_bitmap == 0) { - proc_list = g_list_remove_link(proc_list, elem); - g_list_free(elem); - free(pi); - } - } - } -} - -int confirm_change_state_wait(pid_t pid, guint64 id) -{ - struct change_state_wait *csw; - GList *elem, *elem_next; - - SYS_G_LIST_FOREACH_SAFE(waiting_list, elem, elem_next, csw) { - if (csw->pi->pid == pid && csw->id == id) { - _D("pid=%d(%s) confirmed id=%"PRIu64"(%s)", csw->pi->pid, csw->pi->comm, csw->id, state_name(csw->state)); - waiting_list = g_list_remove_link(waiting_list, elem); - g_list_free(elem); - free(csw); - - if (SYS_G_LIST_LENGTH(waiting_list) == 0) { - change_state_wait_done(); - return 0; - } - } - } - - return 0; -} - -int update_change_state_wait(guint64 id, const struct trans_info *ti, change_state_wait_done_cb callback, void *user_data) -{ - struct proc_info *pi; - struct change_state_wait *csw; - GList *elem, *elem_next; - static int n_waiting = 0; - - // initialize timer - if (max_wait_timer) { - g_source_remove(max_wait_timer); - max_wait_timer = 0; - } - - if (is_poweroff_state(waiting_state)) { - _W("No need to wait if poweroff had been triggered."); - return n_waiting; - } - - // we are waiting for confirm of transition to the next state - waiting_state = ti->next; - - _D("%s wait is triggered, id=%"PRIu64, state_name(waiting_state), id); - - // cancel all ongoing csw that is not a waiting for the next state - SYS_G_LIST_FOREACH_SAFE(waiting_list, elem, elem_next, csw) { - if ((csw->state & waiting_state) == 0) { - waiting_list = g_list_remove_link(waiting_list, elem); - g_list_free(elem); - _D("Cancel waiting: pid=%d(%s) for id=%"PRIu64"(%s)", csw->pi->pid, csw->pi->comm, csw->id, state_name(csw->state)); - free(csw); - } - } - - // add wait list - SYS_G_LIST_FOREACH(proc_list, elem, pi) { - if (pi->state_bitmap & waiting_state) { - csw = calloc(1, sizeof(struct change_state_wait)); - if (!csw) - continue; - - csw->pi = pi; - csw->id = id; - csw->state = waiting_state; - SYS_G_LIST_APPEND(waiting_list, csw); - } - } - - n_waiting = SYS_G_LIST_LENGTH(waiting_list); - if (n_waiting == 0) { - _D("There were no csw requests for %s, skip waiting", state_name(waiting_state)); - __change_state_wait_done = NULL; - return 0; - } - - __change_state_wait_done = callback; - udata = user_data; - - _D("The number of pending wait confirm=%d", n_waiting); - max_wait_timer = g_timeout_add_seconds(max_wait_timeout, max_wait_expired_cb, NULL); - - return n_waiting; -} - -static int load_max_wait_timeout(struct parse_result *result, void *user_data) -{ - if (MATCH(result->section, "PowerState") - && MATCH(result->name, "ChangeStateMaxWaitSecond")) - max_wait_timeout = atoi(result->value); - - return 0; -} - -void power_state_wait_init(void) -{ - config_parse(POWER_CONF_FILE, load_max_wait_timeout, NULL); - - CRITICAL_LOG("Change state max wait timeout=%ds", max_wait_timeout); -} diff --git a/src/power/power-state-wait.h b/src/power/power-state-wait.h deleted file mode 100644 index 3a2660f..0000000 --- a/src/power/power-state-wait.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * deviced - * - * Copyright (c) 2022 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 __POWER_STATE_WAIT_H__ -#define __POWER_STATE_WAIT_H__ - -#include -#include "power.h" - -typedef void (*change_state_wait_done_cb) (void *); - -int add_change_state_wait(pid_t pid, guint64 state); -void remove_change_state_wait(pid_t pid, guint64 state); -int confirm_change_state_wait(pid_t pid, guint64 id); -int update_change_state_wait(guint64 id, const struct trans_info *ti, change_state_wait_done_cb cb, void *user_data); -void power_state_wait_init(void); - -#endif //__POWER_STATE_WAIT_H__ diff --git a/src/power/power.c b/src/power/power.c index 519a126..0ae9be6 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -27,32 +28,210 @@ #include "shared/devices.h" #include "shared/device-notifier.h" #include "shared/log.h" +#include "shared/common.h" #include "power.h" #include "power-suspend.h" #include "power-dbus.h" #include "power-boot.h" #include "power-off.h" -#include "power-state-wait.h" #include "power-event-lock.h" -#define EVENT_TYPE_SLEEP 0 -#define EVENT_TYPE_WAKEUP 1 +#define POWER_CONF_FILE "/etc/deviced/power.conf" +#define POWER_STATE_INDEX(state) ((state) ? 63 - __builtin_clzll(state) : 0) +#define DEFAULT_MAX_WAIT_SECOND 5 /* second */ +#define MAX_DESC_LEN 256 static int delayed_init_done = 0; -static uint64_t state_transition_counter = 0; -static uint64_t current = POWER_STATE_START; +static uint64_t current = POWER_STATE_START; /* current power state */ +static int max_wait_timeout = DEFAULT_MAX_WAIT_SECOND; +static GQueue *transition_queue; +static struct { + int id; + int ongoing; + struct trans_info ti; + GList *waitings; + int max_wait_timer; +} transition_context; + +struct proc_info { + pid_t pid; + char comm[128]; + guint64 state_bitmap; +}; +static GList *proc_list; -/* hold trans_info until delayed_init_done */ -static GList *deferred_transition_list; +struct change_state_wait { + struct proc_info *pi; + guint64 id; + int state; +}; -static int power_transition_state(void *data); +static int transition_request_callback(void *data); +static void prepare_transition(const struct trans_info *ti); +static void action_transition(void); + +static void power_action_normal(void *data); +static void power_action_sleep(void *data); +static void power_action_poweroff(void *data); +static void (*const action_on_state[POWER_STATE_MAX_INDEX]) (void *) = { + [POWER_STATE_NORMAL_INDEX] = power_action_normal, + [POWER_STATE_SLEEP_INDEX] = power_action_sleep, + [POWER_STATE_POWEROFF_INDEX] = power_action_poweroff, + [POWER_STATE_REBOOT_INDEX] = power_action_poweroff, + [POWER_STATE_EXIT_INDEX] = power_action_poweroff, +}; uint64_t power_get_state(void) { return current; } -static void power_wake_unlock(void *udata) +static void cleanup_waiting_list(gpointer data) +{ + struct change_state_wait *csw = (struct change_state_wait *) data; + + _E("%s(pid=%d) hasn't confirmed id=%"PRIu64"(%s)", csw->pi->comm, csw->pi->pid, csw->id, state_name(csw->state)); + + if (kill(csw->pi->pid, 0) != 0) { + _E("cleanup not existing process: %s(pid=%d)", csw->pi->comm, csw->pi->pid); + proc_list = g_list_remove(proc_list, csw->pi); + free(csw->pi); + } + + free(csw); +} + +static gboolean max_wait_expired_cb(void *data) +{ + transition_context.max_wait_timer = 0; + + g_list_free_full(g_steal_pointer(&transition_context.waitings), cleanup_waiting_list); + + action_transition(); + + return G_SOURCE_REMOVE; +} + +static gint find_pi_by_pid(gconstpointer data, gconstpointer udata) +{ + const struct proc_info *pi = (const struct proc_info *) data; + const pid_t pid = *(const pid_t *) udata; + + if (pi->pid == pid) + return 0; + + return -1; +} + +int add_change_state_wait(pid_t pid, guint64 state) +{ + struct proc_info *pi = NULL; + GList *l = NULL; + + l = g_list_find_custom(proc_list, &pid, find_pi_by_pid); + if (l && l->data) { + pi = l->data; + pi->state_bitmap |= state; + _D("pid=%d(%s) updated csw for %#"PRIx64, pi->pid, pi->comm, state); + return 0; + } + + pi = calloc(1, sizeof(struct proc_info)); + if (!pi) + return -ENOMEM; + + pi->pid = pid; + pi->state_bitmap = state; + get_command(pid, pi->comm, sizeof(pi->comm)); + proc_list = g_list_append(proc_list, pi); + + _D("pid=%d(%s) added csw for %#"PRIx64, pid, pi->comm, state); + + return 0; +} + +void remove_change_state_wait(pid_t pid, guint64 state) +{ + struct proc_info *pi = NULL; + GList *l = NULL; + + l = g_list_find_custom(proc_list, &pid, find_pi_by_pid); + if (!l) + return; + + if (!l->data) + return; + + pi = l->data; + + _D("pid=%d(%s) removed csw for %#"PRIx64, pi->pid, pi->comm, state); + + pi->state_bitmap &= ~state; + if (pi->state_bitmap == 0) { + proc_list = g_list_remove_link(proc_list, l); + free(g_steal_pointer(&l->data)); + g_list_free(l); + } +} + +static gint find_csw_by_pid_id(gconstpointer data, gconstpointer udata) +{ + const struct change_state_wait *csw = (const struct change_state_wait *) data; + const struct change_state_wait *target = (const struct change_state_wait *) udata; + + if (csw->pi->pid == target->pi->pid && csw->id == target->id) + return 0; + + return -1; +} + +int confirm_change_state_wait(pid_t pid, guint64 id) +{ + struct proc_info target_pi = { .pid = pid }; + struct change_state_wait target_csw = { .pi = &target_pi, .id = id }; + struct change_state_wait *csw = NULL; + GList *l = NULL; + + l = g_list_find_custom(transition_context.waitings, &target_csw, find_csw_by_pid_id); + if (!l) + return 0; + + if (!l->data) + return 0; + + csw = l->data; + _D("pid=%d(%s) confirmed id=%"PRIu64"(%s)", csw->pi->pid, csw->pi->comm, csw->id, state_name(csw->state)); + + transition_context.waitings = g_list_remove_link(transition_context.waitings, l); + free(g_steal_pointer(&l->data)); + g_list_free(l); + + // continue waiting + if (g_list_length(transition_context.waitings) != 0) + return 0; + + // the last csw is cleared + g_source_remove(transition_context.max_wait_timer); + transition_context.max_wait_timer = 0; + + action_transition(); + + return 0; +} + +static int alloc_unique_id(void) +{ + static int id = 0; + + return ++id; +} + +static void power_action_normal(void *udata) +{ + power_acquire_wakelock(); +} + +static void power_action_sleep(void *udata) { /* for POWER_STATE_NORMAL, POWER_STATE_POWEROFF, do not wake unlock */ if (current != POWER_STATE_SLEEP) { @@ -63,254 +242,378 @@ static void power_wake_unlock(void *udata) power_release_wakelock(); } -static void broadcast_transition_info(const struct trans_info *ti) +static void power_action_poweroff(void *data) +{ + // do not transition anymore after poweroff + unregister_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, transition_request_callback); + + poweroff_prepare(current, data); + poweroff_main((void *)(intptr_t) current); +} + +static void broadcast_transition_info(void) { const char *signame; - if (ti->next == POWER_STATE_START) - signame = SIGNAME_CHANGE_STATE_TO_START; - else if (ti->next == POWER_STATE_NORMAL) - signame = SIGNAME_CHANGE_STATE_TO_NORMAL; - else if (ti->next == POWER_STATE_SLEEP) - signame = SIGNAME_CHANGE_STATE_TO_SLEEP; - else if (ti->next == POWER_STATE_POWEROFF) - signame = SIGNAME_CHANGE_STATE_TO_POWEROFF; - else if (ti->next == POWER_STATE_REBOOT) - signame = SIGNAME_CHANGE_STATE_TO_REBOOT; - else if (ti->next == POWER_STATE_EXIT) - signame = SIGNAME_CHANGE_STATE_TO_EXIT; + if (transition_context.ti.next == POWER_STATE_START) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START; + else if (transition_context.ti.next == POWER_STATE_NORMAL) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL; + else if (transition_context.ti.next == POWER_STATE_SLEEP) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP; + else if (transition_context.ti.next == POWER_STATE_POWEROFF) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF; + else if (transition_context.ti.next == POWER_STATE_REBOOT) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT; + else if (transition_context.ti.next == POWER_STATE_EXIT) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT; else return; gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER, signame, - g_variant_new("(ttti)", ti->curr, ti->next, state_transition_counter, ti->reason)); + g_variant_new("(ttti)", + transition_context.ti.curr, + transition_context.ti.next, + transition_context.id, + transition_context.ti.reason)); } -static void power_transition_start_to_normal(const struct trans_info *ti) +static uint64_t available_starting_state(void) { - current = POWER_STATE_NORMAL; + struct trans_info *ti = NULL; - power_acquire_wakelock(); - broadcast_transition_info(ti); + // If there is no ongoing transition, the available state is the current state. + if (!transition_context.ongoing) + return current; + + // If there is ongoing transition and there are also some pending transitions, + // the available state is the last state of pending transitions. + // Otherwise, if there is ongoing transition but there are no pending transitions, + // the available state is the destination of ongoing transition. + return (ti = g_queue_peek_head(transition_queue)) ? ti->next : transition_context.ti.next; } -static void power_transition_start_to_sleep(const struct trans_info *ti) +static int dequeue_transition(struct trans_info *ti) { - int waiting; + struct trans_info *tail = NULL; - current = POWER_STATE_SLEEP; + if (!ti) + return -1; - power_acquire_wakelock(); - broadcast_transition_info(ti); - waiting = update_change_state_wait(state_transition_counter, ti, power_wake_unlock, NULL); - if (waiting > 0) { - _D("Defer wake unlock."); - return; - } + tail = g_queue_pop_tail(transition_queue); + if (!tail) + return -1; + + *ti = (struct trans_info) { + .curr = tail->curr, + .next = tail->next, + .reason = tail->reason, + .data = tail->data, + }; + + free(tail); - power_wake_unlock(NULL); + return 0; } -static void power_transition_normal_to_normal(const struct trans_info *ti) +static void enqueue_transition(const struct trans_info *ti) { - broadcast_transition_info(ti); - update_change_state_wait(state_transition_counter, ti, NULL, NULL); + struct trans_info *ti_new = NULL; + + if (!ti) + return; + + ti_new = calloc(1, sizeof(struct trans_info)); + if (!ti_new) + return; + + g_queue_push_head(transition_queue, memcpy(ti_new, ti, sizeof(struct trans_info))); } -static void power_transition_normal_to_sleep(const struct trans_info *ti) +static void init_waiting_list(gpointer data, gpointer udata) { - int waiting; + uint64_t waiting_state; + struct proc_info *pi = (struct proc_info *) data; + struct change_state_wait *csw = NULL; - current = POWER_STATE_SLEEP; + waiting_state = transition_context.ti.next; - broadcast_transition_info(ti); - waiting = update_change_state_wait(state_transition_counter, ti, power_wake_unlock, NULL); - if (waiting > 0) { - _D("Defer wake unlock."); + if ((pi->state_bitmap & waiting_state) == 0) return; - } - power_wake_unlock(NULL); + csw = calloc(1, sizeof(struct change_state_wait)); + if (!csw) + return; + + *csw = (struct change_state_wait) { + .pi = pi, + .id = transition_context.id, + .state = waiting_state, + }; + + *(int *) udata += 1; + + transition_context.waitings = g_list_append(transition_context.waitings, csw); } -static void power_transition_sleep_to_normal(const struct trans_info *ti) +static char *state_abbr_name(uint64_t state) { - current = POWER_STATE_NORMAL; + if (state == POWER_STATE_START) + return "START"; + if (state == POWER_STATE_NORMAL) + return "NORMAL"; + if (state == POWER_STATE_SLEEP) + return "SLEEP"; + if (state == POWER_STATE_POWEROFF) + return "POWEROFF"; + if (state == POWER_STATE_REBOOT) + return "REBOOT"; + if (state == POWER_STATE_EXIT) + return "EXIT"; + + return "INVALID"; +} - power_acquire_wakelock(); - broadcast_transition_info(ti); - update_change_state_wait(state_transition_counter, ti, NULL, NULL); +static void reload_transition_sequence(GList **sequence) +{ + GList *new_sequence = NULL; + + g_list_free(g_steal_pointer(sequence)); + + new_sequence = g_list_append(new_sequence, state_abbr_name(transition_context.ti.curr)); + new_sequence = g_list_append(new_sequence, state_abbr_name(transition_context.ti.next)); + + *sequence = new_sequence; } -static void power_transition_sleep_to_sleep(const struct trans_info *ti) +static const char* build_description(GList *sequence, const int seqnum) { - int waiting; + static char buffer[MAX_DESC_LEN] = { 0, }; + char *head = buffer; + // leave 1 byte for terminating null character + char *const tail = buffer + sizeof(buffer) - 1; - power_acquire_wakelock(); - broadcast_transition_info(ti); - waiting = update_change_state_wait(state_transition_counter, ti, power_wake_unlock, NULL); - if (waiting > 0) { - _D("Defer wake unlock."); - return; + // additional (length-1) placeholders for transitioning arrow between each state + int max_sequence = g_list_length(sequence) * 2 - 1; + + GList *iter = sequence; + int n = 0; + + memset(buffer, 0, sizeof(buffer)); + + while (iter) { + GList *next = iter->next; + + if (n == seqnum) + head += snprintf(head, tail - head, "[%s] ", (const char *) iter->data); + else + head += snprintf(head, tail - head, " %s ", (const char *) iter->data); + + if (head >= tail) + break; + + ++n; + if (n >= max_sequence) + break; + + if (n == seqnum) + head += snprintf(head, tail - head, "[=>] "); + else + head += snprintf(head, tail - head, " => "); + + if (head >= tail) + break; + + ++n; + iter = next; } - power_wake_unlock(NULL); + return buffer; } -static void power_transition_to_poweroff(const struct trans_info *ti) +static void transition_description(int reload) { - int waiting; + static GList *transition_sequence = NULL; + static int seqnum = 0; - _D("Transition power state: %s -> %s, option=%s, reason=%d", - state_name(ti->curr), state_name(ti->next), (char *) ti->data, ti->reason); + if (reload) { + seqnum = 0; + reload_transition_sequence(&transition_sequence); + } - current = ti->next; + _D("%s", build_description(transition_sequence, seqnum++)); +} - // do not transition anymore after poweroff - unregister_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, power_transition_state); +static void trigger_transition(void) +{ + int waiting = 0; - poweroff_prepare(ti); - broadcast_transition_info(ti); - waiting = update_change_state_wait(state_transition_counter, ti, poweroff_main, (void *)(intptr_t) ti->next); - if (waiting > 0) { - _D("Defer poweroff."); - return; + assert(transition_context.max_wait_timer == 0); + assert(is_poweroff_state(current) == 0); + + transition_context.id = alloc_unique_id(); + + if (!transition_context.ongoing) { + // hold secondary wakelock not to fall asleep during transition + event_wake_lock(EL_POWER_TRANSITION_STATE); + transition_context.ongoing = 1; } - poweroff_main((void *)(intptr_t) ti->next); + transition_description(0); + + broadcast_transition_info(); + g_list_foreach(proc_list, init_waiting_list, &waiting); + if (waiting > 0) + transition_context.max_wait_timer = g_timeout_add_seconds(max_wait_timeout, max_wait_expired_cb, NULL); + else + action_transition(); } -static void transition_state(const struct trans_info *ti) +static void action_transition(void) { - int next; - struct trans_info __ti = { 0, }; - - if (ti->curr == POWER_STATE_ALL) { - /* replace POWER_STATE_ALL to the current state */ - memcpy(&__ti, ti, sizeof(struct trans_info)); - __ti.curr = current; - ti = &__ti; + struct trans_info ti = { 0 , }; + int retval; + + transition_description(0); + + current = transition_context.ti.next; + + if (action_on_state[POWER_STATE_INDEX(current)]) + action_on_state[POWER_STATE_INDEX(current)](transition_context.ti.data); + + // transition end + transition_context.ongoing = 0; + event_wake_unlock(EL_POWER_TRANSITION_STATE); + + // trigger next transition if exist + retval = dequeue_transition(&ti); + if (retval == 0) { + prepare_transition(&ti); + trigger_transition(); } +} - _D("Transition power state: %s -> %s, reason=%d", - state_name(ti->curr), state_name(ti->next), ti->reason); - - next = ti->next; - - /* transition */ - ++state_transition_counter; - if (current == POWER_STATE_START) { - if (next == POWER_STATE_NORMAL) - power_transition_start_to_normal(ti); - else if (next == POWER_STATE_SLEEP) - power_transition_start_to_sleep(ti); - else if (is_poweroff_state(next)) - power_transition_to_poweroff(ti); - } else if (current == POWER_STATE_NORMAL) { - if (next == POWER_STATE_NORMAL) - power_transition_normal_to_normal(ti); - else if (next == POWER_STATE_SLEEP) - power_transition_normal_to_sleep(ti); - else if (is_poweroff_state(next)) - power_transition_to_poweroff(ti); - } else if (current == POWER_STATE_SLEEP) { - if (next == POWER_STATE_NORMAL) - power_transition_sleep_to_normal(ti); - else if (next == POWER_STATE_SLEEP) - power_transition_sleep_to_sleep(ti); - else if (is_poweroff_state(next)) - power_transition_to_poweroff(ti); +static void prepare_transition(const struct trans_info *ti) +{ + assert(transition_context.waitings == NULL); + assert(transition_context.max_wait_timer == 0); + + if (ti) { + transition_context.ti = (struct trans_info) { + .curr = ti->curr, + .next = ti->next, + .reason = ti->reason, + .data = ti->data, + }; } - if (current != ti->next) - _W("Not defined transition. The current still stays at %s", state_name(current)); + transition_context.ongoing = 0; + + transition_description(1); } -static void deferred_transition_state(gpointer data) +static gint find_ti_by_state(gconstpointer data, gconstpointer udata) { - transition_state(data); - free(data); + const struct trans_info *ti = (const struct trans_info *) data; + const uint64_t state = *(const uint64_t *) udata; + + if (ti->curr & state) + return 0; + + return -1; } -static int power_transition_state(void *data) +static int transition_request_callback(void *data) { - GList *ti_list, *elem; - const struct trans_info *ti = NULL; + GList *ti_list, *l; + const struct trans_info *t = NULL; + struct trans_info ti = { 0 , }; + uint64_t available; if (!data) return 0; + available = available_starting_state(); + ti_list = (GList *) data; - // look for trans_info defined on the current state - SYS_G_LIST_FOREACH(ti_list, elem, ti) { - if (ti->curr & current) - break; - } + l = g_list_find_custom(ti_list, &available, find_ti_by_state); + if (!l) + return 0; - if (!ti) + if (!l->data) return 0; + t = l->data; + // check invalid next state - if (__builtin_popcountll(ti->next & POWER_STATE_ALL) != 1) { - _E("Invalid next state, curr=%"PRIx64", next=%"PRIx64", reason=%d", ti->curr, ti->next, ti->reason); + if (__builtin_popcountll(t->next & POWER_STATE_ALL) != 1) { + _E("Invalid next state, curr=%"PRIx64", next=%"PRIx64", reason=%d", t->curr, t->next, t->reason); return 0; } - // defer state transition until delayed_init_done unless it is transition to poweroff. - // poweroff shall be handled immediately regardless of the delayed_init_done. - if (!delayed_init_done && !is_poweroff_state(ti->next)) { - struct trans_info *deferred_ti = calloc(1, sizeof(struct trans_info)); - if (!deferred_ti) { - CRITICAL_LOG_E("Failed to defer transition."); - return 0; - } - - // Pseudo state transition. - current = ti->next; + ti = (struct trans_info) { + .curr = available, + .next = t->next, + .reason = t->reason, + .data = t->data, + }; - // Reserve the trans_info. - // Those are used on receiving delayed_init_done for real transitioning state. - memcpy(deferred_ti, ti, sizeof(struct trans_info)); - deferred_transition_list = g_list_append(deferred_transition_list, deferred_ti); - _D("Defer state transition %s->%s until delayed init done.", state_name(ti->curr), state_name(ti->next)); + // TODO: immediate handling of poweroff? + if (!delayed_init_done || transition_context.ongoing) { + enqueue_transition(&ti); return 0; } - transition_state(ti); + prepare_transition(&ti); + trigger_transition(); return 0; } -static int delayed_init_cb(void *data) +static int delayed_init_callback(void *data) { + int retval; + struct trans_info ti = { 0 , }; + delayed_init_done = 1; _D("Start deferred state transition."); - /* rewind current state to initial state and do the deferred transition */ - current = POWER_STATE_START; - g_list_free_full(g_steal_pointer(&deferred_transition_list), deferred_transition_state); + retval = dequeue_transition(&ti); + if (retval == 0) { + prepare_transition(&ti); + trigger_transition(); + } - /* Enable autosleep at this point. - * This prevents system go suspend(autosleep) before booting done */ - _D("Finished deferred state transition. Enable autosleep."); power_enable_autosleep(); return 0; } +static int load_max_wait_timeout(struct parse_result *result, void *user_data) +{ + if (MATCH(result->section, "PowerState") + && MATCH(result->name, "ChangeStateMaxWaitSecond")) + max_wait_timeout = atoi(result->value); + + return 0; +} + void power_state_init(void *data) { - register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_cb); - register_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, power_transition_state); + transition_queue = g_queue_new(); + + config_parse(POWER_CONF_FILE, load_max_wait_timeout, NULL); + + register_notifier(DEVICE_NOTIFIER_DELAYED_INIT, delayed_init_callback); + register_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, transition_request_callback); power_dbus_init(); power_off_init(); power_suspend_init(); power_event_lock_init(); - power_state_wait_init(); /* Take the first transition. * diff --git a/src/power/power.h b/src/power/power.h index 7ce29b2..3f469f8 100644 --- a/src/power/power.h +++ b/src/power/power.h @@ -99,5 +99,8 @@ static inline void power_request_change_state(uint64_t next, int reason) } uint64_t power_get_state(void); +int add_change_state_wait(pid_t pid, guint64 state); +void remove_change_state_wait(pid_t pid, guint64 state); +int confirm_change_state_wait(pid_t pid, guint64 id); #endif //__POWER_STATE_MANAGER_H__ -- 2.7.4 From 888dc040d3e1b48d7d370919292ccf2a0646562c Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 22 Nov 2022 17:27:36 +0900 Subject: [PATCH 05/16] power: introduce transient state It is able to define transient state between static states. The deviced always follows those transient states in sequence. It provides some checkpoints between static states, giving chances for other processes to sync with each other. Change-Id: I446083fd1c90610f805a64d61f16defc5a0a9b67 Signed-off-by: Youngjae Cho --- src/power/power.c | 130 ++++++++++++++++++++++++++++++++++++++++++++---------- src/power/power.h | 12 +++++ 2 files changed, 119 insertions(+), 23 deletions(-) diff --git a/src/power/power.c b/src/power/power.c index 0ae9be6..e44b7ed 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -50,6 +50,7 @@ static struct { int ongoing; struct trans_info ti; GList *waitings; + int transient_step; int max_wait_timer; } transition_context; @@ -66,9 +67,36 @@ struct change_state_wait { int state; }; +static const uint64_t transient_scenario_suspending[] = { + POWER_STATE_TRANSIENT_SUSPENDING_EARLY, + POWER_STATE_TRANSIENT_SUSPENDING, + POWER_STATE_TRANSIENT_SUSPENDING_LATE, +}; + +static const uint64_t transient_scenario_resuming[] = { + POWER_STATE_TRANSIENT_RESUMING_EARLY, + POWER_STATE_TRANSIENT_RESUMING, + POWER_STATE_TRANSIENT_RESUMING_LATE, +}; + +static const struct { + int max_step; + const uint64_t *scenario; +} transient[POWER_STATE_MAX_INDEX][POWER_STATE_MAX_INDEX] = { + [POWER_STATE_NORMAL_INDEX][POWER_STATE_SLEEP_INDEX] = { + .max_step = ARRAY_SIZE(transient_scenario_suspending), + .scenario = transient_scenario_suspending, + }, + [POWER_STATE_SLEEP_INDEX][POWER_STATE_NORMAL_INDEX] = { + .max_step = ARRAY_SIZE(transient_scenario_resuming), + .scenario = transient_scenario_resuming, + }, +}; + static int transition_request_callback(void *data); static void prepare_transition(const struct trans_info *ti); static void action_transition(void); +static uint64_t get_next_state(void); static void power_action_normal(void *data); static void power_action_sleep(void *data); @@ -255,25 +283,39 @@ static void broadcast_transition_info(void) { const char *signame; - if (transition_context.ti.next == POWER_STATE_START) + uint64_t next = get_next_state(); + + if (next == POWER_STATE_START) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START; - else if (transition_context.ti.next == POWER_STATE_NORMAL) + else if (next == POWER_STATE_NORMAL) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL; - else if (transition_context.ti.next == POWER_STATE_SLEEP) + else if (next == POWER_STATE_SLEEP) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP; - else if (transition_context.ti.next == POWER_STATE_POWEROFF) + else if (next == POWER_STATE_POWEROFF) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF; - else if (transition_context.ti.next == POWER_STATE_REBOOT) + else if (next == POWER_STATE_REBOOT) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT; - else if (transition_context.ti.next == POWER_STATE_EXIT) + else if (next == POWER_STATE_EXIT) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT; + else if (next == POWER_STATE_TRANSIENT_SUSPENDING_EARLY) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY; + else if (next == POWER_STATE_TRANSIENT_SUSPENDING) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING; + else if (next == POWER_STATE_TRANSIENT_SUSPENDING_LATE) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE; + else if (next == POWER_STATE_TRANSIENT_RESUMING_EARLY) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY; + else if (next == POWER_STATE_TRANSIENT_RESUMING) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING; + else if (next == POWER_STATE_TRANSIENT_RESUMING_LATE) + signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE; else return; gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER, signame, g_variant_new("(ttti)", transition_context.ti.curr, - transition_context.ti.next, + next, transition_context.id, transition_context.ti.reason)); } @@ -330,13 +372,27 @@ static void enqueue_transition(const struct trans_info *ti) g_queue_push_head(transition_queue, memcpy(ti_new, ti, sizeof(struct trans_info))); } +// intermediate state of ongoing transition +// it might be a transient state or a destination state +static uint64_t get_next_state(void) +{ + int curr = POWER_STATE_INDEX(transition_context.ti.curr); + int next = POWER_STATE_INDEX(transition_context.ti.next); + int step = transition_context.transient_step; + + if (step >= transient[curr][next].max_step) + return transition_context.ti.next; + else + return transient[curr][next].scenario[step]; +} + static void init_waiting_list(gpointer data, gpointer udata) { uint64_t waiting_state; struct proc_info *pi = (struct proc_info *) data; struct change_state_wait *csw = NULL; - waiting_state = transition_context.ti.next; + waiting_state = get_next_state(); if ((pi->state_bitmap & waiting_state) == 0) return; @@ -370,6 +426,18 @@ static char *state_abbr_name(uint64_t state) return "REBOOT"; if (state == POWER_STATE_EXIT) return "EXIT"; + if (state == POWER_STATE_TRANSIENT_SUSPENDING_EARLY) + return "SUSPENDING_EARLY"; + if (state == POWER_STATE_TRANSIENT_SUSPENDING) + return "SUSPENDING"; + if (state == POWER_STATE_TRANSIENT_SUSPENDING_LATE) + return "SUSPENDING_LATE"; + if (state == POWER_STATE_TRANSIENT_RESUMING_EARLY) + return "RESUMING_EARLY"; + if (state == POWER_STATE_TRANSIENT_RESUMING) + return "RESUMING"; + if (state == POWER_STATE_TRANSIENT_RESUMING_LATE) + return "RESUMING_LATE"; return "INVALID"; } @@ -377,10 +445,16 @@ static char *state_abbr_name(uint64_t state) static void reload_transition_sequence(GList **sequence) { GList *new_sequence = NULL; + int curr, next, step; g_list_free(g_steal_pointer(sequence)); + curr = POWER_STATE_INDEX(transition_context.ti.curr); + next = POWER_STATE_INDEX(transition_context.ti.next); + new_sequence = g_list_append(new_sequence, state_abbr_name(transition_context.ti.curr)); + for (step = 0; step < transient[curr][next].max_step; ++step) + new_sequence = g_list_append(new_sequence, state_abbr_name(transient[curr][next].scenario[step])); new_sequence = g_list_append(new_sequence, state_abbr_name(transition_context.ti.next)); *sequence = new_sequence; @@ -471,24 +545,33 @@ static void trigger_transition(void) static void action_transition(void) { - struct trans_info ti = { 0 , }; - int retval; + uint64_t state = get_next_state(); transition_description(0); - current = transition_context.ti.next; - - if (action_on_state[POWER_STATE_INDEX(current)]) - action_on_state[POWER_STATE_INDEX(current)](transition_context.ti.data); - - // transition end - transition_context.ongoing = 0; - event_wake_unlock(EL_POWER_TRANSITION_STATE); - - // trigger next transition if exist - retval = dequeue_transition(&ti); - if (retval == 0) { - prepare_transition(&ti); + if (state == transition_context.ti.next) { + // it has reached the destination state + struct trans_info ti = { 0 , }; + int retval; + + current = transition_context.ti.next; + + if (action_on_state[POWER_STATE_INDEX(current)]) + action_on_state[POWER_STATE_INDEX(current)](transition_context.ti.data); + + // transition end + transition_context.ongoing = 0; + event_wake_unlock(EL_POWER_TRANSITION_STATE); + + // trigger next transition if exist + retval = dequeue_transition(&ti); + if (retval == 0) { + prepare_transition(&ti); + trigger_transition(); + } + } else { + // step into the next transient state + ++transition_context.transient_step; trigger_transition(); } } @@ -508,6 +591,7 @@ static void prepare_transition(const struct trans_info *ti) } transition_context.ongoing = 0; + transition_context.transient_step = 0; transition_description(1); } diff --git a/src/power/power.h b/src/power/power.h index 3f469f8..7771556 100644 --- a/src/power/power.h +++ b/src/power/power.h @@ -74,6 +74,18 @@ static inline const char *state_name(uint64_t state) return "POWER_STATE_REBOOT"; if (state == POWER_STATE_EXIT) return "POWER_STATE_EXIT"; + if (state == POWER_STATE_TRANSIENT_SUSPENDING_EARLY) + return "POWER_STATE_TRANSIENT_SUSPENDING_EARLY"; + if (state == POWER_STATE_TRANSIENT_SUSPENDING) + return "POWER_STATE_TRANSIENT_SUSPENDING"; + if (state == POWER_STATE_TRANSIENT_SUSPENDING_LATE) + return "POWER_STATE_TRANSIENT_SUSPENDING_LATE"; + if (state == POWER_STATE_TRANSIENT_RESUMING_EARLY) + return "POWER_STATE_TRANSIENT_RESUMING_EARLY"; + if (state == POWER_STATE_TRANSIENT_RESUMING) + return "POWER_STATE_TRANSIENT_RESUMING"; + if (state == POWER_STATE_TRANSIENT_RESUMING_LATE) + return "POWER_STATE_TRANSIENT_RESUMING_LATE"; if (state == POWER_STATE_ALL) return "POWER_STATE_ALL"; -- 2.7.4 From d861ffd68509eb9871c0ab0f990e8cde61da5940 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 12 Dec 2022 11:17:00 +0900 Subject: [PATCH 06/16] power: fix condition for available starting state The condition for checking queue should have come first. This matters during a system haven't been initialized, that is before the call of delayed_init_callback(). Before the delayed_init_callback(), all requests are enqueued even though transition is not underway. In this case, it is possible to meet the both condtitions below: 1. there is no ongoing transition 2. there are some enqueued transitions In this situation, we must select the last state of transition as an available state. But the previous condition chooses the current state. Change-Id: If6285e2ca78734378ac9b626947b24ebb3d8594d Signed-off-by: Youngjae Cho --- src/power/power.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/power/power.c b/src/power/power.c index e44b7ed..e9b2a02 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -324,15 +324,17 @@ static uint64_t available_starting_state(void) { struct trans_info *ti = NULL; - // If there is no ongoing transition, the available state is the current state. - if (!transition_context.ongoing) - return current; - - // If there is ongoing transition and there are also some pending transitions, - // the available state is the last state of pending transitions. - // Otherwise, if there is ongoing transition but there are no pending transitions, - // the available state is the destination of ongoing transition. - return (ti = g_queue_peek_head(transition_queue)) ? ti->next : transition_context.ti.next; + // If there is pending transition, + // the available state is the last state of pendiong transitions. + ti = g_queue_peek_head(transition_queue); + if (ti) + return ti->next; + + // If a transition is underway and there is no other queued transitions, + // the available state is the destination of the ongoing transition. + // Otherwise, if there neither ongoing nor queued transitions are, + // the available state is the current state. + return transition_context.ongoing ? transition_context.ti.next : current; } static int dequeue_transition(struct trans_info *ti) @@ -646,6 +648,12 @@ static int transition_request_callback(void *data) // TODO: immediate handling of poweroff? if (!delayed_init_done || transition_context.ongoing) { + // Processes starting later than the deviced wanted to be informed + // about power transition that has happend before the process start. To + // this end, all transitions are delayed after the delayed_init_callback(), + // which is called on completing delayed.target. Therefore it is guaranteed + // that all processes that starts before delayed.target can receieve all + // power transition information. enqueue_transition(&ti); return 0; } -- 2.7.4 From 0adc137f91bfe4b6e170df8607f4d1778ac38e64 Mon Sep 17 00:00:00 2001 From: TaeminYeom Date: Mon, 12 Dec 2022 18:05:12 +0900 Subject: [PATCH 07/16] power: Add "DEVICE" or "device" prefix to enum and API To prevent collision, it is a principle to attach a prefix of project name in capi project. However, previous codes does not meet it. So, there is a patch in capi-system-device, and also change the code using them in deviced. changed enum: power_state_e -> device_power_state_e POWER_STATE_* -> DEVICE_POWER_STATE_* power_transient_state_e -> device_power_transient_state_e POWER_STATE_TRANSIENT_* -> DEVICE_POWER_STATE_TRANSIENT_* POWER_STATE_TRANSIENT_*_EARLY -> DEVICE_POWER_STATE_TRANSIENT_*_EARLY POWER_STATE_TRANSIENT_*_LATE -> DEVICE_POWER_STATE_TRANSIENT_*_LATE POWER_STATE_*_INDEX -> DEVICE_POWER_STATE_*_INDEX POWER_STATE_TRANSIENT_*_INDEX -> DEVICE_POWER_STATE_TRANSIENT_*_INDEX changed callback: power_change_state_wait_callback -> device_power_change_state_wait_callback Change-Id: I38887a0c35f897af2607b4ddf1e167675c1daf72 Signed-off-by: TaeminYeom --- src/battery/lowbat-handler.c | 4 +- src/power/power-boot.c | 2 +- src/power/power-dbus.c | 6 +-- src/power/power-off.c | 40 ++++++++++---------- src/power/power.c | 90 ++++++++++++++++++++++---------------------- src/power/power.h | 44 +++++++++++----------- 6 files changed, 93 insertions(+), 93 deletions(-) diff --git a/src/battery/lowbat-handler.c b/src/battery/lowbat-handler.c index 2584b25..85ccd4d 100644 --- a/src/battery/lowbat-handler.c +++ b/src/battery/lowbat-handler.c @@ -239,7 +239,7 @@ direct_launch: if (launched_poweroff == 1) { _I("Will be foreced power off."); - power_execute(POWER_STATE_POWEROFF); + power_execute(DEVICE_POWER_STATE_POWEROFF); return 0; } @@ -293,7 +293,7 @@ static int battery_critical_low_act(void *data) static int battery_power_off_act(void *data) { CRITICAL_LOG("Low battery power off."); - return power_execute(POWER_STATE_POWEROFF); + return power_execute(DEVICE_POWER_STATE_POWEROFF); } int battery_charge_err_cf_act(void *data) diff --git a/src/power/power-boot.c b/src/power/power-boot.c index 75ed8db..7814edb 100644 --- a/src/power/power-boot.c +++ b/src/power/power-boot.c @@ -177,7 +177,7 @@ void initial_transition_by_boot_condition(void) retval = hal_device_board_get_boot_reason(bc.reason, sizeof(bc.reason)); if (retval != 0) { _I("Failed to get BootReason, %d. Default change state to normal.", retval); - power_request_change_state_strict(POWER_STATE_START, POWER_STATE_NORMAL, 1, NULL); + power_request_change_state_strict(DEVICE_POWER_STATE_START, DEVICE_POWER_STATE_NORMAL, 1, NULL); return; } diff --git a/src/power/power-dbus.c b/src/power/power-dbus.c index 89162cc..b735121 100644 --- a/src/power/power-dbus.c +++ b/src/power/power-dbus.c @@ -298,11 +298,11 @@ static GVariant *dbus_power_change_state(GDBusConnection *conn, g_variant_get(param, "(t)", &next); - for (index = POWER_STATE_MIN_INDEX; index < POWER_STATE_MAX_INDEX; ++index) + for (index = DEVICE_POWER_STATE_MIN_INDEX; index < DEVICE_POWER_STATE_MAX_INDEX; ++index) if (next == (1UL << index)) break; - if (index == POWER_STATE_MAX_INDEX) { + if (index == DEVICE_POWER_STATE_MAX_INDEX) { _E("Invalid next state=%#lx", (long) index); ret = -EINVAL; goto out; @@ -320,7 +320,7 @@ static GVariant *dbus_power_change_state(GDBusConnection *conn, _I("Pid=%d(%s) sent request for PowerChangeState to %s", pid, comm, state_name(next)); - power_request_change_state_strict(POWER_STATE_ALL, next, 0, NULL); + power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, 0, NULL); out: return g_variant_new("(i)", ret); diff --git a/src/power/power-off.c b/src/power/power-off.c index 2cf17c6..77059fe 100644 --- a/src/power/power-off.c +++ b/src/power/power-off.c @@ -138,11 +138,11 @@ void poweroff_request_shutdown(int state) if (!is_poweroff_state(state)) return; - if (state == POWER_STATE_POWEROFF) + if (state == DEVICE_POWER_STATE_POWEROFF) systemd_method = "PowerOff"; - else if (state == POWER_STATE_REBOOT) + else if (state == DEVICE_POWER_STATE_REBOOT) systemd_method = "Reboot"; - else if (state == POWER_STATE_EXIT) + else if (state == DEVICE_POWER_STATE_EXIT) systemd_method = "Exit"; CRITICAL_LOG("Requested %s via systemd.", systemd_method); @@ -191,18 +191,18 @@ static void poweroff_delay_for_seconds(void) int poweroff_check_revived(void) { if (access(POWEROFF_OPTPATH_POWEROFF, F_OK) == 0) { - return POWER_STATE_POWEROFF; + return DEVICE_POWER_STATE_POWEROFF; } if (access(POWEROFF_OPTPATH_REBOOT, F_OK) == 0) { - return POWER_STATE_REBOOT; + return DEVICE_POWER_STATE_REBOOT; } if (access(POWEROFF_OPTPATH_EXIT, F_OK) == 0) { - return POWER_STATE_EXIT; + return DEVICE_POWER_STATE_EXIT; } - return POWER_STATE_NORMAL; + return DEVICE_POWER_STATE_NORMAL; } static void mark_poweroff_option(uint64_t state, const char *option) @@ -211,11 +211,11 @@ static void mark_poweroff_option(uint64_t state, const char *option) ssize_t len; const char *optpath; - if (state == POWER_STATE_POWEROFF) + if (state == DEVICE_POWER_STATE_POWEROFF) optpath = POWEROFF_OPTPATH_POWEROFF; - else if (state == POWER_STATE_REBOOT) + else if (state == DEVICE_POWER_STATE_REBOOT) optpath = POWEROFF_OPTPATH_REBOOT; - else if (state == POWER_STATE_EXIT) + else if (state == DEVICE_POWER_STATE_EXIT) optpath = POWEROFF_OPTPATH_EXIT; else return; @@ -300,9 +300,9 @@ void poweroff_prepare(uint64_t state, void *option) mark_poweroff_option(state, option); - if (state == POWER_STATE_POWEROFF) + if (state == DEVICE_POWER_STATE_POWEROFF) vconf = VCONFKEY_SYSMAN_POWER_OFF_DIRECT; - else if (state == POWER_STATE_REBOOT) + else if (state == DEVICE_POWER_STATE_REBOOT) vconf = VCONFKEY_SYSMAN_POWER_OFF_RESTART; vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, vconf); @@ -355,18 +355,18 @@ static GVariant *dbus_poweroff_handler(GDBusConnection *conn, get_command(ret, comm, sizeof(comm)); if (strncmp(type, "poweroff", sizeof("poweroff")) == 0) - next = POWER_STATE_POWEROFF; + next = DEVICE_POWER_STATE_POWEROFF; else if (strncmp(type, "reboot", sizeof("reboot")) == 0) - next = POWER_STATE_REBOOT; + next = DEVICE_POWER_STATE_REBOOT; else if (strncmp(type, "exit", sizeof("exit")) == 0) - next = POWER_STATE_EXIT; + next = DEVICE_POWER_STATE_EXIT; else { ret = -EINVAL; goto out; } CRITICAL_LOG("Poweroff pid=%d(%s) requests %s.", ret, comm, type); - power_request_change_state_strict(POWER_STATE_ALL, next, 9000, NULL); + power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, 9000, NULL); out: g_free(type); @@ -391,18 +391,18 @@ static GVariant *dbus_poweroff_option_handler(GDBusConnection *conn, get_command(ret, comm, sizeof(comm)); if (strncmp(type, "poweroff", sizeof("poweroff")) == 0) - next = POWER_STATE_POWEROFF; + next = DEVICE_POWER_STATE_POWEROFF; else if (strncmp(type, "reboot", sizeof("reboot")) == 0) - next = POWER_STATE_REBOOT; + next = DEVICE_POWER_STATE_REBOOT; else if (strncmp(type, "exit", sizeof("exit")) == 0) - next = POWER_STATE_EXIT; + next = DEVICE_POWER_STATE_EXIT; else { ret = -EINVAL; goto out; } CRITICAL_LOG("Poweroff pid=%d(%s) requests type=%s option=%s.", ret, comm, type, option); - power_request_change_state_strict(POWER_STATE_ALL, next, 9000, option); + power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, 9000, option); out: g_free(type); diff --git a/src/power/power.c b/src/power/power.c index e9b2a02..47587b0 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -42,7 +42,7 @@ #define MAX_DESC_LEN 256 static int delayed_init_done = 0; -static uint64_t current = POWER_STATE_START; /* current power state */ +static uint64_t current = DEVICE_POWER_STATE_START; /* current power state */ static int max_wait_timeout = DEFAULT_MAX_WAIT_SECOND; static GQueue *transition_queue; static struct { @@ -68,26 +68,26 @@ struct change_state_wait { }; static const uint64_t transient_scenario_suspending[] = { - POWER_STATE_TRANSIENT_SUSPENDING_EARLY, - POWER_STATE_TRANSIENT_SUSPENDING, - POWER_STATE_TRANSIENT_SUSPENDING_LATE, + DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY, + DEVICE_POWER_STATE_TRANSIENT_SUSPENDING, + DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE, }; static const uint64_t transient_scenario_resuming[] = { - POWER_STATE_TRANSIENT_RESUMING_EARLY, - POWER_STATE_TRANSIENT_RESUMING, - POWER_STATE_TRANSIENT_RESUMING_LATE, + DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY, + DEVICE_POWER_STATE_TRANSIENT_RESUMING, + DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE, }; static const struct { int max_step; const uint64_t *scenario; -} transient[POWER_STATE_MAX_INDEX][POWER_STATE_MAX_INDEX] = { - [POWER_STATE_NORMAL_INDEX][POWER_STATE_SLEEP_INDEX] = { +} transient[DEVICE_POWER_STATE_MAX_INDEX][DEVICE_POWER_STATE_MAX_INDEX] = { + [DEVICE_POWER_STATE_NORMAL_INDEX][DEVICE_POWER_STATE_SLEEP_INDEX] = { .max_step = ARRAY_SIZE(transient_scenario_suspending), .scenario = transient_scenario_suspending, }, - [POWER_STATE_SLEEP_INDEX][POWER_STATE_NORMAL_INDEX] = { + [DEVICE_POWER_STATE_SLEEP_INDEX][DEVICE_POWER_STATE_NORMAL_INDEX] = { .max_step = ARRAY_SIZE(transient_scenario_resuming), .scenario = transient_scenario_resuming, }, @@ -101,12 +101,12 @@ static uint64_t get_next_state(void); static void power_action_normal(void *data); static void power_action_sleep(void *data); static void power_action_poweroff(void *data); -static void (*const action_on_state[POWER_STATE_MAX_INDEX]) (void *) = { - [POWER_STATE_NORMAL_INDEX] = power_action_normal, - [POWER_STATE_SLEEP_INDEX] = power_action_sleep, - [POWER_STATE_POWEROFF_INDEX] = power_action_poweroff, - [POWER_STATE_REBOOT_INDEX] = power_action_poweroff, - [POWER_STATE_EXIT_INDEX] = power_action_poweroff, +static void (*const action_on_state[DEVICE_POWER_STATE_MAX_INDEX]) (void *) = { + [DEVICE_POWER_STATE_NORMAL_INDEX] = power_action_normal, + [DEVICE_POWER_STATE_SLEEP_INDEX] = power_action_sleep, + [DEVICE_POWER_STATE_POWEROFF_INDEX] = power_action_poweroff, + [DEVICE_POWER_STATE_REBOOT_INDEX] = power_action_poweroff, + [DEVICE_POWER_STATE_EXIT_INDEX] = power_action_poweroff, }; uint64_t power_get_state(void) @@ -261,8 +261,8 @@ static void power_action_normal(void *udata) static void power_action_sleep(void *udata) { - /* for POWER_STATE_NORMAL, POWER_STATE_POWEROFF, do not wake unlock */ - if (current != POWER_STATE_SLEEP) { + /* for DEVICE_POWER_STATE_NORMAL, DEVICE_POWER_STATE_POWEROFF, do not wake unlock */ + if (current != DEVICE_POWER_STATE_SLEEP) { _E("Ignore sleep wait done, current=%s", state_name(current)); return; } @@ -285,29 +285,29 @@ static void broadcast_transition_info(void) uint64_t next = get_next_state(); - if (next == POWER_STATE_START) + if (next == DEVICE_POWER_STATE_START) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START; - else if (next == POWER_STATE_NORMAL) + else if (next == DEVICE_POWER_STATE_NORMAL) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL; - else if (next == POWER_STATE_SLEEP) + else if (next == DEVICE_POWER_STATE_SLEEP) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP; - else if (next == POWER_STATE_POWEROFF) + else if (next == DEVICE_POWER_STATE_POWEROFF) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF; - else if (next == POWER_STATE_REBOOT) + else if (next == DEVICE_POWER_STATE_REBOOT) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT; - else if (next == POWER_STATE_EXIT) + else if (next == DEVICE_POWER_STATE_EXIT) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT; - else if (next == POWER_STATE_TRANSIENT_SUSPENDING_EARLY) + else if (next == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY; - else if (next == POWER_STATE_TRANSIENT_SUSPENDING) + else if (next == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING; - else if (next == POWER_STATE_TRANSIENT_SUSPENDING_LATE) + else if (next == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE; - else if (next == POWER_STATE_TRANSIENT_RESUMING_EARLY) + else if (next == DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY; - else if (next == POWER_STATE_TRANSIENT_RESUMING) + else if (next == DEVICE_POWER_STATE_TRANSIENT_RESUMING) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING; - else if (next == POWER_STATE_TRANSIENT_RESUMING_LATE) + else if (next == DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE) signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE; else return; @@ -416,29 +416,29 @@ static void init_waiting_list(gpointer data, gpointer udata) static char *state_abbr_name(uint64_t state) { - if (state == POWER_STATE_START) + if (state == DEVICE_POWER_STATE_START) return "START"; - if (state == POWER_STATE_NORMAL) + if (state == DEVICE_POWER_STATE_NORMAL) return "NORMAL"; - if (state == POWER_STATE_SLEEP) + if (state == DEVICE_POWER_STATE_SLEEP) return "SLEEP"; - if (state == POWER_STATE_POWEROFF) + if (state == DEVICE_POWER_STATE_POWEROFF) return "POWEROFF"; - if (state == POWER_STATE_REBOOT) + if (state == DEVICE_POWER_STATE_REBOOT) return "REBOOT"; - if (state == POWER_STATE_EXIT) + if (state == DEVICE_POWER_STATE_EXIT) return "EXIT"; - if (state == POWER_STATE_TRANSIENT_SUSPENDING_EARLY) + if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY) return "SUSPENDING_EARLY"; - if (state == POWER_STATE_TRANSIENT_SUSPENDING) + if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING) return "SUSPENDING"; - if (state == POWER_STATE_TRANSIENT_SUSPENDING_LATE) + if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE) return "SUSPENDING_LATE"; - if (state == POWER_STATE_TRANSIENT_RESUMING_EARLY) + if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY) return "RESUMING_EARLY"; - if (state == POWER_STATE_TRANSIENT_RESUMING) + if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING) return "RESUMING"; - if (state == POWER_STATE_TRANSIENT_RESUMING_LATE) + if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE) return "RESUMING_LATE"; return "INVALID"; @@ -633,7 +633,7 @@ static int transition_request_callback(void *data) t = l->data; // check invalid next state - if (__builtin_popcountll(t->next & POWER_STATE_ALL) != 1) { + if (__builtin_popcountll(t->next & DEVICE_POWER_STATE_ALL) != 1) { _E("Invalid next state, curr=%"PRIx64", next=%"PRIx64", reason=%d", t->curr, t->next, t->reason); return 0; } @@ -709,8 +709,8 @@ void power_state_init(void *data) /* Take the first transition. * - * It is determined by bootreason and bootmode to which state to transition, POWER_STATE_NORMAL - * or POWER_STATE_SLEEP. it may stay in POWER_STATE_START if there is no defined action for the + * It is determined by bootreason and bootmode to which state to transition, DEVICE_POWER_STATE_NORMAL + * or DEVICE_POWER_STATE_SLEEP. it may stay in DEVICE_POWER_STATE_START if there is no defined action for the * matching bootreason and bootmode. */ initial_transition_by_boot_condition(); diff --git a/src/power/power.h b/src/power/power.h index 7771556..f559826 100644 --- a/src/power/power.h +++ b/src/power/power.h @@ -41,19 +41,19 @@ void power_state_manager_init(void *data); static inline uint64_t convert_action_string_to_power_state(const char *str) { if (MATCH(str, "start")) - return POWER_STATE_START; + return DEVICE_POWER_STATE_START; else if (MATCH(str, "sleep")) - return POWER_STATE_SLEEP; + return DEVICE_POWER_STATE_SLEEP; else if (MATCH(str, "normal")) - return POWER_STATE_NORMAL; + return DEVICE_POWER_STATE_NORMAL; else if (MATCH(str, "poweroff")) - return POWER_STATE_POWEROFF; + return DEVICE_POWER_STATE_POWEROFF; else if (MATCH(str, "reboot")) - return POWER_STATE_REBOOT; + return DEVICE_POWER_STATE_REBOOT; else if (MATCH(str, "exit")) - return POWER_STATE_EXIT; + return DEVICE_POWER_STATE_EXIT; else if (MATCH(str, "current")) - return POWER_STATE_ALL; + return DEVICE_POWER_STATE_ALL; _W("Invalid power state=%s", str); @@ -62,31 +62,31 @@ static inline uint64_t convert_action_string_to_power_state(const char *str) static inline const char *state_name(uint64_t state) { - if (state == POWER_STATE_START) + if (state == DEVICE_POWER_STATE_START) return "POWER_STATE_START"; - if (state == POWER_STATE_NORMAL) + if (state == DEVICE_POWER_STATE_NORMAL) return "POWER_STATE_NORMAL"; - if (state == POWER_STATE_SLEEP) + if (state == DEVICE_POWER_STATE_SLEEP) return "POWER_STATE_SLEEP"; - if (state == POWER_STATE_POWEROFF) + if (state == DEVICE_POWER_STATE_POWEROFF) return "POWER_STATE_POWEROFF"; - if (state == POWER_STATE_REBOOT) + if (state == DEVICE_POWER_STATE_REBOOT) return "POWER_STATE_REBOOT"; - if (state == POWER_STATE_EXIT) + if (state == DEVICE_POWER_STATE_EXIT) return "POWER_STATE_EXIT"; - if (state == POWER_STATE_TRANSIENT_SUSPENDING_EARLY) + if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY) return "POWER_STATE_TRANSIENT_SUSPENDING_EARLY"; - if (state == POWER_STATE_TRANSIENT_SUSPENDING) + if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING) return "POWER_STATE_TRANSIENT_SUSPENDING"; - if (state == POWER_STATE_TRANSIENT_SUSPENDING_LATE) + if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE) return "POWER_STATE_TRANSIENT_SUSPENDING_LATE"; - if (state == POWER_STATE_TRANSIENT_RESUMING_EARLY) + if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY) return "POWER_STATE_TRANSIENT_RESUMING_EARLY"; - if (state == POWER_STATE_TRANSIENT_RESUMING) + if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING) return "POWER_STATE_TRANSIENT_RESUMING"; - if (state == POWER_STATE_TRANSIENT_RESUMING_LATE) + if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE) return "POWER_STATE_TRANSIENT_RESUMING_LATE"; - if (state == POWER_STATE_ALL) + if (state == DEVICE_POWER_STATE_ALL) return "POWER_STATE_ALL"; return "POWER_STATE_INVALID"; @@ -94,7 +94,7 @@ static inline const char *state_name(uint64_t state) static inline int is_poweroff_state(uint64_t state) { - return !!(state & (POWER_STATE_POWEROFF | POWER_STATE_REBOOT | POWER_STATE_EXIT)); + return !!(state & (DEVICE_POWER_STATE_POWEROFF | DEVICE_POWER_STATE_REBOOT | DEVICE_POWER_STATE_EXIT)); } static inline void power_request_change_state_strict(uint64_t curr, uint64_t next, int reason, void *udata) @@ -107,7 +107,7 @@ static inline void power_request_change_state_strict(uint64_t curr, uint64_t nex static inline void power_request_change_state(uint64_t next, int reason) { - power_request_change_state_strict(POWER_STATE_ALL, next, reason, NULL); + power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, reason, NULL); } uint64_t power_get_state(void); -- 2.7.4 From bab81b4522e739a2f5cc3046b4d50363b806fe79 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Wed, 14 Dec 2022 18:20:05 +0900 Subject: [PATCH 08/16] power: redefine deviced-exclusive power state enum Do not use enums from device API for the deviced power module. Instead, the deviced defines its own enums prefixed with DEVICED_POWER. When the deviced receives request from device API with API enum, then it is converted to the deviced enum, and vice versa. Change-Id: Ic67ba5c1bbbb1fa8335c15fde43cb13e9705eb0c Signed-off-by: Youngjae Cho --- src/battery/lowbat-handler.c | 4 +- src/power/power-boot.c | 2 +- src/power/power-dbus.c | 162 +++++++++++++++++++++++++++++++++++++------ src/power/power-off.c | 40 +++++------ src/power/power.c | 157 +++++++++++++++++++++-------------------- src/power/power.h | 100 +++++++++++++++++--------- 6 files changed, 317 insertions(+), 148 deletions(-) diff --git a/src/battery/lowbat-handler.c b/src/battery/lowbat-handler.c index 85ccd4d..0960194 100644 --- a/src/battery/lowbat-handler.c +++ b/src/battery/lowbat-handler.c @@ -239,7 +239,7 @@ direct_launch: if (launched_poweroff == 1) { _I("Will be foreced power off."); - power_execute(DEVICE_POWER_STATE_POWEROFF); + power_execute(DEVICED_POWER_STATE_POWEROFF); return 0; } @@ -293,7 +293,7 @@ static int battery_critical_low_act(void *data) static int battery_power_off_act(void *data) { CRITICAL_LOG("Low battery power off."); - return power_execute(DEVICE_POWER_STATE_POWEROFF); + return power_execute(DEVICED_POWER_STATE_POWEROFF); } int battery_charge_err_cf_act(void *data) diff --git a/src/power/power-boot.c b/src/power/power-boot.c index 7814edb..74ec729 100644 --- a/src/power/power-boot.c +++ b/src/power/power-boot.c @@ -177,7 +177,7 @@ void initial_transition_by_boot_condition(void) retval = hal_device_board_get_boot_reason(bc.reason, sizeof(bc.reason)); if (retval != 0) { _I("Failed to get BootReason, %d. Default change state to normal.", retval); - power_request_change_state_strict(DEVICE_POWER_STATE_START, DEVICE_POWER_STATE_NORMAL, 1, NULL); + power_request_change_state_strict(DEVICED_POWER_STATE_START, DEVICED_POWER_STATE_NORMAL, 1, NULL); return; } diff --git a/src/power/power-dbus.c b/src/power/power-dbus.c index b735121..4c5a292 100644 --- a/src/power/power-dbus.c +++ b/src/power/power-dbus.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,72 @@ struct lock_node { char locktime[64]; }; +static uint64_t convert_device_state_to_deviced(device_power_state_e state) +{ + if (state == DEVICE_POWER_STATE_START) + return DEVICED_POWER_STATE_START; + if (state == DEVICE_POWER_STATE_NORMAL) + return DEVICED_POWER_STATE_NORMAL; + if (state == DEVICE_POWER_STATE_SLEEP) + return DEVICED_POWER_STATE_SLEEP; + if (state == DEVICE_POWER_STATE_POWEROFF) + return DEVICED_POWER_STATE_POWEROFF; + if (state == DEVICE_POWER_STATE_REBOOT) + return DEVICED_POWER_STATE_REBOOT; + if (state == DEVICE_POWER_STATE_EXIT) + return DEVICED_POWER_STATE_EXIT; + + return DEVICED_POWER_STATE_UNDEFINED; +} + +static uint64_t convert_device_state_bitmap_to_deviced(device_power_state_e state) +{ + uint64_t deviced_bitmap = 0; + uint64_t bitmap = (uint64_t) state; + uint64_t lsb; + + while (bitmap) { + lsb = bitmap & -bitmap; + deviced_bitmap |= convert_device_state_to_deviced(lsb); + bitmap &= ~lsb; + } + + return deviced_bitmap; +} + +static uint64_t convert_device_transient_state_to_deviced(device_power_transient_state_e state) +{ + if (state == DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY) + return DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY; + if (state == DEVICE_POWER_TRANSIENT_STATE_RESUMING) + return DEVICED_POWER_TRANSIENT_STATE_RESUMING; + if (state == DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE) + return DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE; + if (state == DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY) + return DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY; + if (state == DEVICE_POWER_TRANSIENT_STATE_SUSPENDING) + return DEVICED_POWER_TRANSIENT_STATE_SUSPENDING; + if (state == DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE) + return DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE; + + return DEVICED_POWER_STATE_UNDEFINED; +} + +static uint64_t convert_device_transient_state_bitmap_to_deviced(device_power_transient_state_e state) +{ + uint64_t deviced_bitmap = 0; + uint64_t bitmap = (uint64_t) state; + uint64_t lsb; + + while (bitmap) { + lsb = bitmap & -bitmap; + deviced_bitmap |= convert_device_transient_state_to_deviced(lsb); + bitmap &= ~lsb; + } + + return deviced_bitmap; +} + static void print_lock_node(void) { GList *elem; @@ -236,7 +303,7 @@ static GVariant *dbus_power_add_change_state_wait(GDBusConnection *conn, g_variant_get(param, "(t)", &state); - ret = add_change_state_wait(pid, state); + ret = add_change_state_wait(pid, convert_device_state_bitmap_to_deviced(state)); out: return g_variant_new("(i)", ret); @@ -257,7 +324,51 @@ static GVariant *dbus_power_remove_change_state_wait(GDBusConnection *conn, g_variant_get(param, "(t)", &state); - remove_change_state_wait(pid, state); + remove_change_state_wait(pid, convert_device_state_bitmap_to_deviced(state)); + +out: + return gdbus_new_g_variant_tuple(); +} + +static GVariant *dbus_power_add_change_transient_state_wait(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int ret = 0; + pid_t pid; + guint64 state; + + pid = gdbus_connection_get_sender_pid(conn, sender); + if (pid == -1 || kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored.", pid); + ret = -ESRCH; + goto out; + } + + g_variant_get(param, "(t)", &state); + + ret = add_change_state_wait(pid, convert_device_transient_state_bitmap_to_deviced(state)); + +out: + return g_variant_new("(i)", ret); +} + +static GVariant *dbus_power_remove_change_transient_state_wait(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + pid_t pid; + guint64 state; + + pid = gdbus_connection_get_sender_pid(conn, sender); + if (pid == -1 || kill(pid, 0) == -1) { + _E("%d process does not exist, dbus ignored.", pid); + goto out; + } + + g_variant_get(param, "(t)", &state); + + remove_change_state_wait(pid, convert_device_transient_state_bitmap_to_deviced(state)); out: return gdbus_new_g_variant_tuple(); @@ -291,19 +402,16 @@ static GVariant *dbus_power_change_state(GDBusConnection *conn, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) { int ret = 0; - int index; - guint64 next; + uint64_t next; + guint64 device_next; pid_t pid; char comm[128] = "Unknown"; - g_variant_get(param, "(t)", &next); - - for (index = DEVICE_POWER_STATE_MIN_INDEX; index < DEVICE_POWER_STATE_MAX_INDEX; ++index) - if (next == (1UL << index)) - break; + g_variant_get(param, "(t)", &device_next); - if (index == DEVICE_POWER_STATE_MAX_INDEX) { - _E("Invalid next state=%#lx", (long) index); + next = convert_device_state_to_deviced(device_next); + if (next == DEVICED_POWER_STATE_UNDEFINED) { + _E("Invalid next state=%#"PRIx64, device_next); ret = -EINVAL; goto out; } @@ -320,7 +428,7 @@ static GVariant *dbus_power_change_state(GDBusConnection *conn, _I("Pid=%d(%s) sent request for PowerChangeState to %s", pid, comm, state_name(next)); - power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, 0, NULL); + power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, 0, NULL); out: return g_variant_new("(i)", ret); @@ -330,17 +438,31 @@ static GVariant *dbus_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("(t)", power_get_state()); + uint64_t current = power_get_state(); + int index = DEVICED_POWER_STATE_INDEX(current); + + static const uint64_t mapping_device_state[DEVICED_POWER_STATE_MAX_INDEX] = { + [DEVICED_POWER_STATE_START_INDEX] = DEVICE_POWER_STATE_START, + [DEVICED_POWER_STATE_NORMAL_INDEX] = DEVICE_POWER_STATE_NORMAL, + [DEVICED_POWER_STATE_SLEEP_INDEX] = DEVICE_POWER_STATE_SLEEP, + [DEVICED_POWER_STATE_POWEROFF_INDEX] = DEVICE_POWER_STATE_POWEROFF, + [DEVICED_POWER_STATE_REBOOT_INDEX] = DEVICE_POWER_STATE_REBOOT, + [DEVICED_POWER_STATE_EXIT_INDEX] = DEVICE_POWER_STATE_EXIT, + }; + + return g_variant_new("(t)", mapping_device_state[index]); } static const dbus_method_s dbus_methods[] = { - { "LockCpu", "i", "i", dbus_power_lock_cpu }, - { "UnlockCpu", NULL, "i", dbus_power_unlock_cpu }, - { "AddChangeStateWait", "t", "i", dbus_power_add_change_state_wait }, - { "RemoveChangeStateWait", "t", NULL, dbus_power_remove_change_state_wait }, - { "ConfirmChangeStateWait", "t", "i", dbus_power_confirm_change_state_wait }, - { "PowerChangeState", "t", "i", dbus_power_change_state }, - { "PowerGetState", NULL, "t", dbus_power_get_state }, + { "LockCpu", "i", "i", dbus_power_lock_cpu }, + { "UnlockCpu", NULL, "i", dbus_power_unlock_cpu }, + { "AddChangeStateWait", "t", "i", dbus_power_add_change_state_wait }, + { "RemoveChangeStateWait", "t", NULL, dbus_power_remove_change_state_wait }, + { "AddChangeTransientStateWait", "t", "i", dbus_power_add_change_transient_state_wait }, + { "RemoveChangeTransientStateWait", "t", NULL, dbus_power_remove_change_transient_state_wait }, + { "ConfirmChangeStateWait", "t", "i", dbus_power_confirm_change_state_wait }, + { "PowerChangeState", "t", "i", dbus_power_change_state }, + { "PowerGetState", NULL, "t", dbus_power_get_state }, /* Add methods here */ }; diff --git a/src/power/power-off.c b/src/power/power-off.c index 77059fe..37cecc3 100644 --- a/src/power/power-off.c +++ b/src/power/power-off.c @@ -138,11 +138,11 @@ void poweroff_request_shutdown(int state) if (!is_poweroff_state(state)) return; - if (state == DEVICE_POWER_STATE_POWEROFF) + if (state == DEVICED_POWER_STATE_POWEROFF) systemd_method = "PowerOff"; - else if (state == DEVICE_POWER_STATE_REBOOT) + else if (state == DEVICED_POWER_STATE_REBOOT) systemd_method = "Reboot"; - else if (state == DEVICE_POWER_STATE_EXIT) + else if (state == DEVICED_POWER_STATE_EXIT) systemd_method = "Exit"; CRITICAL_LOG("Requested %s via systemd.", systemd_method); @@ -191,18 +191,18 @@ static void poweroff_delay_for_seconds(void) int poweroff_check_revived(void) { if (access(POWEROFF_OPTPATH_POWEROFF, F_OK) == 0) { - return DEVICE_POWER_STATE_POWEROFF; + return DEVICED_POWER_STATE_POWEROFF; } if (access(POWEROFF_OPTPATH_REBOOT, F_OK) == 0) { - return DEVICE_POWER_STATE_REBOOT; + return DEVICED_POWER_STATE_REBOOT; } if (access(POWEROFF_OPTPATH_EXIT, F_OK) == 0) { - return DEVICE_POWER_STATE_EXIT; + return DEVICED_POWER_STATE_EXIT; } - return DEVICE_POWER_STATE_NORMAL; + return DEVICED_POWER_STATE_NORMAL; } static void mark_poweroff_option(uint64_t state, const char *option) @@ -211,11 +211,11 @@ static void mark_poweroff_option(uint64_t state, const char *option) ssize_t len; const char *optpath; - if (state == DEVICE_POWER_STATE_POWEROFF) + if (state == DEVICED_POWER_STATE_POWEROFF) optpath = POWEROFF_OPTPATH_POWEROFF; - else if (state == DEVICE_POWER_STATE_REBOOT) + else if (state == DEVICED_POWER_STATE_REBOOT) optpath = POWEROFF_OPTPATH_REBOOT; - else if (state == DEVICE_POWER_STATE_EXIT) + else if (state == DEVICED_POWER_STATE_EXIT) optpath = POWEROFF_OPTPATH_EXIT; else return; @@ -300,9 +300,9 @@ void poweroff_prepare(uint64_t state, void *option) mark_poweroff_option(state, option); - if (state == DEVICE_POWER_STATE_POWEROFF) + if (state == DEVICED_POWER_STATE_POWEROFF) vconf = VCONFKEY_SYSMAN_POWER_OFF_DIRECT; - else if (state == DEVICE_POWER_STATE_REBOOT) + else if (state == DEVICED_POWER_STATE_REBOOT) vconf = VCONFKEY_SYSMAN_POWER_OFF_RESTART; vconf_set_int(VCONFKEY_SYSMAN_POWER_OFF_STATUS, vconf); @@ -355,18 +355,18 @@ static GVariant *dbus_poweroff_handler(GDBusConnection *conn, get_command(ret, comm, sizeof(comm)); if (strncmp(type, "poweroff", sizeof("poweroff")) == 0) - next = DEVICE_POWER_STATE_POWEROFF; + next = DEVICED_POWER_STATE_POWEROFF; else if (strncmp(type, "reboot", sizeof("reboot")) == 0) - next = DEVICE_POWER_STATE_REBOOT; + next = DEVICED_POWER_STATE_REBOOT; else if (strncmp(type, "exit", sizeof("exit")) == 0) - next = DEVICE_POWER_STATE_EXIT; + next = DEVICED_POWER_STATE_EXIT; else { ret = -EINVAL; goto out; } CRITICAL_LOG("Poweroff pid=%d(%s) requests %s.", ret, comm, type); - power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, 9000, NULL); + power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, 9000, NULL); out: g_free(type); @@ -391,18 +391,18 @@ static GVariant *dbus_poweroff_option_handler(GDBusConnection *conn, get_command(ret, comm, sizeof(comm)); if (strncmp(type, "poweroff", sizeof("poweroff")) == 0) - next = DEVICE_POWER_STATE_POWEROFF; + next = DEVICED_POWER_STATE_POWEROFF; else if (strncmp(type, "reboot", sizeof("reboot")) == 0) - next = DEVICE_POWER_STATE_REBOOT; + next = DEVICED_POWER_STATE_REBOOT; else if (strncmp(type, "exit", sizeof("exit")) == 0) - next = DEVICE_POWER_STATE_EXIT; + next = DEVICED_POWER_STATE_EXIT; else { ret = -EINVAL; goto out; } CRITICAL_LOG("Poweroff pid=%d(%s) requests type=%s option=%s.", ret, comm, type, option); - power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, 9000, option); + power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, 9000, option); out: g_free(type); diff --git a/src/power/power.c b/src/power/power.c index 47587b0..9bef87b 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -37,12 +37,11 @@ #include "power-event-lock.h" #define POWER_CONF_FILE "/etc/deviced/power.conf" -#define POWER_STATE_INDEX(state) ((state) ? 63 - __builtin_clzll(state) : 0) #define DEFAULT_MAX_WAIT_SECOND 5 /* second */ #define MAX_DESC_LEN 256 static int delayed_init_done = 0; -static uint64_t current = DEVICE_POWER_STATE_START; /* current power state */ +static uint64_t current = DEVICED_POWER_STATE_START; /* current power state */ static int max_wait_timeout = DEFAULT_MAX_WAIT_SECOND; static GQueue *transition_queue; static struct { @@ -68,26 +67,26 @@ struct change_state_wait { }; static const uint64_t transient_scenario_suspending[] = { - DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY, - DEVICE_POWER_STATE_TRANSIENT_SUSPENDING, - DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE, + DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY, + DEVICED_POWER_TRANSIENT_STATE_SUSPENDING, + DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE, }; static const uint64_t transient_scenario_resuming[] = { - DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY, - DEVICE_POWER_STATE_TRANSIENT_RESUMING, - DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE, + DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY, + DEVICED_POWER_TRANSIENT_STATE_RESUMING, + DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE, }; static const struct { int max_step; const uint64_t *scenario; -} transient[DEVICE_POWER_STATE_MAX_INDEX][DEVICE_POWER_STATE_MAX_INDEX] = { - [DEVICE_POWER_STATE_NORMAL_INDEX][DEVICE_POWER_STATE_SLEEP_INDEX] = { +} transient[DEVICED_POWER_STATE_MAX_INDEX][DEVICED_POWER_STATE_MAX_INDEX] = { + [DEVICED_POWER_STATE_NORMAL_INDEX][DEVICED_POWER_STATE_SLEEP_INDEX] = { .max_step = ARRAY_SIZE(transient_scenario_suspending), .scenario = transient_scenario_suspending, }, - [DEVICE_POWER_STATE_SLEEP_INDEX][DEVICE_POWER_STATE_NORMAL_INDEX] = { + [DEVICED_POWER_STATE_SLEEP_INDEX][DEVICED_POWER_STATE_NORMAL_INDEX] = { .max_step = ARRAY_SIZE(transient_scenario_resuming), .scenario = transient_scenario_resuming, }, @@ -101,12 +100,12 @@ static uint64_t get_next_state(void); static void power_action_normal(void *data); static void power_action_sleep(void *data); static void power_action_poweroff(void *data); -static void (*const action_on_state[DEVICE_POWER_STATE_MAX_INDEX]) (void *) = { - [DEVICE_POWER_STATE_NORMAL_INDEX] = power_action_normal, - [DEVICE_POWER_STATE_SLEEP_INDEX] = power_action_sleep, - [DEVICE_POWER_STATE_POWEROFF_INDEX] = power_action_poweroff, - [DEVICE_POWER_STATE_REBOOT_INDEX] = power_action_poweroff, - [DEVICE_POWER_STATE_EXIT_INDEX] = power_action_poweroff, +static void (*const action_on_state[DEVICED_POWER_STATE_MAX_INDEX]) (void *) = { + [DEVICED_POWER_STATE_NORMAL_INDEX] = power_action_normal, + [DEVICED_POWER_STATE_SLEEP_INDEX] = power_action_sleep, + [DEVICED_POWER_STATE_POWEROFF_INDEX] = power_action_poweroff, + [DEVICED_POWER_STATE_REBOOT_INDEX] = power_action_poweroff, + [DEVICED_POWER_STATE_EXIT_INDEX] = power_action_poweroff, }; uint64_t power_get_state(void) @@ -261,8 +260,8 @@ static void power_action_normal(void *udata) static void power_action_sleep(void *udata) { - /* for DEVICE_POWER_STATE_NORMAL, DEVICE_POWER_STATE_POWEROFF, do not wake unlock */ - if (current != DEVICE_POWER_STATE_SLEEP) { + /* for DEVICED_POWER_STATE_NORMAL, DEVICED_POWER_STATE_POWEROFF, do not wake unlock */ + if (current != DEVICED_POWER_STATE_SLEEP) { _E("Ignore sleep wait done, current=%s", state_name(current)); return; } @@ -281,41 +280,47 @@ static void power_action_poweroff(void *data) static void broadcast_transition_info(void) { - const char *signame; - - uint64_t next = get_next_state(); - - if (next == DEVICE_POWER_STATE_START) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START; - else if (next == DEVICE_POWER_STATE_NORMAL) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL; - else if (next == DEVICE_POWER_STATE_SLEEP) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP; - else if (next == DEVICE_POWER_STATE_POWEROFF) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF; - else if (next == DEVICE_POWER_STATE_REBOOT) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT; - else if (next == DEVICE_POWER_STATE_EXIT) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT; - else if (next == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY; - else if (next == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING; - else if (next == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE; - else if (next == DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY; - else if (next == DEVICE_POWER_STATE_TRANSIENT_RESUMING) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING; - else if (next == DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE) - signame = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE; - else - return; + uint64_t curr = DEVICED_POWER_STATE_INDEX(transition_context.ti.curr); + uint64_t next = DEVICED_POWER_STATE_INDEX(get_next_state()); + + assert(DEVICED_POWER_STATE_MIN_INDEX <= curr && curr < DEVICED_POWER_TRANSIENT_STATE_MAX_INDEX); + assert(DEVICED_POWER_STATE_MIN_INDEX <= next && next < DEVICED_POWER_TRANSIENT_STATE_MAX_INDEX); + + static const char* mapping_signame[DEVICED_POWER_TRANSIENT_STATE_MAX_INDEX] = { + [DEVICED_POWER_STATE_START_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START, + [DEVICED_POWER_STATE_NORMAL_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL, + [DEVICED_POWER_STATE_SLEEP_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP, + [DEVICED_POWER_STATE_POWEROFF_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF, + [DEVICED_POWER_STATE_REBOOT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT, + [DEVICED_POWER_STATE_EXIT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT, + [DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY, + [DEVICED_POWER_TRANSIENT_STATE_RESUMING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING, + [DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE, + [DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY, + [DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING, + [DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE, + }; + + // convert deviced state to a correspond device enum + static const uint64_t mapping_device_state[DEVICED_POWER_TRANSIENT_STATE_MAX_INDEX] = { + [DEVICED_POWER_STATE_START_INDEX] = DEVICE_POWER_STATE_START, + [DEVICED_POWER_STATE_NORMAL_INDEX] = DEVICE_POWER_STATE_NORMAL, + [DEVICED_POWER_STATE_SLEEP_INDEX] = DEVICE_POWER_STATE_SLEEP, + [DEVICED_POWER_STATE_POWEROFF_INDEX] = DEVICE_POWER_STATE_POWEROFF, + [DEVICED_POWER_STATE_REBOOT_INDEX] = DEVICE_POWER_STATE_REBOOT, + [DEVICED_POWER_STATE_EXIT_INDEX] = DEVICE_POWER_STATE_EXIT, + [DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX] = DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY, + [DEVICED_POWER_TRANSIENT_STATE_RESUMING_INDEX] = DEVICE_POWER_TRANSIENT_STATE_RESUMING, + [DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX] = DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE, + [DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX] = DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY, + [DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_INDEX] = DEVICE_POWER_TRANSIENT_STATE_SUSPENDING, + [DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX] = DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE, + }; - gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER, signame, + gdbus_signal_emit(NULL, DEVICED_PATH_POWER, DEVICED_INTERFACE_POWER, mapping_signame[next], g_variant_new("(ttti)", - transition_context.ti.curr, - next, + mapping_device_state[curr], + mapping_device_state[next], transition_context.id, transition_context.ti.reason)); } @@ -378,8 +383,8 @@ static void enqueue_transition(const struct trans_info *ti) // it might be a transient state or a destination state static uint64_t get_next_state(void) { - int curr = POWER_STATE_INDEX(transition_context.ti.curr); - int next = POWER_STATE_INDEX(transition_context.ti.next); + int curr = DEVICED_POWER_STATE_INDEX(transition_context.ti.curr); + int next = DEVICED_POWER_STATE_INDEX(transition_context.ti.next); int step = transition_context.transient_step; if (step >= transient[curr][next].max_step) @@ -416,29 +421,29 @@ static void init_waiting_list(gpointer data, gpointer udata) static char *state_abbr_name(uint64_t state) { - if (state == DEVICE_POWER_STATE_START) + if (state == DEVICED_POWER_STATE_START) return "START"; - if (state == DEVICE_POWER_STATE_NORMAL) + if (state == DEVICED_POWER_STATE_NORMAL) return "NORMAL"; - if (state == DEVICE_POWER_STATE_SLEEP) + if (state == DEVICED_POWER_STATE_SLEEP) return "SLEEP"; - if (state == DEVICE_POWER_STATE_POWEROFF) + if (state == DEVICED_POWER_STATE_POWEROFF) return "POWEROFF"; - if (state == DEVICE_POWER_STATE_REBOOT) + if (state == DEVICED_POWER_STATE_REBOOT) return "REBOOT"; - if (state == DEVICE_POWER_STATE_EXIT) + if (state == DEVICED_POWER_STATE_EXIT) return "EXIT"; - if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY) + if (state == DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY) return "SUSPENDING_EARLY"; - if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING) + if (state == DEVICED_POWER_TRANSIENT_STATE_SUSPENDING) return "SUSPENDING"; - if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE) + if (state == DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE) return "SUSPENDING_LATE"; - if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY) + if (state == DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY) return "RESUMING_EARLY"; - if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING) + if (state == DEVICED_POWER_TRANSIENT_STATE_RESUMING) return "RESUMING"; - if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE) + if (state == DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE) return "RESUMING_LATE"; return "INVALID"; @@ -451,8 +456,8 @@ static void reload_transition_sequence(GList **sequence) g_list_free(g_steal_pointer(sequence)); - curr = POWER_STATE_INDEX(transition_context.ti.curr); - next = POWER_STATE_INDEX(transition_context.ti.next); + curr = DEVICED_POWER_STATE_INDEX(transition_context.ti.curr); + next = DEVICED_POWER_STATE_INDEX(transition_context.ti.next); new_sequence = g_list_append(new_sequence, state_abbr_name(transition_context.ti.curr)); for (step = 0; step < transient[curr][next].max_step; ++step) @@ -524,8 +529,10 @@ static void trigger_transition(void) { int waiting = 0; + assert(current != DEVICED_POWER_STATE_POWEROFF); + assert(current != DEVICED_POWER_STATE_REBOOT); + assert(current != DEVICED_POWER_STATE_EXIT); assert(transition_context.max_wait_timer == 0); - assert(is_poweroff_state(current) == 0); transition_context.id = alloc_unique_id(); @@ -555,11 +562,13 @@ static void action_transition(void) // it has reached the destination state struct trans_info ti = { 0 , }; int retval; + int index; current = transition_context.ti.next; + index = DEVICED_POWER_STATE_INDEX(current); - if (action_on_state[POWER_STATE_INDEX(current)]) - action_on_state[POWER_STATE_INDEX(current)](transition_context.ti.data); + if (action_on_state[index]) + action_on_state[index](transition_context.ti.data); // transition end transition_context.ongoing = 0; @@ -633,7 +642,7 @@ static int transition_request_callback(void *data) t = l->data; // check invalid next state - if (__builtin_popcountll(t->next & DEVICE_POWER_STATE_ALL) != 1) { + if (__builtin_popcountll(t->next & DEVICED_POWER_STATE_ALL) != 1) { _E("Invalid next state, curr=%"PRIx64", next=%"PRIx64", reason=%d", t->curr, t->next, t->reason); return 0; } @@ -709,8 +718,8 @@ void power_state_init(void *data) /* Take the first transition. * - * It is determined by bootreason and bootmode to which state to transition, DEVICE_POWER_STATE_NORMAL - * or DEVICE_POWER_STATE_SLEEP. it may stay in DEVICE_POWER_STATE_START if there is no defined action for the + * It is determined by bootreason and bootmode to which state to transition, DEVICED_POWER_STATE_NORMAL + * or DEVICED_POWER_STATE_SLEEP. it may stay in DEVICED_POWER_STATE_START if there is no defined action for the * matching bootreason and bootmode. */ initial_transition_by_boot_condition(); diff --git a/src/power/power.h b/src/power/power.h index f559826..a2aefac 100644 --- a/src/power/power.h +++ b/src/power/power.h @@ -20,14 +20,52 @@ #define __POWER_STATE_MANAGER_H__ #include +#include #include + #include -#include #include "shared/log-macro.h" #include "shared/device-notifier.h" -#define POWER_STATE_NONE 0 +enum { + DEVICED_POWER_STATE_MIN_INDEX, + DEVICED_POWER_STATE_START_INDEX = DEVICED_POWER_STATE_MIN_INDEX, + DEVICED_POWER_STATE_NORMAL_INDEX, + DEVICED_POWER_STATE_SLEEP_INDEX, + DEVICED_POWER_STATE_POWEROFF_INDEX, + DEVICED_POWER_STATE_REBOOT_INDEX, + DEVICED_POWER_STATE_EXIT_INDEX, + DEVICED_POWER_STATE_MAX_INDEX, + + DEVICED_POWER_TRANSIENT_STATE_MIN_INDEX, + DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX = DEVICED_POWER_TRANSIENT_STATE_MIN_INDEX, + DEVICED_POWER_TRANSIENT_STATE_RESUMING_INDEX, + DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX, + DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX, + DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_INDEX, + DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX, + DEVICED_POWER_TRANSIENT_STATE_MAX_INDEX, +}; + +#define DEVICED_POWER_STATE_UNDEFINED (0) + +#define DEVICED_POWER_STATE_START (1ULL << DEVICED_POWER_STATE_START_INDEX) +#define DEVICED_POWER_STATE_NORMAL (1ULL << DEVICED_POWER_STATE_NORMAL_INDEX) +#define DEVICED_POWER_STATE_SLEEP (1ULL << DEVICED_POWER_STATE_SLEEP_INDEX) +#define DEVICED_POWER_STATE_POWEROFF (1ULL << DEVICED_POWER_STATE_POWEROFF_INDEX) +#define DEVICED_POWER_STATE_REBOOT (1ULL << DEVICED_POWER_STATE_REBOOT_INDEX) +#define DEVICED_POWER_STATE_EXIT (1ULL << DEVICED_POWER_STATE_EXIT_INDEX) +#define DEVICED_POWER_STATE_ALL ((1ULL << DEVICED_POWER_STATE_MAX_INDEX) - (1ULL << DEVICED_POWER_STATE_MIN_INDEX)) + +#define DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY (1ULL << DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX) +#define DEVICED_POWER_TRANSIENT_STATE_SUSPENDING (1ULL << DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_INDEX) +#define DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE (1ULL << DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX) +#define DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY (1ULL << DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX) +#define DEVICED_POWER_TRANSIENT_STATE_RESUMING (1ULL << DEVICED_POWER_TRANSIENT_STATE_RESUMING_INDEX) +#define DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE (1ULL << DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX) + +#define DEVICED_POWER_STATE_INDEX(state) (__builtin_ctzll(state)) struct trans_info { uint64_t curr; @@ -41,52 +79,52 @@ void power_state_manager_init(void *data); static inline uint64_t convert_action_string_to_power_state(const char *str) { if (MATCH(str, "start")) - return DEVICE_POWER_STATE_START; + return DEVICED_POWER_STATE_START; else if (MATCH(str, "sleep")) - return DEVICE_POWER_STATE_SLEEP; + return DEVICED_POWER_STATE_SLEEP; else if (MATCH(str, "normal")) - return DEVICE_POWER_STATE_NORMAL; + return DEVICED_POWER_STATE_NORMAL; else if (MATCH(str, "poweroff")) - return DEVICE_POWER_STATE_POWEROFF; + return DEVICED_POWER_STATE_POWEROFF; else if (MATCH(str, "reboot")) - return DEVICE_POWER_STATE_REBOOT; + return DEVICED_POWER_STATE_REBOOT; else if (MATCH(str, "exit")) - return DEVICE_POWER_STATE_EXIT; + return DEVICED_POWER_STATE_EXIT; else if (MATCH(str, "current")) - return DEVICE_POWER_STATE_ALL; + return DEVICED_POWER_STATE_ALL; _W("Invalid power state=%s", str); - return POWER_STATE_NONE; + return DEVICED_POWER_STATE_UNDEFINED; } static inline const char *state_name(uint64_t state) { - if (state == DEVICE_POWER_STATE_START) + if (state == DEVICED_POWER_STATE_START) return "POWER_STATE_START"; - if (state == DEVICE_POWER_STATE_NORMAL) + if (state == DEVICED_POWER_STATE_NORMAL) return "POWER_STATE_NORMAL"; - if (state == DEVICE_POWER_STATE_SLEEP) + if (state == DEVICED_POWER_STATE_SLEEP) return "POWER_STATE_SLEEP"; - if (state == DEVICE_POWER_STATE_POWEROFF) + if (state == DEVICED_POWER_STATE_POWEROFF) return "POWER_STATE_POWEROFF"; - if (state == DEVICE_POWER_STATE_REBOOT) + if (state == DEVICED_POWER_STATE_REBOOT) return "POWER_STATE_REBOOT"; - if (state == DEVICE_POWER_STATE_EXIT) + if (state == DEVICED_POWER_STATE_EXIT) return "POWER_STATE_EXIT"; - if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY) - return "POWER_STATE_TRANSIENT_SUSPENDING_EARLY"; - if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING) - return "POWER_STATE_TRANSIENT_SUSPENDING"; - if (state == DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE) - return "POWER_STATE_TRANSIENT_SUSPENDING_LATE"; - if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY) - return "POWER_STATE_TRANSIENT_RESUMING_EARLY"; - if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING) - return "POWER_STATE_TRANSIENT_RESUMING"; - if (state == DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE) - return "POWER_STATE_TRANSIENT_RESUMING_LATE"; - if (state == DEVICE_POWER_STATE_ALL) + if (state == DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_EARLY) + return "POWER_TRANSIENT_STATE_SUSPENDING_EARLY"; + if (state == DEVICED_POWER_TRANSIENT_STATE_SUSPENDING) + return "POWER_TRANSIENT_STATE_SUSPENDING"; + if (state == DEVICED_POWER_TRANSIENT_STATE_SUSPENDING_LATE) + return "POWER_TRANSIENT_STATE_SUSPENDING_LATE"; + if (state == DEVICED_POWER_TRANSIENT_STATE_RESUMING_EARLY) + return "POWER_TRANSIENT_STATE_RESUMING_EARLY"; + if (state == DEVICED_POWER_TRANSIENT_STATE_RESUMING) + return "POWER_TRANSIENT_STATE_RESUMING"; + if (state == DEVICED_POWER_TRANSIENT_STATE_RESUMING_LATE) + return "POWER_TRANSIENT_STATE_RESUMING_LATE"; + if (state == DEVICED_POWER_STATE_ALL) return "POWER_STATE_ALL"; return "POWER_STATE_INVALID"; @@ -94,7 +132,7 @@ static inline const char *state_name(uint64_t state) static inline int is_poweroff_state(uint64_t state) { - return !!(state & (DEVICE_POWER_STATE_POWEROFF | DEVICE_POWER_STATE_REBOOT | DEVICE_POWER_STATE_EXIT)); + return !!(state & (DEVICED_POWER_STATE_POWEROFF | DEVICED_POWER_STATE_REBOOT | DEVICED_POWER_STATE_EXIT)); } static inline void power_request_change_state_strict(uint64_t curr, uint64_t next, int reason, void *udata) @@ -107,7 +145,7 @@ static inline void power_request_change_state_strict(uint64_t curr, uint64_t nex static inline void power_request_change_state(uint64_t next, int reason) { - power_request_change_state_strict(DEVICE_POWER_STATE_ALL, next, reason, NULL); + power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, reason, NULL); } uint64_t power_get_state(void); -- 2.7.4 From 98289c214d9a610c009505639353bb49a8f69d65 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Thu, 15 Dec 2022 17:03:14 +0900 Subject: [PATCH 09/16] power: fix data type of transition id Prevent including garbage at broadcast_transition_info() where an id is extended to a 64-bit size datatype. Change-Id: I5aabaecbb3a8dfa5a54aa7bd43248546e731bca6 Signed-off-by: Youngjae Cho --- src/power/power.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/power/power.c b/src/power/power.c index 9bef87b..e225839 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -45,7 +45,7 @@ static uint64_t current = DEVICED_POWER_STATE_START; /* current power state */ static int max_wait_timeout = DEFAULT_MAX_WAIT_SECOND; static GQueue *transition_queue; static struct { - int id; + uint64_t id; int ongoing; struct trans_info ti; GList *waitings; @@ -246,9 +246,9 @@ int confirm_change_state_wait(pid_t pid, guint64 id) return 0; } -static int alloc_unique_id(void) +static uint64_t alloc_unique_id(void) { - static int id = 0; + static uint64_t id = 0; return ++id; } -- 2.7.4 From 5f262d9d915ec4b49e6a78a0bec04bfb30f3fdfd Mon Sep 17 00:00:00 2001 From: TaeminYeom Date: Thu, 1 Dec 2022 17:59:14 +0900 Subject: [PATCH 10/16] power: add getter wakeup reason Add function to get wakeup reason by calling hal api function and save wakup reason. Add dbus method to delliver saved wakeup reason to device API. "wakeup reason" is the power transition state reason of sleep to normal. There are several reasons why the device wakeup and sometimes it Is needed to get the reason. added dbus method: dbus_power_get_wakeup_reason path: "/Org/Tizen/System/DeviceD/Power" interace: "org.tizen.system.deviced.Power" member: "PowerGetWakeupReason" paremeter: "(i)", enum transition reason to get. return: "(i)", 0 on success, negative on error. Change-Id: I2f96fecb3bc1308afc712421e3b2f6c8a7efefea Signed-off-by: TaeminYeom --- src/power/power-dbus.c | 8 ++++++++ src/power/power-suspend.c | 20 +++++++++++++++++++- src/power/power-suspend.h | 2 ++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/power/power-dbus.c b/src/power/power-dbus.c index 4c5a292..79bd067 100644 --- a/src/power/power-dbus.c +++ b/src/power/power-dbus.c @@ -453,6 +453,13 @@ static GVariant *dbus_power_get_state(GDBusConnection *conn, return g_variant_new("(t)", mapping_device_state[index]); } +static GVariant *dbus_power_get_wakeup_reason(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)", power_get_wakeup_reason()); +} + static const dbus_method_s dbus_methods[] = { { "LockCpu", "i", "i", dbus_power_lock_cpu }, { "UnlockCpu", NULL, "i", dbus_power_unlock_cpu }, @@ -463,6 +470,7 @@ static const dbus_method_s dbus_methods[] = { { "ConfirmChangeStateWait", "t", "i", dbus_power_confirm_change_state_wait }, { "PowerChangeState", "t", "i", dbus_power_change_state }, { "PowerGetState", NULL, "t", dbus_power_get_state }, + { "PowerGetWakeupReason", NULL, "i", dbus_power_get_wakeup_reason }, /* Add methods here */ }; diff --git a/src/power/power-suspend.c b/src/power/power-suspend.c index f7cf357..c50bcfd 100644 --- a/src/power/power-suspend.c +++ b/src/power/power-suspend.c @@ -16,7 +16,6 @@ * limitations under the License. */ - #include #include #include @@ -49,6 +48,7 @@ static int mainlock_status = POWER_UNLOCK; static int vital_service; static bool vital_sleep; static int vital_support = -2; +static enum hal_device_power_transition_reason wakeup_reason = HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN; #ifdef ENABLE_PM_LOG @@ -148,6 +148,11 @@ static int vital_mode_support(void) return vital_support; } +static int update_wakeup_reason(void) +{ + return hal_device_power_get_wakeup_reason(&wakeup_reason); +} + int suspend_other_process(int type) { int ret = 0; @@ -209,6 +214,14 @@ int pm_suspend(void) _I("system suspend"); ret_val = sys_set_str(POWER_STATE_PATH, "mem"); _I("System resume: %d", ret_val); + + ret_val = update_wakeup_reason(); + if (ret_val < 0) { + _E("Failed to update wakeup reason"); + wakeup_reason = HAL_DEVICE_POWER_TRANSITION_REASON_UNKNOWN; + return ret_val; + } + return 0; } @@ -274,6 +287,11 @@ int power_release_wakelock(void) return sys_set_str(POWER_UNLOCK_PATH, "mainlock"); } +enum hal_device_power_transition_reason power_get_wakeup_reason(void) +{ + return wakeup_reason; +} + int check_wakeup_src(void) { /* TODO if nedded. diff --git a/src/power/power-suspend.h b/src/power/power-suspend.h index a14b9d0..16a02e3 100644 --- a/src/power/power-suspend.h +++ b/src/power/power-suspend.h @@ -20,6 +20,7 @@ #define __DEVICED_POWER_SUSPEND_H__ #include "display/core.h" +#include #define POWER_AUTOSLEEP_PATH "/sys/power/autosleep" #define POWER_LOCK_PATH "/sys/power/wake_lock" @@ -81,6 +82,7 @@ int power_acquire_wakelock(void); int power_release_wakelock(void); int pm_get_power_lock(void); int pm_get_power_lock_support(void); +enum hal_device_power_transition_reason power_get_wakeup_reason(void); int check_wakeup_src(void); int get_wakeup_count(int *cnt); int set_wakeup_count(int cnt); -- 2.7.4 From 4e1f541f0a9e027a64a5ba4e53e091fe5ef24853 Mon Sep 17 00:00:00 2001 From: Yunhee Seo Date: Tue, 13 Dec 2022 11:41:35 +0900 Subject: [PATCH 11/16] input: add the input dbus interface Add a getter and setter function of input device event status With input device id parameter, it is possible to enable/disable input device event Input device event getter/setter dbus methods 1. Set input event state path: /Org/Tizen/System/DeviceD/Input interface: org.tizen.system.deviced.input member: InputSetEventState parameter: "(ii)", input device id to be set event state, value to be set return: "(i)", 0 on success, negative on error. 2. Get input event state path: /Org/Tizen/System/DeviceD/Input interface: org.tizen.system.deviced.input member: InputGetEventState parameter: "(i)", input device id to be get event state return: "(i)", get value on success, negative on error. Change-Id: I820add4689222198e3cc9a24fd616382800bcf16 Signed-off-by: Yunhee Seo --- src/input/input-dbus.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ src/input/input-dbus.h | 24 +++++++++++ src/input/input.c | 5 +++ 3 files changed, 134 insertions(+) create mode 100644 src/input/input-dbus.c create mode 100644 src/input/input-dbus.h diff --git a/src/input/input-dbus.c b/src/input/input-dbus.c new file mode 100644 index 0000000..e8a1e0a --- /dev/null +++ b/src/input/input-dbus.c @@ -0,0 +1,105 @@ +/* + * deviced + * + * Copyright (c) 2022 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. + */ + +/** + * @file input-dbus.c + * @brief dbus interface related to control input devices + * in this dbus methods will be added to + * "org.tizen.system.deviced.input" dbus interface. + */ + +#include +#include + +#include +#include + +#include "core/log.h" +#include "shared/common.h" +#include "input-dbus.h" + +/* FIXME: input.keyboard feature check should be added and return DEVICE_ERROR_NOT_SUPPORTED */ +static GVariant *dbus_inputseteventstate(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int input_device_id, event_state; + int ret = 0; + pid_t pid; + + g_variant_get(param, "(ii)", &input_device_id, &event_state); + + ret = hal_device_input_set_event_state(input_device_id, event_state); + if (ret < 0) + _E("Failed to set input event state"); + + pid = gdbus_connection_get_sender_pid(conn, sender); + _D("Input set event state pid=%d input device id=%d event state=%d", + pid, input_device_id, event_state); + + return g_variant_new("(i)", ret); +} + +/* FIXME: input.keyboard feature check should be added and return DEVICE_ERROR_NOT_SUPPORTED */ +static GVariant *dbus_inputgeteventstate(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int input_device_id, event_state = 0; + int ret = 0; + pid_t pid; + + g_variant_get(param, "(i)", &input_device_id); + + ret = hal_device_input_get_event_state(input_device_id, &event_state); + if (ret < 0) + _E("Failed to get input event state"); + else + ret = event_state; + + pid = gdbus_connection_get_sender_pid(conn, sender); + _D("Input get event state pid=%d input device id=%d event_state=%d", + pid, input_device_id, event_state); + + return g_variant_new("(i)", ret); +} + +static const dbus_method_s dbus_methods[] = { + {"InputSetEventState", "ii", "i", dbus_inputseteventstate}, + {"InputGetEventState", "i", "i", dbus_inputgeteventstate}, + /* Add methods here */ +}; + +static const dbus_interface_u dbus_interface = { + .oh = NULL, + .name = DEVICED_INTERFACE_INPUT, + .methods = dbus_methods, + .nr_methods = ARRAY_SIZE(dbus_methods), +}; + +int input_dbus_init(void) +{ + int ret = 0; + + ret = gdbus_add_object(NULL, DEVICED_PATH_INPUT, &dbus_interface); + if (ret < 0) { + _E("Failed to init input device dbus interface(%d)", ret); + return ret; + } + return 0; +} \ No newline at end of file diff --git a/src/input/input-dbus.h b/src/input/input-dbus.h new file mode 100644 index 0000000..a7522d9 --- /dev/null +++ b/src/input/input-dbus.h @@ -0,0 +1,24 @@ +/* + * deviced + * + * Copyright (c) 2022 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 __INPUT_DBUS_H__ +#define __INPUT_DBUS_H__ + +int input_dbus_init(void); + +#endif //__INPUT_DBUS_H__ diff --git a/src/input/input.c b/src/input/input.c index f39e7b8..c18c6f6 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -32,6 +32,7 @@ #include "shared/devices.h" #include "shared/log.h" +#include "input-dbus.h" #define SEAT_NAME "seat0" @@ -96,6 +97,10 @@ static void input_init(void *data) int ret; int fd; + ret = input_dbus_init(); + if(ret < 0) + _E("Failed to init input device dbus interface(%d)", ret); + /* load plugin input handler */ input_handler = find_device("input-handler"); if (check_default(input_handler) || input_handler->execute == NULL) { -- 2.7.4 From 86213dab21f29d3fa75d5f799f7fc2f5a04e6993 Mon Sep 17 00:00:00 2001 From: TaeminYeom Date: Thu, 29 Sep 2022 13:52:55 +0900 Subject: [PATCH 12/16] display: Add rotation angle interface rotation angle means "physical display" direction. Clients can rotate display or check current display angle. dbus method: dbus_getrotationangle path: "/Org/Tizen/System/DeviceD/Display" interace: "org.tizen.system.deviced.display" member: "GetRotationAngle" paremeter: "(i)", display index to get rotation angle. return: "(ii)", 0 on success, negative on error. enum display rotation angle to get. dbus_setrotationangle path: "/Org/Tizen/System/DeviceD/Display" interace: "org.tizen.system.deviced.display" member: "SetRotationAngle" paremeter: "(iii)", display index to set rotation angle. enum display rotation angle to set. enum display rotation direction. return: "(i)", 0 on success, negative on error. Change-Id: I792dd4d68034d511443c3c09c5b37bea220bce81 Signed-off-by: TaeminYeom --- plugins/iot-headless/display/core.c | 38 +++++++++++++++++++++++++++++++++++-- src/display/display-dbus.c | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/plugins/iot-headless/display/core.c b/plugins/iot-headless/display/core.c index fc642eb..288bb45 100644 --- a/plugins/iot-headless/display/core.c +++ b/plugins/iot-headless/display/core.c @@ -18,6 +18,7 @@ #include #include +#include #include static GVariant *dbus_lockstate(GDBusConnection *conn, @@ -34,9 +35,42 @@ static GVariant *dbus_unlockstate(GDBusConnection *conn, return g_variant_new("(i)", 0); } +static GVariant *dbus_getrotationangle(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int ret; + int display_index; + enum hal_device_display_rotation_angle angle; + + g_variant_get(param, "(i)", &display_index); + ret = hal_device_display_get_rotation_angle(display_index, &angle); + if (ret < 0) + angle = HAL_DEVICE_DISPLAY_ROTATION_ANGLE_UNKNOWN; + + return g_variant_new("(ii)", ret, angle); +} + +static GVariant *dbus_setrotationangle(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int ret; + int display_index; + enum hal_device_display_rotation_angle angle; + enum hal_device_display_rotation_direction direction; + + g_variant_get(param, "(iii)", &display_index, &angle, &direction); + ret = hal_device_display_set_rotation_angle(display_index, angle, direction); + + return g_variant_new("(i)", ret); +} + static const dbus_method_s dbus_methods[] = { - { "lockstate", "sssi", "i", dbus_lockstate }, - { "unlockstate", "ss", "i", dbus_unlockstate }, + { "lockstate", "sssi", "i", dbus_lockstate }, + { "unlockstate", "ss", "i", dbus_unlockstate }, + { "GetRotationAngle", "i", "ii", dbus_getrotationangle }, + { "SetRotationAngle", "iii", "i", dbus_setrotationangle } }; static const dbus_interface_u dbus_interface = { diff --git a/src/display/display-dbus.c b/src/display/display-dbus.c index 197260a..9d97619 100644 --- a/src/display/display-dbus.c +++ b/src/display/display-dbus.c @@ -1245,6 +1245,37 @@ static GVariant *dbus_getwhitebalance(GDBusConnection *conn, return g_variant_new("(i)", ret); } +static GVariant *dbus_getrotationangle(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int ret; + int display_index; + enum hal_device_display_rotation_angle angle; + + g_variant_get(param, "(i)", &display_index); + ret = hal_device_display_get_rotation_angle(display_index, &angle); + if (ret < 0) + angle = HAL_DEVICE_DISPLAY_ROTATION_ANGLE_UNKNOWN; + + return g_variant_new("(ii)", ret, angle); +} + +static GVariant *dbus_setrotationangle(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int ret = 0; + int display_index; + enum hal_device_display_rotation_angle angle; + enum hal_device_display_rotation_direction direction; + + g_variant_get(param, "(iii)", &display_index, &angle, &direction); + ret = hal_device_display_set_rotation_angle(display_index, angle, direction); + + return g_variant_new("(i)", ret); +} + static const dbus_method_s dbus_methods[] = { { "start", NULL, NULL, dbus_start }, { "stop", NULL, NULL, dbus_stop }, @@ -1284,6 +1315,8 @@ static const dbus_method_s dbus_methods[] = { { "GetBrightnessInfo", NULL, "ii", dbus_getbrightnessinfo}, { "SetWhiteBalance", "ii", "i", dbus_setwhitebalance}, { "GetWhiteBalance", "i", "i", dbus_getwhitebalance}, + { "GetRotationAngle", "i", "ii", dbus_getrotationangle}, + { "SetRotationAngle", "iii", "i", dbus_setrotationangle} /* Add methods here */ }; -- 2.7.4 From 470680f23c1c37d375238c43c7f7821977350814 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Fri, 23 Dec 2022 10:17:08 +0900 Subject: [PATCH 13/16] power: reloacte marking poweroff option Poweroff option can be marked just on receiving the option from dbus method. It is safer in that it prevents loss of option address due to asynchronous process of power transition. Change-Id: I77f7c81035d3281396c0aea0a8c96760f08d5334 Signed-off-by: Youngjae Cho --- src/power/power-off.c | 14 +++++++++----- src/power/power-off.h | 2 +- src/power/power.c | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/power/power-off.c b/src/power/power-off.c index 37cecc3..de68503 100644 --- a/src/power/power-off.c +++ b/src/power/power-off.c @@ -60,6 +60,7 @@ static struct timeval tv_start_poweroff; static int poweroff_delay_second = 0; +static int silent_reboot = 0; static void poweroff_start_animation(void) { @@ -220,6 +221,9 @@ static void mark_poweroff_option(uint64_t state, const char *option) else return; + if (option && strncmp(option, "silent", sizeof("silent")) == 0) + silent_reboot = 1; + fd = open(optpath, O_RDWR|O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) { _E("Failed to create '%s'.", optpath); @@ -291,15 +295,13 @@ static void system_shutdown_send_system_event(void) bundle_free(b); } -void poweroff_prepare(uint64_t state, void *option) +void poweroff_prepare(uint64_t state) { int vconf = VCONFKEY_SYSMAN_POWER_OFF_NONE; if (!is_poweroff_state(state)) return; - mark_poweroff_option(state, option); - if (state == DEVICED_POWER_STATE_POWEROFF) vconf = VCONFKEY_SYSMAN_POWER_OFF_DIRECT; else if (state == DEVICED_POWER_STATE_REBOOT) @@ -313,7 +315,7 @@ void poweroff_prepare(uint64_t state, void *option) system_shutdown_send_system_event(); /* Skip running animation if it is silent reboot */ - if (option && strncmp(option, "silent", sizeof("silent")) == 0) + if (silent_reboot) return; poweroff_start_animation(); @@ -401,8 +403,10 @@ static GVariant *dbus_poweroff_option_handler(GDBusConnection *conn, goto out; } + mark_poweroff_option(next, option); + CRITICAL_LOG("Poweroff pid=%d(%s) requests type=%s option=%s.", ret, comm, type, option); - power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, 9000, option); + power_request_change_state_strict(DEVICED_POWER_STATE_ALL, next, 9000, NULL); out: g_free(type); diff --git a/src/power/power-off.h b/src/power/power-off.h index 7e961f7..bdef892 100644 --- a/src/power/power-off.h +++ b/src/power/power-off.h @@ -34,7 +34,7 @@ void power_off_init(void); int poweroff_check_revived(void); void poweroff_request_shutdown(int state); -void poweroff_prepare(uint64_t state, void *option); +void poweroff_prepare(uint64_t state); void poweroff_main(void *udata); #endif /* __DEVICED_POWER_OFF_H__ */ diff --git a/src/power/power.c b/src/power/power.c index e225839..42e0da3 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -274,7 +274,7 @@ static void power_action_poweroff(void *data) // do not transition anymore after poweroff unregister_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, transition_request_callback); - poweroff_prepare(current, data); + poweroff_prepare(current); poweroff_main((void *)(intptr_t) current); } -- 2.7.4 From 4d0daf18b56643cfaeb81f7ca777135726340398 Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Tue, 27 Dec 2022 17:25:51 +0900 Subject: [PATCH 14/16] devicectl: add suspend/resume command Usage: devicectl power suspend|resume reason(int) #) devicectl power suspend 12345 #) devicectl power resume 2000 The value reason can be an any integer and the devicectl doesn't test it is valid reason or not. Therefore some listeners of suspend/resume event might malfunction as they receive a wierd reason. Change-Id: I62c66e0a8034f9884fd006404991330902ecca21 Signed-off-by: Youngjae Cho --- src/power/power-dbus.c | 16 ++++++++++++++++ tools/devicectl/devicectl.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/power/power-dbus.c b/src/power/power-dbus.c index 79bd067..09a1f4a 100644 --- a/src/power/power-dbus.c +++ b/src/power/power-dbus.c @@ -434,6 +434,21 @@ out: return g_variant_new("(i)", ret); } +// devicectl power suspend +// devicectl power resume +static GVariant *dbus_power_change_state_with_reason(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + uint64_t next; + int reason; + + g_variant_get(param, "(ti)", &next, &reason); + power_request_change_state(next, reason); + + return gdbus_new_g_variant_tuple(); +} + static GVariant *dbus_power_get_state(GDBusConnection *conn, const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) @@ -469,6 +484,7 @@ static const dbus_method_s dbus_methods[] = { { "RemoveChangeTransientStateWait", "t", NULL, dbus_power_remove_change_transient_state_wait }, { "ConfirmChangeStateWait", "t", "i", dbus_power_confirm_change_state_wait }, { "PowerChangeState", "t", "i", dbus_power_change_state }, + { "PowerChangeStateWithReason", "ti", NULL, dbus_power_change_state_with_reason }, { "PowerGetState", NULL, "t", dbus_power_get_state }, { "PowerGetWakeupReason", NULL, "i", dbus_power_get_wakeup_reason }, /* Add methods here */ diff --git a/tools/devicectl/devicectl.c b/tools/devicectl/devicectl.c index 66704fa..456cd42 100644 --- a/tools/devicectl/devicectl.c +++ b/tools/devicectl/devicectl.c @@ -24,6 +24,8 @@ #include #include #include "usb.h" +#include "power/power.h" + /* * devicectl [device] [action] @@ -413,6 +415,30 @@ out: return ret; } +static int power_suspend(char **args) +{ + gdbus_call_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_POWER, + DEVICED_INTERFACE_POWER, + "PowerChangeStateWithReason", + g_variant_new("(ti)", DEVICED_POWER_STATE_SLEEP, atoi(args[3])), + NULL); + + return 0; +} + +static int power_resume(char **args) +{ + gdbus_call_sync_with_reply(DEVICED_BUS_NAME, + DEVICED_PATH_POWER, + DEVICED_INTERFACE_POWER, + "PowerChangeStateWithReason", + g_variant_new("(ti)", DEVICED_POWER_STATE_NORMAL, atoi(args[3])), + NULL); + + return 0; +} + static int power_off(char **args) { return power_operation(args, "poweroff"); @@ -442,6 +468,8 @@ static const struct action { { DEVICE_CORE, "devicelist", 3, device_list, "" }, { DEVICE_EXTCON, "enable", 4, enable_device, "[USB|HEADPHONE|HDMI|DOCK]" }, { DEVICE_EXTCON, "disable", 4, disable_device, "[USB|HEADPHONE|HDMI|DOCK]" }, + { DEVICE_POWER, "suspend", 4, power_suspend, "reason(int)" }, + { DEVICE_POWER, "resume", 4, power_resume, "reason(int)" }, { DEVICE_POWER, "off", 3, power_off, "" }, { DEVICE_POWER, "reboot", 3, power_reboot, "" }, }; -- 2.7.4 From 1e7a5e79b37c786ff852663b36ef27583491df1e Mon Sep 17 00:00:00 2001 From: Yunhee Seo Date: Mon, 2 Jan 2023 11:11:11 +0900 Subject: [PATCH 15/16] input: relocate dbus interface initialization Previous input dbus interface was initialized by input plugin part. Thus, input dbus interface initialization part is moved to core input module. Change-Id: Ie786e15b49b20d30e35719e5f5f26dd0a492a4e8 Signed-off-by: Yunhee Seo --- plugins/iot-headless/input/input-handler.c | 9 +++++++-- plugins/iot-headless/input/input-handler.h | 2 +- src/input/input-dbus.c | 16 ++++++++++++++++ src/input/input-dbus.h | 2 +- src/input/input-interface.h | 30 ++++++++++++++++++++++++++++++ src/input/input.c | 22 +++++++++++++++++----- src/input/input.h | 28 ++++++++++++++++++++++++++++ 7 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 src/input/input-interface.h create mode 100644 src/input/input.h diff --git a/plugins/iot-headless/input/input-handler.c b/plugins/iot-headless/input/input-handler.c index ffa7f83..81f3978 100644 --- a/plugins/iot-headless/input/input-handler.c +++ b/plugins/iot-headless/input/input-handler.c @@ -28,6 +28,7 @@ #include "shared/device-notifier.h" #include "shared/log.h" #include "shared/event.h" +#include "input/input-interface.h" #include "input-config.h" #include "input-dbus.h" @@ -127,7 +128,7 @@ static void stop_event_timer(struct input_config *ic) } } -void input_handler_process_key(int keycode, int keyvalue) +static void input_handler_process_key(int keycode, int keyvalue) { struct input_config *ic; @@ -172,10 +173,14 @@ static int input_handler_execute(void *data) return 0; } +static struct input_ops input_handler_ops = { + .input_handler_process_key = input_handler_process_key, +}; + static void input_handler_init(void *data) { init_input_config(); - init_input_dbus(); + *(struct input_ops**)data = &input_handler_ops; } static const struct device_ops input_handler_device_ops = { diff --git a/plugins/iot-headless/input/input-handler.h b/plugins/iot-headless/input/input-handler.h index 8b03f12..e66730d 100644 --- a/plugins/iot-headless/input/input-handler.h +++ b/plugins/iot-headless/input/input-handler.h @@ -3,4 +3,4 @@ void input_handler_process_key(int keycode, int keyvalue); -#endif //__INPUT_HANDLER_H__ +#endif //__INPUT_HANDLER_H__ \ No newline at end of file diff --git a/src/input/input-dbus.c b/src/input/input-dbus.c index e8a1e0a..ba00174 100644 --- a/src/input/input-dbus.c +++ b/src/input/input-dbus.c @@ -31,7 +31,9 @@ #include "core/log.h" #include "shared/common.h" +#include "input.h" #include "input-dbus.h" +#include "input-interface.h" /* FIXME: input.keyboard feature check should be added and return DEVICE_ERROR_NOT_SUPPORTED */ static GVariant *dbus_inputseteventstate(GDBusConnection *conn, @@ -79,9 +81,23 @@ static GVariant *dbus_inputgeteventstate(GDBusConnection *conn, return g_variant_new("(i)", ret); } +static GVariant *dbus_emulate_key(GDBusConnection *conn, + const gchar *sender, const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data) +{ + int keycode, keyvalue; + + g_variant_get(param, "(ii)", &keycode, &keyvalue); + + input_handler_process_key(keycode, keyvalue); + + return gdbus_new_g_variant_tuple(); +} + static const dbus_method_s dbus_methods[] = { {"InputSetEventState", "ii", "i", dbus_inputseteventstate}, {"InputGetEventState", "i", "i", dbus_inputgeteventstate}, + {"EmulateKey", "ii", NULL, dbus_emulate_key}, /* Add methods here */ }; diff --git a/src/input/input-dbus.h b/src/input/input-dbus.h index a7522d9..54ada46 100644 --- a/src/input/input-dbus.h +++ b/src/input/input-dbus.h @@ -21,4 +21,4 @@ int input_dbus_init(void); -#endif //__INPUT_DBUS_H__ +#endif //__INPUT_DBUS_H__ \ No newline at end of file diff --git a/src/input/input-interface.h b/src/input/input-interface.h new file mode 100644 index 0000000..62bbf1e --- /dev/null +++ b/src/input/input-interface.h @@ -0,0 +1,30 @@ +/* + * deviced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +/** + * @file input-interface.h + * @brief input interface module header + */ +#ifndef __INPUT_INTERFACE_H__ +#define __INPUT_INTERFACE_H__ + +struct input_ops { + void (*input_handler_process_key)(int keycode, int keyvalue); +}; + +#endif /* __INPUT_INTERFACE_H__ */ \ No newline at end of file diff --git a/src/input/input.c b/src/input/input.c index c18c6f6..20b4faf 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -32,12 +32,15 @@ #include "shared/devices.h" #include "shared/log.h" +#include "input.h" #include "input-dbus.h" +#include "input-interface.h" #define SEAT_NAME "seat0" static struct udev *udev; static struct libinput *li; +static struct input_ops *input_plugin_ops; static guint efd; static const struct device_ops *input_handler; @@ -92,15 +95,17 @@ static const struct libinput_interface interface = { .close_restricted = close_restricted, }; +void input_handler_process_key(int keycode, int keyvalue) +{ + if (input_plugin_ops && input_plugin_ops->input_handler_process_key) + input_plugin_ops->input_handler_process_key(keycode, keyvalue); +} + static void input_init(void *data) { int ret; int fd; - ret = input_dbus_init(); - if(ret < 0) - _E("Failed to init input device dbus interface(%d)", ret); - /* load plugin input handler */ input_handler = find_device("input-handler"); if (check_default(input_handler) || input_handler->execute == NULL) { @@ -109,7 +114,14 @@ static void input_init(void *data) } if (input_handler->init) - input_handler->init(NULL); + input_handler->init(&input_plugin_ops); + + if (input_plugin_ops == NULL) + _E("Failed to init input_ops"); + + ret = input_dbus_init(); + if (ret < 0) + _E("Failed to init input device dbus interface(%d)", ret); udev = udev_new(); if (!udev) { diff --git a/src/input/input.h b/src/input/input.h new file mode 100644 index 0000000..287ad30 --- /dev/null +++ b/src/input/input.h @@ -0,0 +1,28 @@ +/* + * deviced + * + * Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved. + * + * 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. + */ + +/** + * @file input.h + * @brief input module header + */ +#ifndef __INPUT_H__ +#define __INPUT_H__ + +void input_handler_process_key(int keycode, int keyvalue); + +#endif /* __INPUT_H__ */ \ No newline at end of file -- 2.7.4 From 41ab55ff50cd06956fabeaf70cec5ad0b8fe81da Mon Sep 17 00:00:00 2001 From: Youngjae Cho Date: Mon, 2 Jan 2023 19:58:27 +0900 Subject: [PATCH 16/16] power: move broadcast suspend/resume into power module Change-Id: I3a9499947866716154dadc1a415578630c60ad7b Signed-off-by: Youngjae Cho --- plugins/iot-headed/display/core.c | 7 ------ plugins/mobile/display/core.c | 7 ------ plugins/tv/display/core.c | 7 ------ plugins/wearable/display/core.c | 4 ---- src/display/display-signal.c | 45 +---------------------------------- src/display/display-signal.h | 21 ---------------- src/power/power-suspend.c | 50 +++++++++++++++++++++++++++++++++++++++ src/shared/time.c | 20 ++++++++++++++++ src/shared/time.h | 6 +++++ 9 files changed, 77 insertions(+), 90 deletions(-) create mode 100644 src/shared/time.c create mode 100644 src/shared/time.h diff --git a/plugins/iot-headed/display/core.c b/plugins/iot-headed/display/core.c index 6bd21d0..92dc4e3 100644 --- a/plugins/iot-headed/display/core.c +++ b/plugins/iot-headed/display/core.c @@ -84,9 +84,6 @@ #define PALM_STR "palm" #define UNKNOWN_STR "unknown" -#define PM_WAKEUP 0 -#define PM_SUSPEND 1 - extern void init_pm_internal(); extern void init_save_userlock(void); @@ -722,7 +719,6 @@ void lcd_on_direct(enum device_flags flags) { if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { - broadcast_pm_wakeup(); power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1446,7 +1442,6 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); @@ -1531,7 +1526,6 @@ go_suspend: #ifdef ENABLE_PM_LOG pm_history_save(PM_LOG_SLEEP, get_pm_cur_state()); #endif - broadcast_pm_suspend(); if (pm_get_power_lock_support()) { power_enable_autosleep(); @@ -2185,7 +2179,6 @@ static void display_init(void *data) if (flags & WITHOUT_STARTNOTI) { /* start without noti */ _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } /* diff --git a/plugins/mobile/display/core.c b/plugins/mobile/display/core.c index ddb7e58..25deced 100644 --- a/plugins/mobile/display/core.c +++ b/plugins/mobile/display/core.c @@ -85,9 +85,6 @@ #define PALM_STR "palm" #define UNKNOWN_STR "unknown" -#define PM_WAKEUP 0 -#define PM_SUSPEND 1 - extern void init_pm_internal(); extern void init_save_userlock(void); @@ -729,7 +726,6 @@ void lcd_on_direct(enum device_flags flags) { if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { - broadcast_pm_wakeup(); power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1456,7 +1452,6 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); @@ -1541,7 +1536,6 @@ go_suspend: #ifdef ENABLE_PM_LOG pm_history_save(PM_LOG_SLEEP, get_pm_cur_state()); #endif - broadcast_pm_suspend(); if (pm_get_power_lock_support()) { power_enable_autosleep(); @@ -2191,7 +2185,6 @@ static void display_init(void *data) if (flags & WITHOUT_STARTNOTI) { /* start without noti */ _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } /* diff --git a/plugins/tv/display/core.c b/plugins/tv/display/core.c index 3dc8fc8..333d3b3 100644 --- a/plugins/tv/display/core.c +++ b/plugins/tv/display/core.c @@ -83,9 +83,6 @@ #define PALM_STR "palm" #define UNKNOWN_STR "unknown" -#define PM_WAKEUP 0 -#define PM_SUSPEND 1 - extern void init_pm_internal(); extern void init_save_userlock(void); @@ -722,7 +719,6 @@ void lcd_on_direct(enum device_flags flags) { if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { - broadcast_pm_wakeup(); power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1446,7 +1442,6 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); @@ -1531,7 +1526,6 @@ go_suspend: #ifdef ENABLE_PM_LOG pm_history_save(PM_LOG_SLEEP, get_pm_cur_state()); #endif - broadcast_pm_suspend(); if (pm_get_power_lock_support()) { power_enable_autosleep(); @@ -2182,7 +2176,6 @@ static void display_init(void *data) if (flags & WITHOUT_STARTNOTI) { /* start without noti */ _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } /* diff --git a/plugins/wearable/display/core.c b/plugins/wearable/display/core.c index 56275ad..baa1784 100644 --- a/plugins/wearable/display/core.c +++ b/plugins/wearable/display/core.c @@ -939,7 +939,6 @@ void lcd_on_direct(enum device_flags flags) if (pm_get_power_lock_support() && (get_pm_cur_state() == S_SLEEP)) { - broadcast_pm_wakeup(); power_acquire_wakelock(); set_pm_cur_state(S_NORMAL); } @@ -1719,7 +1718,6 @@ static int default_action(int timeout) if ((get_pm_cur_state() != get_pm_old_state()) && (get_pm_cur_state() != S_SLEEP)) { if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } set_setting_pmstate(get_pm_cur_state()); @@ -1807,7 +1805,6 @@ go_suspend: #ifdef ENABLE_PM_LOG pm_history_save(PM_LOG_SLEEP, get_pm_cur_state()); #endif - broadcast_pm_suspend(); if (pm_get_power_lock_support()) { power_enable_autosleep(); @@ -2512,7 +2509,6 @@ static void display_init(void *data) if (flags & WITHOUT_STARTNOTI) { /* start without noti */ _I("Start Power managing without noti"); if (pm_get_power_lock_support()) { - broadcast_pm_wakeup(); power_acquire_wakelock(); } /* diff --git a/src/display/display-signal.c b/src/display/display-signal.c index ddb02df..5a08c1b 100644 --- a/src/display/display-signal.c +++ b/src/display/display-signal.c @@ -19,6 +19,7 @@ #include "display-signal.h" #include "poll.h" #include "shared/plugin.h" +#include "shared/time.h" #define ACTIVE_ACT "active" #define INACTIVE_ACT "inactive" @@ -33,52 +34,8 @@ static const char *lcdoff_sig_lookup[SIGNAL_MAX] = { }; static struct display_plugin *disp_plgn; -static int pmstate_suspend = PM_SUSPEND; static long displayoff_time; -void broadcast_pm_suspend(void) -{ - int ret; - long now; - - if (pmstate_suspend) - return; - - _D("PM will be changed to sleep."); - - pmstate_suspend = PM_SUSPEND; - now = clock_gettime_to_long(); - ret = gdbus_signal_emit(NULL, - DEVICED_PATH_DISPLAY, - DEVICED_INTERFACE_DISPLAY, - "sleep", - g_variant_new("(t)", (guint64)now)); - if (ret < 0) - _E("Failed to send dbus signal sleep."); -} - -void broadcast_pm_wakeup(void) -{ - int ret; - long now; - - if (!pmstate_suspend) - return; - - _D("PM is changed to wakeup."); - - pmstate_suspend = PM_WAKEUP; - now = clock_gettime_to_long(); - ret = gdbus_signal_emit(NULL, - DEVICED_PATH_DISPLAY, - DEVICED_INTERFACE_DISPLAY, - "wakeup", - g_variant_new("(t)", (guint64)now)); - if (ret < 0) - _E("Failed to send dbus signal wakeup."); - -} - void broadcast_lcd_on(enum signal_type type, enum device_flags flags) { const char *str; diff --git a/src/display/display-signal.h b/src/display/display-signal.h index f0abbcc..8387352 100644 --- a/src/display/display-signal.h +++ b/src/display/display-signal.h @@ -19,31 +19,12 @@ #ifndef __DISPLAY_SIGNAL_H__ #define __DISPLAY_SIGNAL_H__ -#include #include #include "util.h" #include "shared/devices.h" #include "shared/device-notifier.h" -static inline long clock_gettime_to_long(void) -{ - struct timespec now; - int ret; - - ret = clock_gettime(CLOCK_REALTIME, &now); - - if (ret < 0) { - _E("Failed to clock gettime!"); - return 0; - } - - return SEC_TO_MSEC(now.tv_sec) + NSEC_TO_MSEC(now.tv_nsec); -} - -#define PM_WAKEUP 0 -#define PM_SUSPEND 1 - enum signal_type { SIGNAL_INVALID = 0, SIGNAL_PRE, @@ -51,8 +32,6 @@ enum signal_type { SIGNAL_MAX, }; -void broadcast_pm_suspend(void); -void broadcast_pm_wakeup(void); void broadcast_lcd_on(enum signal_type type, enum device_flags flags); void broadcast_lcd_off(enum signal_type type, enum device_flags flags); void broadcast_lcd_off_late(enum device_flags flags); diff --git a/src/power/power-suspend.c b/src/power/power-suspend.c index c50bcfd..0888af4 100644 --- a/src/power/power-suspend.c +++ b/src/power/power-suspend.c @@ -36,6 +36,7 @@ #include "shared/devices.h" #include "shared/common.h" #include "shared/device-notifier.h" +#include "shared/time.h" #include "vconf.h" #include "display/display-dpms.h" #include "display/display.h" @@ -69,6 +70,49 @@ static const char history_string[PM_LOG_MAX][15] = { bool timeout_sleep_support = false; + +// Leave it for backward compatability. As the signal was implemented when distinction +// between power and display is unclear, path and interface is related with display. +// Since tizen 7.0, it is able to receive suspend/resume event using device power-internal API, +// which is irrelevent with this signal. +static void power_broadcast_suspend(void) +{ + int ret; + long now; + + _D("PM will be changed to sleep."); + + now = clock_gettime_to_long(); + ret = gdbus_signal_emit(NULL, + DEVICED_PATH_DISPLAY, + DEVICED_INTERFACE_DISPLAY, + "sleep", + g_variant_new("(t)", (guint64)now)); + if (ret < 0) + _E("Failed to send dbus signal sleep."); +} + +// Leave it for backward compatability. As the signal was implemented when distinction +// between power and display is unclear, path and interface is related with display. +// Since tizen 7.0, it is able to receive suspend/resume event using device power-internal API, +// which is irrelevent with this signal. +static void power_broadcast_wakeup(void) +{ + int ret; + long now; + + _D("PM is changed to wakeup."); + + now = clock_gettime_to_long(); + ret = gdbus_signal_emit(NULL, + DEVICED_PATH_DISPLAY, + DEVICED_INTERFACE_DISPLAY, + "wakeup", + g_variant_new("(t)", (guint64)now)); + if (ret < 0) + _E("Failed to send dbus signal wakeup."); +} + void pm_history_init() { memset(pm_history_log, 0x0, sizeof(pm_history_log)); @@ -211,9 +255,11 @@ int pm_suspend(void) { int ret_val; + power_broadcast_suspend(); _I("system suspend"); ret_val = sys_set_str(POWER_STATE_PATH, "mem"); _I("System resume: %d", ret_val); + power_broadcast_wakeup(); ret_val = update_wakeup_reason(); if (ret_val < 0) { @@ -242,6 +288,8 @@ int power_acquire_wakelock(void) if (mainlock_status == POWER_LOCK) return 0; + power_broadcast_wakeup(); + _I("system power lock"); suspend_other_process(VITAL_WAKEUP); mainlock_status = POWER_LOCK; @@ -280,6 +328,8 @@ int power_release_wakelock(void) if (mainlock_status == POWER_UNLOCK) return 0; + power_broadcast_suspend(); + _I("system power unlock"); suspend_other_process(VITAL_SLEEP); mainlock_status = POWER_UNLOCK; diff --git a/src/shared/time.c b/src/shared/time.c new file mode 100644 index 0000000..825491f --- /dev/null +++ b/src/shared/time.c @@ -0,0 +1,20 @@ +#include + +#include "log-macro.h" +#include "common.h" + +long clock_gettime_to_long(void) +{ + struct timespec now; + int ret; + + ret = clock_gettime(CLOCK_REALTIME, &now); + + if (ret < 0) { + _E("Failed to clock gettime!"); + return 0; + } + + return SEC_TO_MSEC(now.tv_sec) + NSEC_TO_MSEC(now.tv_nsec); +} + diff --git a/src/shared/time.h b/src/shared/time.h new file mode 100644 index 0000000..85069a3 --- /dev/null +++ b/src/shared/time.h @@ -0,0 +1,6 @@ +#ifndef __DD_TIME_H__ +#define __DD_TIME_H__ + +long clock_gettime_to_long(void); + +#endif //__DD_TIME_H__ -- 2.7.4