#include <glib.h>
#include <gio/gio.h>
-#include "device-error.h"
-
/**
* @platform
* @brief Power off the device.
* @return @c 0 on success,
* otherwise a negative error value
* @retval #DEVICE_ERROR_NONE Successful
- * @retval #DEVICE_ERROR_INVALID_PARAMETER Invalid parameter
* @retval #DEVICE_ERROR_PERMISSION_DENIED Permission denied
* @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed
*/
POWER_STATE_MAX_INDEX,
};
-#define POWER_STATE_START (1ULL << POWER_STATE_START_INDEX)
-#define POWER_STATE_NORMAL (1ULL << POWER_STATE_NORMAL_INDEX)
-#define POWER_STATE_SLEEP (1ULL << POWER_STATE_SLEEP_INDEX)
-#define POWER_STATE_POWEROFF (1ULL << POWER_STATE_POWEROFF_INDEX)
-#define POWER_STATE_REBOOT (1ULL << POWER_STATE_REBOOT_INDEX)
-#define POWER_STATE_EXIT (1ULL << POWER_STATE_EXIT_INDEX)
-#define POWER_STATE_ALL ((1ULL << POWER_STATE_MAX_INDEX) - (1ULL << POWER_STATE_MIN_INDEX))
-
-#define SIGNAME_CHANGE_STATE_TO_START "ChangeStateToStart"
-#define SIGNAME_CHANGE_STATE_TO_NORMAL "ChangeStateToNormal"
-#define SIGNAME_CHANGE_STATE_TO_SLEEP "ChangeStateToSleep"
-#define SIGNAME_CHANGE_STATE_TO_POWEROFF "ChangeStateToPowerOff"
-#define SIGNAME_CHANGE_STATE_TO_REBOOT "ChangeStateToReboot"
-#define SIGNAME_CHANGE_STATE_TO_EXIT "ChangeStateToExit"
+enum {
+ POWER_STATE_TRANSIENT_MIN_INDEX = POWER_STATE_MAX_INDEX + 1,
+ POWER_STATE_TRANSIENT_RESUMING_EARLY_INDEX = POWER_STATE_TRANSIENT_MIN_INDEX,
+ POWER_STATE_TRANSIENT_RESUMING_INDEX,
+ POWER_STATE_TRANSIENT_RESUMING_LATE_INDEX,
+ POWER_STATE_TRANSIENT_SUSPENDING_EARLY_INDEX,
+ POWER_STATE_TRANSIENT_SUSPENDING_INDEX,
+ POWER_STATE_TRANSIENT_SUSPENDING_LATE_INDEX,
+ POWER_STATE_TRANSIENT_MAX_INDEX,
+};
+
+/**
+ * @brief Enumeration for power state.
+ * @since_tizen 6.5
+ */
+typedef enum {
+ POWER_STATE_START = (1ULL << POWER_STATE_START_INDEX), /**< initial state of power module */
+ POWER_STATE_NORMAL = (1ULL << POWER_STATE_NORMAL_INDEX), /**< normal state */
+ POWER_STATE_SLEEP = (1ULL << POWER_STATE_SLEEP_INDEX), /**< sleep state */
+ POWER_STATE_POWEROFF = (1ULL << POWER_STATE_POWEROFF_INDEX), /**< poweroff state */
+ POWER_STATE_REBOOT = (1ULL << POWER_STATE_REBOOT_INDEX), /**< reboot state */
+ POWER_STATE_EXIT = (1ULL << POWER_STATE_EXIT_INDEX), /**< exit state */
+ POWER_STATE_ALL = ((1ULL << POWER_STATE_MAX_INDEX) - (1ULL << POWER_STATE_MIN_INDEX)), /**< all the above states */
+} power_state_e;
+
+/**
+ * @brief Enumeration for transient state.
+ * @details Each enum denotes transient state between static state #power_state_e.
+ * @since_tizen 7.0
+ */
+typedef enum {
+ POWER_STATE_TRANSIENT_RESUMING_EARLY = (1ULL << POWER_STATE_TRANSIENT_RESUMING_EARLY_INDEX), /**< the first step of transitioning from sleep to normal */
+ POWER_STATE_TRANSIENT_RESUMING = (1ULL << POWER_STATE_TRANSIENT_RESUMING_INDEX), /**< the second step of transitioning from sleep to normal */
+ POWER_STATE_TRANSIENT_RESUMING_LATE = (1ULL << POWER_STATE_TRANSIENT_RESUMING_LATE_INDEX), /**< the last step of transitioning from sleep to normal */
+ POWER_STATE_TRANSIENT_SUSPENDING_EARLY = (1ULL << POWER_STATE_TRANSIENT_SUSPENDING_EARLY_INDEX), /**< the first step of transitioning from normal to sleep */
+ POWER_STATE_TRANSIENT_SUSPENDING = (1ULL << POWER_STATE_TRANSIENT_SUSPENDING_INDEX), /**< the second step of transitioning from normal to sleep */
+ POWER_STATE_TRANSIENT_SUSPENDING_LATE = (1ULL << POWER_STATE_TRANSIENT_SUSPENDING_LATE_INDEX), /**< the last step of transitioning from normal to sleep */
+} power_transient_state_e;
struct device_change_state_info {
uint64_t prev_state; /* previous state before the state transition, one of POWER_STATE_* */
};
/**
- * @brief Called when a device power state is changed
- * @details If both power_change_state_wait_callback and power_change_state_callback have registered to the same power state, \n
- * then the power_change_state_wait_callback will be invoked first and the power_change_state_callback will follow.
+ * @brief Called when a device power state is changed.
+ * @details If both power_change_state_wait_callback() and power_change_state_callback() have registered to the same power state, \n
+ * then the power_change_state_wait_callback() will be invoked first and the power_change_state_callback() will follow.
+ * @since_tizen 6.5
* @param[out] info Information about state change
* @param[out] user_data User data passed from the callback registration
*/
typedef void (*power_change_state_wait_callback) (const struct device_change_state_info *info, void *user_data);
/**
- * @brief Add a callback to observe power state change
+ * @brief Add a callback to observe power state change.
* @details Register a callback for specific power state. \n
* The callback will be invoked when the deviced changes state to the designated power state. \n
- * An actual action, such as triggering poweroff on changing state to POWER_STATE_POWEROFF or \n
- * wake unlock on changing state to POWER_STATE_SLEEP, will be deferred to give a chance \n
+ * An actual action, such as triggering poweroff on changing state to #POWER_STATE_POWEROFF or \n
+ * wake unlock on changing state to #POWER_STATE_SLEEP, will be deferred to give a chance \n
* for the API caller to prepare for the action.
- * @sinze_tizen 6.5
- * @param[in] state_bits Bitwise ORed power state
+ * @since_tizen 6.5
+ * @param[in] state_bits Bitwise ORed #power_state_e
* @param[in] cb Callback function
* @param[in] user_data Data to be passed to the callback function
* @return 0 on success,
* @retval #DEVICE_ERROR_NONE Successful
* @retval #DEVICE_ERROR_OPERATION_FAILED Operation failed
*/
-int device_power_add_change_state_wait_callback(uint64_t state_bits, power_change_state_wait_callback cb, void *user_data);
+int device_power_add_change_state_wait_callback(power_state_e state_bits, power_change_state_wait_callback cb, 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
+ * until it is confirmed to be ready to go. \n
+ * @since_tizen 7.0
+ * @param[in] transient_bits Bitwise ORed #power_transient_state_e
+ * @param[in] cb 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_OPERATION_FAILED Operation failed
+ */
+int device_power_add_transient_state_wait_callback(power_transient_state_e transient_bits, 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 API only works on the id received from power_change_state_wait_callback.
+ * This function only works on the id received from power_change_state_wait_callback().
* @since_tizen 6.5
* @param[in] id Id of a state change
* @return 0 on success,
/**
* @brief Remove callback that has registered to power state.
* @since_tizen 6.5
- * @param[in] state_bits Bitwise ORed power state
+ * @param[in] state_bits Bitwise ORed #power_state_e
+ */
+void device_power_remove_change_state_wait_callback(power_state_e state_bits);
+
+/**
+ * @brief Remove callback that has registered to transient power state.
+ * @since_tizen 7.0
+ * @param[in] transient_bits Bitwise ORed #power_transient_state_e
*/
-void device_power_remove_change_state_wait_callback(uint64_t state_bits);
+void device_power_remove_transient_state_wait_callback(power_transient_state_e transient_bits);
/**
* @brief Async callback of device_power_change_state().
- * @details If both power_change_state_wait_callback and power_change_state_callback have registered to the same power state, \n
- * then the power_change_state_wait_callback will be invoked first and the power_change_state_callback will follow.
+ * @details If both power_change_state_wait_callback() and power_change_state_callback() have registered to the same power state, \n
+ * then the power_change_state_wait_callback() will be invoked first and the power_change_state_callback() will follow.
* @since_tizen 6.5
* @param[out] state State to be changed
* @param[out] retval Return of change state
int device_power_change_state(uint64_t state, int timeout_sec, power_change_state_callback cb, void *user_data);
/**
- * @brief Check if reboot is possible on the current device state
+ * @brief Check if reboot is possible on the current device state.
* @since_tizen 6.5
* @return 1 if a device is able to reboot,
* otherwise return 0
}
#endif
-#endif
+#endif /* __TIZEN_SYSTEM_POWER_INTERNAL_H__ */
uint64_t state;
};
-static int change_state_signal_id[POWER_STATE_MAX_INDEX];
+static int change_state_signal_id[POWER_STATE_TRANSIENT_MAX_INDEX];
static void signal_unsubscribed_callback(void *data)
{
h->callback(&info, h->user_data);
}
-static int __device_power_add_change_state_wait_callback(GDBusConnection *connection,
+static int __register_signal_callback(GDBusConnection *connection,
int index, power_change_state_wait_callback cb, void *data)
{
- static const char *signame[POWER_STATE_MAX_INDEX] = {
- [POWER_STATE_START_INDEX] = SIGNAME_CHANGE_STATE_TO_START,
- [POWER_STATE_NORMAL_INDEX] = SIGNAME_CHANGE_STATE_TO_NORMAL,
- [POWER_STATE_SLEEP_INDEX] = SIGNAME_CHANGE_STATE_TO_SLEEP,
- [POWER_STATE_POWEROFF_INDEX] = SIGNAME_CHANGE_STATE_TO_POWEROFF,
- [POWER_STATE_REBOOT_INDEX] = SIGNAME_CHANGE_STATE_TO_REBOOT,
- [POWER_STATE_EXIT_INDEX] = SIGNAME_CHANGE_STATE_TO_EXIT,
+ static const char *signame[POWER_STATE_TRANSIENT_MAX_INDEX] = {
+ [POWER_STATE_START_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START,
+ [POWER_STATE_NORMAL_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL,
+ [POWER_STATE_SLEEP_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP,
+ [POWER_STATE_POWEROFF_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF,
+ [POWER_STATE_REBOOT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT,
+ [POWER_STATE_EXIT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT,
+ [POWER_STATE_TRANSIENT_RESUMING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY,
+ [POWER_STATE_TRANSIENT_RESUMING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING,
+ [POWER_STATE_TRANSIENT_RESUMING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE,
+ [POWER_STATE_TRANSIENT_SUSPENDING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY,
+ [POWER_STATE_TRANSIENT_SUSPENDING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING,
+ [POWER_STATE_TRANSIENT_SUSPENDING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE,
};
struct power_change_state_wait_handler *h;
return DEVICE_ERROR_NONE;
}
-int device_power_add_change_state_wait_callback(uint64_t state_bits, power_change_state_wait_callback cb, void *data)
+static int register_signal_callback(uint64_t states, power_change_state_wait_callback cb, void *data)
{
GDBusConnection *connection;
GVariant *retgv = NULL;
GError *err = NULL;
- if (state_bits == 0)
+ if (states == 0)
return DEVICE_ERROR_NONE;
connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
DEVICED_PATH_POWER,
DEVICED_INTERFACE_POWER,
"AddChangeStateWait",
- g_variant_new("(t)", state_bits),
+ g_variant_new("(t)", states),
NULL,
G_DBUS_CALL_FLAGS_NONE,
DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
}
// subscribe signal
- for (int index = 0; index < POWER_STATE_MAX_INDEX; ++index)
- if((state_bits & (1ULL << index)) && (change_state_signal_id[index] == 0))
- __device_power_add_change_state_wait_callback(connection, index, cb, data);
+ for (int index = 0; index < POWER_STATE_TRANSIENT_MAX_INDEX; ++index)
+ if((states & (1ULL << index)) && (change_state_signal_id[index] == 0))
+ __register_signal_callback(connection, index, cb, data);
return DEVICE_ERROR_NONE;
}
+int device_power_add_change_state_wait_callback(power_state_e state_bits, power_change_state_wait_callback cb, void *data)
+{
+ uint64_t valid = (1ULL << POWER_STATE_MAX_INDEX) - (1ULL << POWER_STATE_MIN_INDEX);
+ uint64_t invalid = (state_bits & ~valid);
+
+ if (invalid)
+ return DEVICE_ERROR_INVALID_PARAMETER;
+
+ return register_signal_callback(state_bits, cb, data);
+}
+
+int device_power_add_transient_state_wait_callback(power_transient_state_e transient_bits, power_change_state_wait_callback cb, void *data)
+{
+ uint64_t valid = (1ULL << POWER_STATE_TRANSIENT_MAX_INDEX) - (1ULL << POWER_STATE_TRANSIENT_MIN_INDEX);
+ uint64_t invalid = (transient_bits & ~valid);
+
+ if (invalid)
+ return DEVICE_ERROR_INVALID_PARAMETER;
+
+ return register_signal_callback(transient_bits, cb, data);
+}
+
int device_power_change_state_wait_done(uint64_t id)
{
GDBusConnection *connection;
return DEVICE_ERROR_NONE;
}
-static void __device_power_remove_change_state_wait_callback(GDBusConnection *connection, int index)
+static void __unregister_signal_callback(GDBusConnection *connection, int index)
{
if (change_state_signal_id[index] == 0)
return;
change_state_signal_id[index] = 0;
}
-void device_power_remove_change_state_wait_callback(uint64_t state_bits)
+static void unregister_signal_callback(uint64_t states)
{
GError *err = NULL;
GDBusConnection *connection;
- if (state_bits == 0)
+ if (states == 0)
return;
connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
}
// unsubscribe signal
- for (int index = 0; index < POWER_STATE_MAX_INDEX; ++index)
- if((state_bits & (1ULL << index)) && (change_state_signal_id[index] > 0))
- __device_power_remove_change_state_wait_callback(connection, index);
+ for (int index = 0; index < POWER_STATE_TRANSIENT_MAX_INDEX; ++index)
+ if((states & (1ULL << index)) && (change_state_signal_id[index] > 0))
+ __unregister_signal_callback(connection, index);
//remove change state wait
g_dbus_connection_call_sync(connection,
DEVICED_PATH_POWER,
DEVICED_INTERFACE_POWER,
"RemoveChangeStateWait",
- g_variant_new("(t)", state_bits),
+ g_variant_new("(t)", states),
NULL,
G_DBUS_CALL_FLAGS_NONE,
DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
NULL,
NULL);
+
+}
+
+void device_power_remove_change_state_wait_callback(power_state_e state_bits)
+{
+ uint64_t valid = (1ULL << POWER_STATE_MAX_INDEX) - (1ULL << POWER_STATE_MIN_INDEX);
+ uint64_t invalid = (state_bits & ~valid);
+
+ if (invalid)
+ return;
+
+ unregister_signal_callback(state_bits);
+}
+
+void device_power_remove_transient_state_wait_callback(power_transient_state_e transient_bits)
+{
+ uint64_t valid = (1ULL << POWER_STATE_TRANSIENT_MAX_INDEX) - (1ULL << POWER_STATE_TRANSIENT_MIN_INDEX);
+ uint64_t invalid = (transient_bits & ~valid);
+
+ if (invalid)
+ return;
+
+ unregister_signal_callback(transient_bits);
+
}
static void change_state_async_callback(GObject *source_object, GAsyncResult *res, gpointer user_data)
GDBusConnection *connection;
struct power_change_state_handler *h = NULL;
+ uint64_t valid = (1ULL << POWER_STATE_MAX_INDEX) - (1ULL << POWER_STATE_MIN_INDEX);
+ uint64_t invalid = (state & ~valid);
+
+ if (invalid)
+ return DEVICE_ERROR_INVALID_PARAMETER;
+
if (!device_power_check_reboot_allowed()) {
if (state == POWER_STATE_POWEROFF) {
_E("Failed to Poweroff due to partition cloning.");