From: Youngjae Cho Date: Thu, 28 Dec 2023 05:30:52 +0000 (+0900) Subject: power-internal: Add getter and signal subscriber for lock count X-Git-Tag: accepted/tizen/unified/20240614.084913^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F40%2F311640%2F1;p=platform%2Fcore%2Fapi%2Fdevice.git power-internal: Add getter and signal subscriber for lock count int device_power_get_lock_count() : Get the current lock count that hasn't yet been unlocked. int device_power_add_lock_count_change_callback() : Register callback function that is invoked on lock count changed. The lock count is increased by 1 on device_power_request_lock(), decreased by 1 on device_power_release_lock() or timeout. int device_power_remove_lock_count_change_callback() : Unregister the callback registered by the above. Change-Id: Ib77260c867a27013572ee42ab1264ad3c3e5794e Signed-off-by: Youngjae Cho --- diff --git a/include/power-internal.h b/include/power-internal.h index da79697..b769ed5 100644 --- a/include/power-internal.h +++ b/include/power-internal.h @@ -283,6 +283,16 @@ typedef void (*device_power_lock_state_change_callback) (power_lock_e power_lock device_power_lock_state_e power_lock_state, void *user_data); /** + * @brief Called when the registered power lock is changed. + * @since_tizen 7.0 + * @param[out] power_lock_type Type of power lock + * @param[out] power_lock_count Number of power lock + * @param[out] user_data User data passed from the callback registration + */ +typedef void (*device_power_lock_count_change_callback) (power_lock_e power_lock_type, + int power_lock_count, void *user_data); + +/** * @brief Gets the status of power lock. * @since_tizen 7.0 * @param[in] power_lock_type Type of power lock @@ -296,6 +306,19 @@ int device_power_get_lock_state(power_lock_e power_lock_type, device_power_lock_state_e *power_lock_state); /** + * @brief Gets the status of power lock. + * @since_tizen 7.0 + * @param[in] power_lock_type Type of power lock + * @param[out] power_lock_count Number of power lock to be get + * @return 0 on success, + * otherwise a negative error value + * @retval #DEVICE_ERROR_NONE Successful + * @retval #DEVICE_ERROR_INVALID_PARAMETER Invalid parameter + */ +int device_power_get_lock_count(power_lock_e power_lock_type, + int *power_lock_count); + +/** * @brief Add a callback to observe status of registered specific power lock. * @details The callback will be invoked when the power lock is changed * @since_tizen 7.0 @@ -328,6 +351,39 @@ int device_power_add_lock_state_change_callback(power_lock_e power_lock_type, int device_power_remove_lock_state_change_callback(power_lock_e power_lock_type, device_power_lock_state_change_callback power_lock_state_change_callback); +/** + * @brief Add a callback to observe status of registered specific power lock. + * @details The callback will be invoked when the power lock is changed + * @since_tizen 7.0 + * @param[in] power_lock_type Power lock type to be observed + * @param[in] power_lock_count_change_callback Callback function + * @param[in] user_data Data to be passed to the callback function + * @return 0 on success, + * otherwise a negative error value + * @retval #DEVICE_ERROR_NONE Successful + * @retval #DEVICE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed + * @see device_power_request_lock() + * @see device_power_release_lock() + */ +int device_power_add_lock_count_change_callback(power_lock_e power_lock_type, + device_power_lock_count_change_callback power_lock_count_change_callback, + void *user_data); + +/** + * @brief Remove callback that has registered to power lock type. + * @since_tizen 7.0 + * @param[in] power_lock_type Type of power lock + * @param[in] power_lock_count_change_callback Callback function to be removed + * @return 0 on success, + * otherwise a negative error value + * @retval #DEVICE_ERROR_NONE Successful + * @retval #DEVICE_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed + */ +int device_power_remove_lock_count_change_callback(power_lock_e power_lock_type, + device_power_lock_count_change_callback power_lock_count_change_callback); + #ifdef __cplusplus } #endif diff --git a/src/power-internal.c b/src/power-internal.c index 6b095cf..a7b1017 100644 --- a/src/power-internal.c +++ b/src/power-internal.c @@ -51,8 +51,10 @@ enum { static int state_signal_id[DEVICE_POWER_STATE_MAX_INDEX]; static int transient_state_signal_id[DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX]; -static int power_lock_callback_signal_subscription_id[DEVICE_POWER_LOCK_MAX_INDEX]; -static GList *power_lock_callback_list[DEVICE_POWER_LOCK_MAX_INDEX]; +static int power_lock_state_callback_signal_subscription_id[DEVICE_POWER_LOCK_MAX_INDEX]; +static int power_lock_count_callback_signal_subscription_id[DEVICE_POWER_LOCK_MAX_INDEX]; +static GList *power_lock_state_callback_list[DEVICE_POWER_LOCK_MAX_INDEX]; +static GList *power_lock_count_callback_list[DEVICE_POWER_LOCK_MAX_INDEX]; struct power_wait_handler { union { @@ -74,6 +76,11 @@ struct power_lock_state_change_callback_handler { }; //LCOV_EXCL_START Internal function +struct power_lock_count_change_callback_handler { + device_power_lock_count_change_callback callback; + void *data; +}; + static bool power_is_valid_power_lock_type(power_lock_e power_lock_type) { switch(power_lock_type) { @@ -647,12 +654,33 @@ static void power_lock_state_change_cb(GDBusConnection *connection, g_variant_get(parameters, "(ii)", &power_lock_type, &power_lock_state); - callback_list = power_lock_callback_list[power_lock_type]; + callback_list = power_lock_state_callback_list[power_lock_type]; SYS_G_LIST_FOREACH_SAFE(callback_list, elem, elem_next, callback_handler) callback_handler->callback(power_lock_type, power_lock_state, callback_handler->data); } +static void power_lock_count_change_cb(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + struct power_lock_count_change_callback_handler *callback_handler; + power_lock_e power_lock_type; + int power_lock_count; + GList *callback_list, *elem, *elem_next; + + g_variant_get(parameters, "(ii)", &power_lock_type, &power_lock_count); + + callback_list = power_lock_count_callback_list[power_lock_type]; + SYS_G_LIST_FOREACH_SAFE(callback_list, elem, elem_next, callback_handler) + callback_handler->callback(power_lock_type, + power_lock_count, callback_handler->data); +} + static void destroy_power_lock_state_change_callback_handler(void *data) { struct power_lock_state_change_callback_handler *callback_handler = @@ -691,6 +719,36 @@ int device_power_get_lock_state(power_lock_e power_lock_type, return DEVICE_ERROR_NONE; } +int device_power_get_lock_count(power_lock_e power_lock_type, + int *power_lock_count) +{ + int ret, reply; + + if (!power_is_valid_power_lock_type(power_lock_type)) { + _E("Undefined power lock type"); + return DEVICE_ERROR_INVALID_PARAMETER; + } + + if (!power_lock_count) { + _E("Invalid parameters"); + return DEVICE_ERROR_INVALID_PARAMETER; + } + + ret = gdbus_call_sync_with_reply_int(DEVICED_BUS_NAME, + DEVICED_PATH_DISPLAY, + DEVICED_INTERFACE_DISPLAY, + "PmlockGetLockCount", + g_variant_new("(i)", (int)power_lock_type), + &reply); + if (ret < 0) { + _E("Failed to call dbus method to get power lock count, return value(%d)", ret); + return errno_to_device_error(ret); + } + + *power_lock_count = reply; + + return DEVICE_ERROR_NONE; +} int device_power_add_lock_state_change_callback(power_lock_e power_lock_type, device_power_lock_state_change_callback power_lock_state_change_callback, @@ -727,7 +785,7 @@ int device_power_add_lock_state_change_callback(power_lock_e power_lock_type, callback_handler->callback = power_lock_state_change_callback; callback_handler->data = user_data; - if (power_lock_callback_signal_subscription_id[power_lock_type] == 0) { + if (power_lock_state_callback_signal_subscription_id[power_lock_type] == 0) { signal_subscription_id = g_dbus_connection_signal_subscribe(connection, DEVICED_BUS_NAME, DEVICED_INTERFACE_DISPLAY, @@ -738,12 +796,12 @@ int device_power_add_lock_state_change_callback(power_lock_e power_lock_type, power_lock_state_change_cb, NULL, destroy_power_lock_state_change_callback_handler); - power_lock_callback_signal_subscription_id[power_lock_type] = + power_lock_state_callback_signal_subscription_id[power_lock_type] = signal_subscription_id; } - power_lock_callback_list[power_lock_type] = - g_list_append(power_lock_callback_list[power_lock_type], callback_handler); + power_lock_state_callback_list[power_lock_type] = + g_list_append(power_lock_state_callback_list[power_lock_type], callback_handler); return DEVICE_ERROR_NONE; } @@ -767,7 +825,7 @@ int device_power_remove_lock_state_change_callback(power_lock_e power_lock_type, return DEVICE_ERROR_INVALID_PARAMETER; } - callback_list = &power_lock_callback_list[power_lock_type]; + callback_list = &power_lock_state_callback_list[power_lock_type]; if (g_list_length(*callback_list) <= 0) { _W("No callback functions for power_lock_type(%d)", power_lock_type); return DEVICE_ERROR_NONE; @@ -789,8 +847,112 @@ int device_power_remove_lock_state_change_callback(power_lock_e power_lock_type, return DEVICE_ERROR_OPERATION_FAILED; } g_dbus_connection_signal_unsubscribe(connection, - power_lock_callback_signal_subscription_id[power_lock_type]); - power_lock_callback_signal_subscription_id[power_lock_type] = 0; + power_lock_state_callback_signal_subscription_id[power_lock_type]); + power_lock_state_callback_signal_subscription_id[power_lock_type] = 0; + } + + return DEVICE_ERROR_NONE; +} + +int device_power_add_lock_count_change_callback(power_lock_e power_lock_type, + device_power_lock_count_change_callback power_lock_count_change_callback, + void *user_data) +{ + GError *err = NULL; + GDBusConnection *connection; + int signal_subscription_id = 0; + + if (!power_is_valid_power_lock_type(power_lock_type)) { + _E("Undefined power lock type"); + return DEVICE_ERROR_INVALID_PARAMETER; + } + + if (!power_lock_count_change_callback) { + _E("Invalid parameters"); + return DEVICE_ERROR_INVALID_PARAMETER; + } + + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!connection) { + _E("Failed to get dbus connection, %s", err->message); + g_clear_error(&err); + return DEVICE_ERROR_OPERATION_FAILED; + } + + struct power_lock_count_change_callback_handler *callback_handler; + + callback_handler = malloc(sizeof(struct power_lock_count_change_callback_handler)); + if (!callback_handler) { + _E("Cannot alloc memory for power lock count change callback"); + return DEVICE_ERROR_OPERATION_FAILED; + } + callback_handler->callback = power_lock_count_change_callback; + callback_handler->data = user_data; + + if (power_lock_count_callback_signal_subscription_id[power_lock_type] == 0) { + signal_subscription_id = g_dbus_connection_signal_subscribe(connection, + DEVICED_BUS_NAME, + DEVICED_INTERFACE_DISPLAY, + DEVICED_SIGNAL_POWER_LOCK_COUNT_CHANGED, + DEVICED_PATH_DISPLAY, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + power_lock_count_change_cb, + NULL, + NULL); + power_lock_count_callback_signal_subscription_id[power_lock_type] = + signal_subscription_id; + } + + power_lock_count_callback_list[power_lock_type] = + g_list_append(power_lock_count_callback_list[power_lock_type], callback_handler); + + return DEVICE_ERROR_NONE; +} + +int device_power_remove_lock_count_change_callback(power_lock_e power_lock_type, + device_power_lock_count_change_callback power_lock_count_change_callback) +{ + struct power_lock_count_change_callback_handler *callback_handler; + GList **callback_list; + GList *elem, *elem_next; + GError *err = NULL; + GDBusConnection *connection; + + if (!power_is_valid_power_lock_type(power_lock_type)) { + _E("Undefined power lock type"); + return DEVICE_ERROR_INVALID_PARAMETER; + } + + if (!power_lock_count_change_callback) { + _E("Invalid parameters"); + return DEVICE_ERROR_INVALID_PARAMETER; + } + + callback_list = &power_lock_count_callback_list[power_lock_type]; + if (g_list_length(*callback_list) <= 0) { + _W("No callback functions for power_lock_type(%d)", power_lock_type); + return DEVICE_ERROR_NONE; + } + + SYS_G_LIST_FOREACH_SAFE(*callback_list, elem, elem_next, callback_handler) { + if (callback_handler->callback == power_lock_count_change_callback) + break; + } + + SYS_G_LIST_REMOVE(*callback_list, callback_handler); + free(callback_handler); + + if (SYS_G_LIST_LENGTH(*callback_list) == 0) { + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!connection) { + _E("Failed to get dbus connection, %s", err->message); + g_clear_error(&err); + return DEVICE_ERROR_OPERATION_FAILED; + } + g_dbus_connection_signal_unsubscribe(connection, + power_lock_count_callback_signal_subscription_id[power_lock_type]); + power_lock_count_callback_signal_subscription_id[power_lock_type] = 0; } return DEVICE_ERROR_NONE;