*/
int device_power_poweroff(void);
-enum {
- DEVICE_POWER_STATE_MIN_INDEX = 4,
- DEVICE_POWER_STATE_START_INDEX = DEVICE_POWER_STATE_MIN_INDEX,
- DEVICE_POWER_STATE_NORMAL_INDEX,
- DEVICE_POWER_STATE_SLEEP_INDEX,
- DEVICE_POWER_STATE_POWEROFF_INDEX,
- DEVICE_POWER_STATE_REBOOT_INDEX,
- DEVICE_POWER_STATE_EXIT_INDEX,
- DEVICE_POWER_STATE_MAX_INDEX,
-};
-
-enum {
- DEVICE_POWER_STATE_TRANSIENT_MIN_INDEX = DEVICE_POWER_STATE_MAX_INDEX + 1,
- DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY_INDEX = DEVICE_POWER_STATE_TRANSIENT_MIN_INDEX,
- DEVICE_POWER_STATE_TRANSIENT_RESUMING_INDEX,
- DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE_INDEX,
- DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY_INDEX,
- DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_INDEX,
- DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE_INDEX,
- DEVICE_POWER_STATE_TRANSIENT_MAX_INDEX,
-};
+/**
+ * @platform
+ * @brief Reason for what triggered transition.
+ * @since_tizen 7.0
+ */
+typedef enum {
+ DEVICE_POWER_TRANSITION_REASON_UNKNOWN, /**< Unknown reason */
+ DEVICE_POWER_TRANSITION_REASON_POWER_KEY, /**< Power key pressed */
+ DEVICE_POWER_TRANSITION_REASON_BATTERY_NORMAL_LEVEL, /**< Battery capacity reaches normal level*/
+ DEVICE_POWER_TRANSITION_REASON_BATTERY_WARNING_LEVEL, /**< Battery capacity reaches warning level */
+ DEVICE_POWER_TRANSITION_REASON_BATTERY_CRITICAL_LEVEL, /**< Battery capacity reaches critical level */
+ DEVICE_POWER_TRANSITION_REASON_BATTERY_POWEROFF_LEVEL, /**< Battery capacity reaches poweroff level */
+ DEVICE_POWER_TRANSITION_REASON_DISPLAY_OFF, /**< Display off */
+
+ DEVICE_POWER_TRANSITION_REASON_CUSTOM = 1000, /**< Define custom reason from here */
+} device_power_transition_reason_e;
/**
* @brief Enumeration for power state.
* @since_tizen 6.5
*/
typedef enum {
- DEVICE_POWER_STATE_START = (1ULL << DEVICE_POWER_STATE_START_INDEX), /**< initial state of power module */
- DEVICE_POWER_STATE_NORMAL = (1ULL << DEVICE_POWER_STATE_NORMAL_INDEX), /**< normal state */
- DEVICE_POWER_STATE_SLEEP = (1ULL << DEVICE_POWER_STATE_SLEEP_INDEX), /**< sleep state */
- DEVICE_POWER_STATE_POWEROFF = (1ULL << DEVICE_POWER_STATE_POWEROFF_INDEX), /**< poweroff state */
- DEVICE_POWER_STATE_REBOOT = (1ULL << DEVICE_POWER_STATE_REBOOT_INDEX), /**< reboot state */
- DEVICE_POWER_STATE_EXIT = (1ULL << DEVICE_POWER_STATE_EXIT_INDEX), /**< exit state */
- DEVICE_POWER_STATE_ALL = ((1ULL << DEVICE_POWER_STATE_MAX_INDEX) - (1ULL << DEVICE_POWER_STATE_MIN_INDEX)), /**< all the above states */
+ DEVICE_POWER_STATE_START = (1ULL << 4), /**< Initial state of power module. It is especially meaningful in that
+ this can be used to identify the first transition and implement
+ booting UX */
+ DEVICE_POWER_STATE_NORMAL = (1ULL << 5), /**< System keeps running */
+ DEVICE_POWER_STATE_SLEEP = (1ULL << 6), /**< System may be suspended at any time */
+ DEVICE_POWER_STATE_POWEROFF = (1ULL << 7), /**< Prepare for poweroff and perform `systemctl poweroff` */
+ DEVICE_POWER_STATE_REBOOT = (1ULL << 8), /**< Prepare for reboot and perform `systemctl reboot` */
+ DEVICE_POWER_STATE_EXIT = (1ULL << 9), /**< Prepare for exit and perform `systemctl exit` */
} device_power_state_e;
/**
* @brief Enumeration for transient state.
- * @details Each enum denotes transient state between static state #power_state_e.
+ * @details Each enum denotes transient state between static state #device_power_state_e.
* @since_tizen 7.0
*/
typedef enum {
- DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY = (1ULL << DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY_INDEX), /**< the first step of transitioning from sleep to normal */
- DEVICE_POWER_STATE_TRANSIENT_RESUMING = (1ULL << DEVICE_POWER_STATE_TRANSIENT_RESUMING_INDEX), /**< the second step of transitioning from sleep to normal */
- DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE = (1ULL << DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE_INDEX), /**< the last step of transitioning from sleep to normal */
- DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY = (1ULL << DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY_INDEX), /**< the first step of transitioning from normal to sleep */
- DEVICE_POWER_STATE_TRANSIENT_SUSPENDING = (1ULL << DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_INDEX), /**< the second step of transitioning from normal to sleep */
- DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE = (1ULL << DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE_INDEX), /**< the last step of transitioning from normal to sleep */
+ DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY = (1ULL << 4), /**< The first step of transitioning from sleep to normal */
+ DEVICE_POWER_TRANSIENT_STATE_RESUMING = (1ULL << 5), /**< The second step of transitioning from sleep to normal */
+ DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE = (1ULL << 6), /**< The last step of transitioning from sleep to normal */
+ DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY = (1ULL << 7), /**< The first step of transitioning from normal to sleep */
+ DEVICE_POWER_TRANSIENT_STATE_SUSPENDING = (1ULL << 8), /**< The second step of transitioning from normal to sleep */
+ DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE = (1ULL << 9), /**< The last step of transitioning from normal to sleep */
} device_power_transient_state_e;
-struct device_change_state_info {
- uint64_t prev_state; /* previous state before the state transition, one of POWER_STATE_* */
- uint64_t next_state; /* current state that has been transitioned, one of POWER_STATE_* */
- uint64_t id; /* unique id for each transition. it is used for wait-done */
- int reason; /* integer that signifies what event has triggered the transition */
-};
+/**
+ * @brief Notify the deviced that it is ready for the actual action.
+ * @details Notify the deviced that it is ok to take an actual action of change state. \n
+ * This function only works on the id received from device_power_state_wait_callback() and device_power_transient_state_wait_callback().
+ * @since_tizen 6.5
+ * @param[in] wait_done_id Change state id to confirm waiting
+ * @return 0 on success,
+ * otherwise a negative error value
+ * @retval #DEVICE_ERROR_NONE Successful
+ * @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed
+ * @see device_power_state_wait_callback()
+ * @see device_power_transient_state_wait_callback()
+ */
+int device_power_wait_done(uint64_t wait_done_id);
/**
* @brief Called when a device power state is changed.
- * @details If both device_power_change_state_wait_callback() and device_power_change_state_callback() have registered to the same power state, \n
- * then the device_power_change_state_wait_callback() will be invoked first and the device_power_change_state_callback() will follow.
+ * @details If both device_power_state_wait_callback() and device_power_change_state_callback() have registered to the same power state, \n
+ * then the device_power_state_wait_callback() will be invoked first and the device_power_change_state_callback() will follow.
* @since_tizen 6.5
- * @param[out] info Information about state change
+ * @param[out] state Power state to be changed by the transition
+ * @param[out] wait_done_id Transition id
+ * @param[out] transition_reason Reason for what triggered the transition
* @param[out] user_data User data passed from the callback registration
*/
-typedef void (*device_power_change_state_wait_callback) (const struct device_change_state_info *info, void *user_data);
+typedef void (*device_power_state_wait_callback) (device_power_state_e state,
+ uint64_t wait_done_id, device_power_transition_reason_e transition_reason, void *user_data);
/**
* @brief Add a callback to observe power state change.
* otherwise a negative error value
* @retval #DEVICE_ERROR_NONE Successful
* @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed
+ * @see device_power_state_wait_callback()
*/
-int device_power_add_change_state_wait_callback(device_power_state_e state_bits, device_power_change_state_wait_callback cb, void *user_data);
+int device_power_add_state_wait_callback(device_power_state_e state_bits, device_power_state_wait_callback cb, void *user_data);
+
+/**
+ * @brief Remove callback that has registered to power state.
+ * @since_tizen 6.5
+ * @param[in] state_bits Bitwise ORed #device_power_state_e
+ */
+void device_power_remove_state_wait_callback(device_power_state_e state_bits);
+
+/**
+ * @brief Called when a device power state is changed.
+ * @since_tizen 6.5
+ * @param[out] transient_state Transient state to be changed by the transition
+ * @param[out] wait_done_id Transition id
+ * @param[out] transition_reason Reason for what triggered the transition
+ * @param[out] user_data User data passed from the callback registration
+ */
+typedef void (*device_power_transient_state_wait_callback) (device_power_transient_state_e transient_state,
+ uint64_t wait_done_id, device_power_transition_reason_e transition_reason, void *user_data);
/**
* @brief Add a callback to observe transient power state.
* @details Register a callback for specific transient power state. \n
- * The callback will be invoked when the deviced changes state to the designated transient power state. \n
- * Similar to the device_power_add_change_state_wait_callback(), it defers transition to the next state \n
+ * The callback will be invoked in the middle of transition process. \n
+ * Similar to the device_power_add_change_state_wait_callback(), it withholds transition \n
* until it is confirmed to be ready to go. \n
* @since_tizen 7.0
* @param[in] transient_bits Bitwise ORed #device_power_transient_state_e
* otherwise a negative error value
* @retval #DEVICE_ERROR_NONE Successful
* @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed
+ * @see device_power_transient_state_wait_callback()
*/
-int device_power_add_transient_state_wait_callback(device_power_transient_state_e transient_bits, device_power_change_state_wait_callback cb, void *user_data);
-
-/**
- * @brief Notify the deviced that it is ready for the actual action.
- * @details Notify the deviced that it is ok to take an actual action of change state. \n
- * This function only works on the id received from device_power_change_state_wait_callback().
- * @since_tizen 6.5
- * @param[in] id Id of a state change
- * @return 0 on success,
- * otherwise a negative error value
- * @retval #DEVICE_ERROR_NONE Successful
- * @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed
- */
-int device_power_change_state_wait_done(uint64_t id);
-
-/**
- * @brief Remove callback that has registered to power state.
- * @since_tizen 6.5
- * @param[in] state_bits Bitwise ORed #device_power_state_e
- */
-void device_power_remove_change_state_wait_callback(device_power_state_e state_bits);
+int device_power_add_transient_state_wait_callback(device_power_transient_state_e transient_bits,
+ device_power_transient_state_wait_callback cb, void *user_data);
/**
* @brief Remove callback that has registered to transient power state.
/**
* @brief Async callback of device_power_change_state().
- * @details If both device_power_change_state_wait_callback() and device_power_change_state_callback() have registered to the same power state, \n
- * then the device_power_change_state_wait_callback() will be invoked first and the device_power_change_state_callback() will follow.
+ * @details If both device_power_state_wait_callback() and device_power_change_state_callback() have registered to the same power state, \n
+ * then the device_power_state_wait_callback() will be invoked first and the device_power_change_state_callback() will follow.
* @since_tizen 6.5
* @param[out] state State to be changed
* @param[out] retval Return of change state
* @param[out] user_data The user data passed from the change state function
*/
-typedef void (*device_power_change_state_callback) (uint64_t state, int retval, void *user_data);
+typedef void (*device_power_change_state_callback) (device_power_state_e state, int retval, void *user_data);
/**
* @brief Send request for changing power state asynchronously.
* @retval #DEVICE_ERROR_NONE Successful
* @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed
*/
-int device_power_change_state(uint64_t state, int timeout_sec, device_power_change_state_callback cb, void *user_data);
+int device_power_change_state(device_power_state_e state, int timeout_sec, device_power_change_state_callback cb, void *user_data);
/**
* @brief Check if reboot is possible on the current device state.
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <gio/gio.h>
+
#include <libsyscommon/libgdbus.h>
#include <hal/device/hal-board.h>
#define DBUS_METHOD_SYNC_CALL_TIMEOUT_MS 10000 /* 10 second */
-struct power_change_state_wait_handler {
- device_power_change_state_wait_callback callback;
+#define LSB_INDEX(val) (__builtin_ctzll(val))
+#define IS_IN_BETWEEN(val, le, gt) (((le) <= (val) && (val) < (gt)))
+#define IS_STATE_BIT(bit) IS_IN_BETWEEN(bit, \
+ (1ULL << DEVICE_POWER_STATE_MIN_INDEX), \
+ (1ULL << DEVICE_POWER_STATE_MAX_INDEX))
+#define IS_TRANSIENT_STATE_BIT(bit) IS_IN_BETWEEN(bit, \
+ (1ULL << DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX), \
+ (1ULL << DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX))
+
+enum {
+ DEVICE_POWER_STATE_START_INDEX = LSB_INDEX(DEVICE_POWER_STATE_START),
+ DEVICE_POWER_STATE_NORMAL_INDEX = LSB_INDEX(DEVICE_POWER_STATE_NORMAL),
+ DEVICE_POWER_STATE_SLEEP_INDEX = LSB_INDEX(DEVICE_POWER_STATE_SLEEP),
+ DEVICE_POWER_STATE_POWEROFF_INDEX = LSB_INDEX(DEVICE_POWER_STATE_POWEROFF),
+ DEVICE_POWER_STATE_REBOOT_INDEX = LSB_INDEX(DEVICE_POWER_STATE_REBOOT),
+ DEVICE_POWER_STATE_EXIT_INDEX = LSB_INDEX(DEVICE_POWER_STATE_EXIT),
+ /* add state here */
+
+ DEVICE_POWER_STATE_MAX_INDEX,
+ DEVICE_POWER_STATE_MIN_INDEX = DEVICE_POWER_STATE_START_INDEX,
+};
+
+enum {
+ DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY),
+ DEVICE_POWER_TRANSIENT_STATE_RESUMING_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_RESUMING),
+ DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE),
+ DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY),
+ DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_SUSPENDING),
+ DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE),
+ /* add transient state here */
+
+ DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX,
+ DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX = DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX,
+};
+
+static int state_signal_id[DEVICE_POWER_STATE_MAX_INDEX];
+static int transient_state_signal_id[DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX];
+
+struct power_wait_handler {
+ union {
+ device_power_state_wait_callback state_wait_callback;
+ device_power_transient_state_wait_callback transient_state_wait_callback;
+ };
void *user_data;
};
uint64_t state;
};
-static int change_state_signal_id[DEVICE_POWER_STATE_TRANSIENT_MAX_INDEX];
-
static void signal_unsubscribed_callback(void *data)
{
- struct power_change_state_wait_handler *h = (struct power_change_state_wait_handler *) data;
+ struct power_wait_handler *h = (struct power_wait_handler *) data;
free(h);
}
-static void signal_callback(GDBusConnection *connection,
+static void state_signal_callback(GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
GVariant *parameters,
gpointer user_data)
{
- struct device_change_state_info info;
- struct power_change_state_wait_handler *h;
+ struct power_wait_handler *h;
+ uint64_t prev_state, next_state, id;
+ int reason;
- h = (struct power_change_state_wait_handler *) user_data;
+ h = (struct power_wait_handler *) user_data;
- if (!h || !h->callback)
- return;
+ assert(h->state_wait_callback);
- g_variant_get(parameters, "(ttti)", &info.prev_state, &info.next_state, &info.id, &info.reason);
+ g_variant_get(parameters, "(ttti)", &prev_state, &next_state, &id, &reason);
- h->callback(&info, h->user_data);
+ h->state_wait_callback(next_state, id, reason, h->user_data);
}
-static int __register_signal_callback(GDBusConnection *connection,
- int index, device_power_change_state_wait_callback cb, void *data)
+static int __register_state_signal_callback(GDBusConnection *connection,
+ int index, device_power_state_wait_callback cb, void *data)
{
- static const char *signame[DEVICE_POWER_STATE_TRANSIENT_MAX_INDEX] = {
+ static const char *signame[DEVICE_POWER_STATE_MAX_INDEX] = {
[DEVICE_POWER_STATE_START_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START,
[DEVICE_POWER_STATE_NORMAL_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL,
[DEVICE_POWER_STATE_SLEEP_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP,
[DEVICE_POWER_STATE_POWEROFF_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF,
[DEVICE_POWER_STATE_REBOOT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT,
[DEVICE_POWER_STATE_EXIT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT,
- [DEVICE_POWER_STATE_TRANSIENT_RESUMING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY,
- [DEVICE_POWER_STATE_TRANSIENT_RESUMING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING,
- [DEVICE_POWER_STATE_TRANSIENT_RESUMING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE,
- [DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY,
- [DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING,
- [DEVICE_POWER_STATE_TRANSIENT_SUSPENDING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE,
};
- struct power_change_state_wait_handler *h;
- if (change_state_signal_id[index] > 0)
- return DEVICE_ERROR_ALREADY_IN_PROGRESS;
+ struct power_wait_handler *h;
+
+ assert(state_signal_id[index] == 0);
- h = malloc(sizeof(struct power_change_state_wait_handler));
+ h = malloc(sizeof(struct power_wait_handler));
if (!h) {
_E("Failed to alloc user data");
return DEVICE_ERROR_OPERATION_FAILED;
}
- h->callback = cb;
+ h->state_wait_callback = cb;
h->user_data = data;
- change_state_signal_id[index] = g_dbus_connection_signal_subscribe(connection,
+ state_signal_id[index] = g_dbus_connection_signal_subscribe(connection,
DEVICED_BUS_NAME,
DEVICED_INTERFACE_POWER,
signame[index],
DEVICED_PATH_POWER,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
- signal_callback,
+ state_signal_callback,
h,
signal_unsubscribed_callback);
return DEVICE_ERROR_NONE;
}
-static int register_signal_callback(uint64_t states, device_power_change_state_wait_callback cb, void *data)
+static int register_state_signal_callback(uint64_t states, device_power_state_wait_callback cb, void *data)
{
GDBusConnection *connection;
GVariant *retgv = NULL;
}
// subscribe signal
- for (int index = 0; index < DEVICE_POWER_STATE_TRANSIENT_MAX_INDEX; ++index)
- if((states & (1ULL << index)) && (change_state_signal_id[index] == 0))
- __register_signal_callback(connection, index, cb, data);
-
+ for (int index = DEVICE_POWER_STATE_MIN_INDEX; index < DEVICE_POWER_STATE_MAX_INDEX; ++index)
+ if((states & (1ULL << index)) && (state_signal_id[index] == 0))
+ __register_state_signal_callback(connection, index, cb, data);
return DEVICE_ERROR_NONE;
}
-int device_power_add_change_state_wait_callback(device_power_state_e state_bits, device_power_change_state_wait_callback cb, void *data)
+int device_power_add_state_wait_callback(device_power_state_e state_bits,
+ device_power_state_wait_callback cb, void *data)
{
- uint64_t valid = (1ULL << DEVICE_POWER_STATE_MAX_INDEX) - (1ULL << DEVICE_POWER_STATE_MIN_INDEX);
- uint64_t invalid = (state_bits & ~valid);
-
- if (invalid)
+ if (!IS_STATE_BIT(state_bits))
return DEVICE_ERROR_INVALID_PARAMETER;
- return register_signal_callback(state_bits, cb, data);
+ return register_state_signal_callback(state_bits, cb, data);
+}
+
+static void transient_state_signal_callback(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_wait_handler *h;
+ uint64_t prev_state, next_state, id;
+ int reason;
+
+ h = (struct power_wait_handler *) user_data;
+
+ assert(h->transient_state_wait_callback);
+
+ g_variant_get(parameters, "(ttti)", &prev_state, &next_state, &id, &reason);
+
+ h->transient_state_wait_callback(next_state, id, reason, h->user_data);
+}
+
+static int __register_transient_state_signal_callback(GDBusConnection *connection,
+ int index, device_power_transient_state_wait_callback cb, void *data)
+{
+ static const char *signame[DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX] = {
+ [DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY,
+ [DEVICE_POWER_TRANSIENT_STATE_RESUMING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING,
+ [DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE,
+ [DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY,
+ [DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING,
+ [DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE,
+ };
+
+ struct power_wait_handler *h;
+
+ assert(transient_state_signal_id[index] == 0);
+
+ h = malloc(sizeof(struct power_wait_handler));
+ if (!h) {
+ _E("Failed to alloc user data");
+ return DEVICE_ERROR_OPERATION_FAILED;
+ }
+
+ h->transient_state_wait_callback = cb;
+ h->user_data = data;
+
+ transient_state_signal_id[index] = g_dbus_connection_signal_subscribe(connection,
+ DEVICED_BUS_NAME,
+ DEVICED_INTERFACE_POWER,
+ signame[index],
+ DEVICED_PATH_POWER,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ transient_state_signal_callback,
+ h,
+ signal_unsubscribed_callback);
+
+ return DEVICE_ERROR_NONE;
}
-int device_power_add_transient_state_wait_callback(device_power_transient_state_e transient_bits, device_power_change_state_wait_callback cb, void *data)
+static int register_transient_state_signal_callback(uint64_t states, device_power_transient_state_wait_callback cb, void *data)
{
- uint64_t valid = (1ULL << DEVICE_POWER_STATE_TRANSIENT_MAX_INDEX) - (1ULL << DEVICE_POWER_STATE_TRANSIENT_MIN_INDEX);
- uint64_t invalid = (transient_bits & ~valid);
+ GDBusConnection *connection;
+ GVariant *retgv = NULL;
+ GError *err = NULL;
- if (invalid)
+ if (states == 0)
+ return DEVICE_ERROR_NONE;
+
+ 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;
+ }
+
+ // add change state wait
+ retgv = g_dbus_connection_call_sync(connection,
+ DEVICED_BUS_NAME,
+ DEVICED_PATH_POWER,
+ DEVICED_INTERFACE_POWER,
+ "AddChangeTransientStateWait",
+ g_variant_new("(t)", states),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
+ NULL,
+ &err);
+ if (!retgv || err) {
+ _E("Failed to request AddChangeTransientStateWait, %s", err->message);
+ g_error_free(err);
+ return DEVICE_ERROR_OPERATION_FAILED;
+ }
+
+ // subscribe signal
+ for (int index = DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX; index < DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX; ++index)
+ if((states & (1ULL << index)) && (transient_state_signal_id[index] == 0))
+ __register_transient_state_signal_callback(connection, index, cb, data);
+
+ return DEVICE_ERROR_NONE;
+}
+
+int device_power_add_transient_state_wait_callback(device_power_transient_state_e transient_bits,
+ device_power_transient_state_wait_callback cb, void *data)
+{
+ if (!IS_TRANSIENT_STATE_BIT(transient_bits))
return DEVICE_ERROR_INVALID_PARAMETER;
- return register_signal_callback(transient_bits, cb, data);
+ return register_transient_state_signal_callback(transient_bits, cb, data);
}
-int device_power_change_state_wait_done(uint64_t id)
+int device_power_wait_done(uint64_t id)
{
GDBusConnection *connection;
GVariant *retgv;
return DEVICE_ERROR_NONE;
}
-static void __unregister_signal_callback(GDBusConnection *connection, int index)
+static void __unregister_state_signal_callback(GDBusConnection *connection, int index)
{
- if (change_state_signal_id[index] == 0)
+ if (state_signal_id[index] == 0)
return;
- g_dbus_connection_signal_unsubscribe(connection, change_state_signal_id[index]);
- change_state_signal_id[index] = 0;
+ g_dbus_connection_signal_unsubscribe(connection, state_signal_id[index]);
+ state_signal_id[index] = 0;
}
-static void unregister_signal_callback(uint64_t states)
+static void unregister_state_signal_callback(uint64_t states)
{
GError *err = NULL;
GDBusConnection *connection;
}
// unsubscribe signal
- for (int index = 0; index < DEVICE_POWER_STATE_TRANSIENT_MAX_INDEX; ++index)
- if((states & (1ULL << index)) && (change_state_signal_id[index] > 0))
- __unregister_signal_callback(connection, index);
+ for (int index = DEVICE_POWER_STATE_MIN_INDEX; index < DEVICE_POWER_STATE_MAX_INDEX; ++index)
+ if((states & (1ULL << index)) && (state_signal_id[index] > 0))
+ __unregister_state_signal_callback(connection, index);
//remove change state wait
g_dbus_connection_call_sync(connection,
DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
NULL,
NULL);
-
}
-void device_power_remove_change_state_wait_callback(device_power_state_e state_bits)
+void device_power_remove_state_wait_callback(device_power_state_e state_bits)
{
- uint64_t valid = (1ULL << DEVICE_POWER_STATE_MAX_INDEX) - (1ULL << DEVICE_POWER_STATE_MIN_INDEX);
- uint64_t invalid = (state_bits & ~valid);
+ if (!IS_STATE_BIT(state_bits))
+ return;
- if (invalid)
+ unregister_state_signal_callback(state_bits);
+}
+
+static void __unregister_transient_state_signal_callback(GDBusConnection *connection, int index)
+{
+ if (transient_state_signal_id[index] == 0)
return;
- unregister_signal_callback(state_bits);
+ g_dbus_connection_signal_unsubscribe(connection, transient_state_signal_id[index]);
+ transient_state_signal_id[index] = 0;
}
-void device_power_remove_transient_state_wait_callback(device_power_transient_state_e transient_bits)
+static void unregister_transient_state_signal_callback(uint64_t states)
{
- uint64_t valid = (1ULL << DEVICE_POWER_STATE_TRANSIENT_MAX_INDEX) - (1ULL << DEVICE_POWER_STATE_TRANSIENT_MIN_INDEX);
- uint64_t invalid = (transient_bits & ~valid);
+ GError *err = NULL;
+ GDBusConnection *connection;
- if (invalid)
+ if (states == 0)
return;
- unregister_signal_callback(transient_bits);
+ 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;
+ }
+
+ // unsubscribe signal
+ for (int index = DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX; index < DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX; ++index)
+ if((states & (1ULL << index)) && (transient_state_signal_id[index] > 0))
+ __unregister_transient_state_signal_callback(connection, index);
+ //remove change state wait
+ g_dbus_connection_call_sync(connection,
+ DEVICED_BUS_NAME,
+ DEVICED_PATH_POWER,
+ DEVICED_INTERFACE_POWER,
+ "RemoveChangeTransientStateWait",
+ g_variant_new("(t)", states),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
+ NULL,
+ NULL);
+}
+
+void device_power_remove_transient_state_wait_callback(device_power_transient_state_e transient_bits)
+{
+ if (!IS_TRANSIENT_STATE_BIT(transient_bits))
+ return;
+
+ unregister_transient_state_signal_callback(transient_bits);
}
static void change_state_async_callback(GObject *source_object, GAsyncResult *res, gpointer user_data)
free(h);
}
-int device_power_change_state(uint64_t state, int timeout_sec, device_power_change_state_callback cb, void *user_data)
+int device_power_change_state(device_power_state_e state, int timeout_sec, device_power_change_state_callback cb, void *user_data)
{
GError *err = NULL;
GDBusConnection *connection;
struct power_change_state_handler *h = NULL;
- uint64_t valid = (1ULL << DEVICE_POWER_STATE_MAX_INDEX) - (1ULL << DEVICE_POWER_STATE_MIN_INDEX);
- uint64_t invalid = (state & ~valid);
-
- if (invalid)
+ if (!IS_STATE_BIT(state))
return DEVICE_ERROR_INVALID_PARAMETER;
if (!device_power_check_reboot_allowed()) {