power-internal: Add getter and signal subscriber for lock count 40/311640/1 tizen
authorYoungjae Cho <y0.cho@samsung.com>
Thu, 28 Dec 2023 05:30:52 +0000 (14:30 +0900)
committeryoungjae cho <y0.cho@samsung.com>
Thu, 23 May 2024 03:17:16 +0000 (03:17 +0000)
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 <y0.cho@samsung.com>
include/power-internal.h
src/power-internal.c

index da79697..b769ed5 100644 (file)
@@ -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
index 6b095cf..a7b1017 100644 (file)
@@ -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;