From: Youngjae Cho Date: Fri, 9 May 2025 06:38:55 +0000 (+0900) Subject: power: Add checker to verify request before doing transition X-Git-Tag: accepted/tizen/7.0/unified/20250514.161413^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Ftizen_7.0;p=platform%2Fcore%2Fsystem%2Fdeviced.git power: Add checker to verify request before doing transition Previously as for the poweroff/reboot/exit transition, no further requests should've been handled, and it was accomplished by unsubscribing requests right before the action_transition(). However, this function could be deferred depending on how long the other processes hold the transition using device APIs below, giving chance to receive additional requests. - device_power_add_state_wait_callback() - device_power_confirm_wait_callback() To make it thoroughly not receive further requests, checks all the receiving transition requests before processing it. To this end, added check_transition(), verifying whether a transition could be processed, at the beginning of transition routine. This fixes violation of the below assertions at the head of the trigger_transition(). - assert(current != DEVICED_POWER_STATE_POWEROFF); - assert(current != DEVICED_POWER_STATE_REBOOT); - assert(current != DEVICED_POWER_STATE_EXIT); Change-Id: I9f19274acfd9962e395fc2fa348a65833d96dc77 Signed-off-by: Youngjae Cho --- diff --git a/src/power/power.c b/src/power/power.c index 9ccf8de2..2c88044b 100644 --- a/src/power/power.c +++ b/src/power/power.c @@ -333,8 +333,6 @@ static void post_action_sleep(void *udata) static void pre_action_poweroff(void *data) { - // do not transition anymore after poweroff - unregister_notifier(DEVICE_NOTIFIER_REQUEST_TRANSITION_STATE, transition_request_callback); poweroff_prepare(current); } @@ -746,12 +744,43 @@ static gint find_ti_by_state(gconstpointer data, gconstpointer udata) return -1; } +/** + * Checks whether the transition can be validated. + * + * Return 0 on available transition. + * Return negative error on transition that must not be processed. + */ +static int check_transition(const struct trans_info *ti) +{ + if (!ti) { + _E("Invalid transition"); + return -EINVAL; + } + + // Don't allow multiple next state + if (__builtin_popcountll(ti->next & DEVICED_POWER_STATE_ALL) != 1) { + _E("Invalid next state(more then one), curr=%"PRIx64", next=%"PRIx64", reason=%d", + ti->curr, ti->next, ti->reason); + return -EINVAL; + } + + // Prohibit transition from poweroff/reboot/exit state + if (is_poweroff_state(ti->curr)) { + _E("Prohibit transition to %s, it is already at the %s", + state_name(ti->next), state_name(ti->curr)); + return -ESHUTDOWN; + } + + return 0; +} + static int transition_request_callback(void *data) { GList *ti_list, *l; const struct trans_info *t = NULL; struct trans_info ti = { 0 , }; uint64_t available; + int ret; if (!data) return 0; @@ -769,12 +798,6 @@ static int transition_request_callback(void *data) t = l->data; - // check invalid next state - 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; - } - ti = (struct trans_info) { .curr = available, .next = t->next, @@ -782,6 +805,10 @@ static int transition_request_callback(void *data) .data = t->data, }; + ret = check_transition(&ti); + if (ret < 0) + return ret; + // TODO: immediate handling of poweroff? if (!delayed_init_done || transition_context.ongoing) {