7 #include <libsyscommon/libgdbus.h>
8 #include <libsyscommon/list.h>
9 #include <hal/hal-device-board.h>
11 #include "power-internal.h"
14 #define DBUS_METHOD_SYNC_CALL_TIMEOUT_MS 10000 /* 10 second */
15 #define DEVICE_POWER_LOCK_MAX_INDEX (POWER_LOCK_DISPLAY_DIM + 1)
17 #define LSB_INDEX(val) (__builtin_ctzll(val))
18 #define IS_IN_BETWEEN(val, le, gt) (((le) <= (val) && (val) < (gt)))
19 #define IS_STATE_BIT(bit) IS_IN_BETWEEN(bit, \
20 (1ULL << DEVICE_POWER_STATE_MIN_INDEX), \
21 (1ULL << DEVICE_POWER_STATE_MAX_INDEX))
22 #define IS_TRANSIENT_STATE_BIT(bit) IS_IN_BETWEEN(bit, \
23 (1ULL << DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX), \
24 (1ULL << DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX))
27 DEVICE_POWER_STATE_START_INDEX = LSB_INDEX(DEVICE_POWER_STATE_START),
28 DEVICE_POWER_STATE_NORMAL_INDEX = LSB_INDEX(DEVICE_POWER_STATE_NORMAL),
29 DEVICE_POWER_STATE_SLEEP_INDEX = LSB_INDEX(DEVICE_POWER_STATE_SLEEP),
30 DEVICE_POWER_STATE_POWEROFF_INDEX = LSB_INDEX(DEVICE_POWER_STATE_POWEROFF),
31 DEVICE_POWER_STATE_REBOOT_INDEX = LSB_INDEX(DEVICE_POWER_STATE_REBOOT),
32 DEVICE_POWER_STATE_EXIT_INDEX = LSB_INDEX(DEVICE_POWER_STATE_EXIT),
35 DEVICE_POWER_STATE_MAX_INDEX,
36 DEVICE_POWER_STATE_MIN_INDEX = DEVICE_POWER_STATE_START_INDEX,
40 DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY),
41 DEVICE_POWER_TRANSIENT_STATE_RESUMING_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_RESUMING),
42 DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE),
43 DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY),
44 DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_SUSPENDING),
45 DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX = LSB_INDEX(DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE),
46 /* add transient state here */
48 DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX,
49 DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX = DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX,
52 static int state_signal_id[DEVICE_POWER_STATE_MAX_INDEX];
53 static int transient_state_signal_id[DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX];
54 static int power_lock_state_callback_signal_subscription_id[DEVICE_POWER_LOCK_MAX_INDEX];
55 static int power_lock_count_callback_signal_subscription_id[DEVICE_POWER_LOCK_MAX_INDEX];
56 static GList *power_lock_state_callback_list[DEVICE_POWER_LOCK_MAX_INDEX];
57 static GList *power_lock_count_callback_list[DEVICE_POWER_LOCK_MAX_INDEX];
59 struct power_wait_handler {
61 device_power_state_wait_callback state_wait_callback;
62 device_power_transient_state_wait_callback transient_state_wait_callback;
67 struct power_change_state_handler {
68 device_power_change_state_callback callback;
73 struct power_lock_state_change_callback_handler {
74 device_power_lock_state_change_callback callback;
78 //LCOV_EXCL_START Internal function
79 struct power_lock_count_change_callback_handler {
80 device_power_lock_count_change_callback callback;
84 static bool power_is_valid_power_lock_type(power_lock_e power_lock_type)
86 switch(power_lock_type) {
88 case POWER_LOCK_DISPLAY:
89 case POWER_LOCK_DISPLAY_DIM:
96 static void signal_unsubscribed_callback(void *data)
98 struct power_wait_handler *h = (struct power_wait_handler *) data;
103 static void state_signal_callback(GDBusConnection *connection,
104 const gchar *sender_name,
105 const gchar *object_path,
106 const gchar *interface_name,
107 const gchar *signal_name,
108 GVariant *parameters,
111 struct power_wait_handler *h;
112 uint64_t prev_state, next_state, id;
115 h = (struct power_wait_handler *) user_data;
117 assert(h->state_wait_callback);
119 g_variant_get(parameters, "(ttti)", &prev_state, &next_state, &id, &reason);
121 h->state_wait_callback((unsigned int)prev_state, (unsigned int)next_state, id, reason, h->user_data);
124 static int __register_state_signal_callback(GDBusConnection *connection,
125 int index, device_power_state_wait_callback cb, void *data)
127 static const char *signame[DEVICE_POWER_STATE_MAX_INDEX] = {
128 [DEVICE_POWER_STATE_START_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_START,
129 [DEVICE_POWER_STATE_NORMAL_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_NORMAL,
130 [DEVICE_POWER_STATE_SLEEP_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SLEEP,
131 [DEVICE_POWER_STATE_POWEROFF_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_POWEROFF,
132 [DEVICE_POWER_STATE_REBOOT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_REBOOT,
133 [DEVICE_POWER_STATE_EXIT_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_EXIT,
136 struct power_wait_handler *h;
138 assert(state_signal_id[index] == 0);
140 h = malloc(sizeof(struct power_wait_handler));
142 _E("Failed to alloc user data");
143 return DEVICE_ERROR_OPERATION_FAILED;
146 h->state_wait_callback = cb;
149 state_signal_id[index] = g_dbus_connection_signal_subscribe(connection,
151 DEVICED_INTERFACE_POWER,
155 G_DBUS_SIGNAL_FLAGS_NONE,
156 state_signal_callback,
158 signal_unsubscribed_callback);
160 return DEVICE_ERROR_NONE;
163 static int register_state_signal_callback(uint64_t states, device_power_state_wait_callback cb, void *data)
165 GDBusConnection *connection;
166 GVariant *retgv = NULL;
170 return DEVICE_ERROR_NONE;
172 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
174 _E("Failed to get dbus connection, %s", err->message);
176 return DEVICE_ERROR_OPERATION_FAILED;
179 // add change state wait
180 retgv = g_dbus_connection_call_sync(connection,
183 DEVICED_INTERFACE_POWER,
184 "AddChangeStateWait",
185 g_variant_new("(t)", states),
187 G_DBUS_CALL_FLAGS_NONE,
188 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
192 _E("Failed to request AddChangeStateWait, %s", err->message);
194 return DEVICE_ERROR_OPERATION_FAILED;
198 for (int index = DEVICE_POWER_STATE_MIN_INDEX; index < DEVICE_POWER_STATE_MAX_INDEX; ++index)
199 if((states & (1ULL << index)) && (state_signal_id[index] == 0))
200 __register_state_signal_callback(connection, index, cb, data);
202 return DEVICE_ERROR_NONE;
205 int device_power_add_state_wait_callback(device_power_state_e state_bits,
206 device_power_state_wait_callback cb, void *data)
208 if (!IS_STATE_BIT(state_bits))
209 return DEVICE_ERROR_INVALID_PARAMETER;
212 return DEVICE_ERROR_INVALID_PARAMETER;
214 return register_state_signal_callback(state_bits, cb, data);
217 static void transient_state_signal_callback(GDBusConnection *connection,
218 const gchar *sender_name,
219 const gchar *object_path,
220 const gchar *interface_name,
221 const gchar *signal_name,
222 GVariant *parameters,
225 struct power_wait_handler *h;
226 uint64_t prev_state, next_state, id;
229 h = (struct power_wait_handler *) user_data;
231 assert(h->transient_state_wait_callback);
233 g_variant_get(parameters, "(ttti)", &prev_state, &next_state, &id, &reason);
235 h->transient_state_wait_callback((unsigned int)next_state, id, reason, h->user_data);
238 static int __register_transient_state_signal_callback(GDBusConnection *connection,
239 int index, device_power_transient_state_wait_callback cb, void *data)
241 static const char *signame[DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX] = {
242 [DEVICE_POWER_TRANSIENT_STATE_RESUMING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_EARLY,
243 [DEVICE_POWER_TRANSIENT_STATE_RESUMING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING,
244 [DEVICE_POWER_TRANSIENT_STATE_RESUMING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_RESUMING_LATE,
245 [DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_EARLY_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_EARLY,
246 [DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING,
247 [DEVICE_POWER_TRANSIENT_STATE_SUSPENDING_LATE_INDEX] = DEVICED_SIGNAL_POWER_CHANGE_STATE_TO_SUSPENDING_LATE,
250 struct power_wait_handler *h;
252 assert(transient_state_signal_id[index] == 0);
254 h = malloc(sizeof(struct power_wait_handler));
256 _E("Failed to alloc user data");
257 return DEVICE_ERROR_OPERATION_FAILED;
260 h->transient_state_wait_callback = cb;
263 transient_state_signal_id[index] = g_dbus_connection_signal_subscribe(connection,
265 DEVICED_INTERFACE_POWER,
269 G_DBUS_SIGNAL_FLAGS_NONE,
270 transient_state_signal_callback,
272 signal_unsubscribed_callback);
274 return DEVICE_ERROR_NONE;
277 static int register_transient_state_signal_callback(uint64_t states, device_power_transient_state_wait_callback cb, void *data)
279 GDBusConnection *connection;
280 GVariant *retgv = NULL;
284 return DEVICE_ERROR_NONE;
286 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
288 _E("Failed to get dbus connection, %s", err->message);
290 return DEVICE_ERROR_OPERATION_FAILED;
293 // add change state wait
294 retgv = g_dbus_connection_call_sync(connection,
297 DEVICED_INTERFACE_POWER,
298 "AddChangeTransientStateWait",
299 g_variant_new("(t)", states),
301 G_DBUS_CALL_FLAGS_NONE,
302 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
306 _E("Failed to request AddChangeTransientStateWait, %s", err->message);
308 return DEVICE_ERROR_OPERATION_FAILED;
312 for (int index = DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX; index < DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX; ++index)
313 if((states & (1ULL << index)) && (transient_state_signal_id[index] == 0))
314 __register_transient_state_signal_callback(connection, index, cb, data);
316 return DEVICE_ERROR_NONE;
319 int device_power_add_transient_state_wait_callback(device_power_transient_state_e transient_bits,
320 device_power_transient_state_wait_callback cb, void *data)
322 if (!IS_TRANSIENT_STATE_BIT(transient_bits))
323 return DEVICE_ERROR_INVALID_PARAMETER;
326 return DEVICE_ERROR_INVALID_PARAMETER;
328 return register_transient_state_signal_callback(transient_bits, cb, data);
331 int device_power_confirm_wait_callback(uint64_t wait_callback_id)
333 GDBusConnection *connection;
338 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
340 _E("Failed to get dbus connection, %s", err->message);
342 return DEVICE_ERROR_OPERATION_FAILED;
345 retgv = g_dbus_connection_call_sync(connection,
348 DEVICED_INTERFACE_POWER,
349 "ConfirmChangeStateWait",
350 g_variant_new("(t)", wait_callback_id),
352 G_DBUS_CALL_FLAGS_NONE,
353 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
357 _E("Failed to request ConfirmChangeStateWait, %s", err->message);
359 return DEVICE_ERROR_OPERATION_FAILED;
362 g_variant_get(retgv, "(i)", &ret);
363 g_variant_unref(retgv);
365 return DEVICE_ERROR_OPERATION_FAILED;
367 return DEVICE_ERROR_NONE;
370 int device_power_cancel_wait_callback(uint64_t wait_callback_id)
372 GDBusConnection *connection;
377 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
379 _E("Failed to get dbus connection, %s", err->message);
381 return DEVICE_ERROR_OPERATION_FAILED;
384 retgv = g_dbus_connection_call_sync(connection,
387 DEVICED_INTERFACE_POWER,
388 "CancelChangeStateWait",
389 g_variant_new("(t)", wait_callback_id),
391 G_DBUS_CALL_FLAGS_NONE,
392 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
396 _E("Failed to request ConfirmChangeStateWait, %s", err->message);
398 return DEVICE_ERROR_OPERATION_FAILED;
401 g_variant_get(retgv, "(i)", &ret);
402 g_variant_unref(retgv);
404 return DEVICE_ERROR_OPERATION_FAILED;
406 return DEVICE_ERROR_NONE;
409 static void __unregister_state_signal_callback(GDBusConnection *connection, int index)
411 if (state_signal_id[index] == 0)
414 g_dbus_connection_signal_unsubscribe(connection, state_signal_id[index]);
415 state_signal_id[index] = 0;
418 static void unregister_state_signal_callback(uint64_t states)
421 GDBusConnection *connection;
426 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
428 _E("Failed to get dbus connection, %s", err->message);
433 // unsubscribe signal
434 for (int index = DEVICE_POWER_STATE_MIN_INDEX; index < DEVICE_POWER_STATE_MAX_INDEX; ++index)
435 if((states & (1ULL << index)) && (state_signal_id[index] > 0))
436 __unregister_state_signal_callback(connection, index);
438 //remove change state wait
439 g_dbus_connection_call_sync(connection,
442 DEVICED_INTERFACE_POWER,
443 "RemoveChangeStateWait",
444 g_variant_new("(t)", states),
446 G_DBUS_CALL_FLAGS_NONE,
447 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
452 void device_power_remove_state_wait_callback(device_power_state_e state_bits)
454 if (!IS_STATE_BIT(state_bits))
457 unregister_state_signal_callback(state_bits);
460 static void __unregister_transient_state_signal_callback(GDBusConnection *connection, int index)
462 if (transient_state_signal_id[index] == 0)
465 g_dbus_connection_signal_unsubscribe(connection, transient_state_signal_id[index]);
466 transient_state_signal_id[index] = 0;
469 static void unregister_transient_state_signal_callback(uint64_t states)
472 GDBusConnection *connection;
477 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
479 _E("Failed to get dbus connection, %s", err->message);
484 // unsubscribe signal
485 for (int index = DEVICE_POWER_TRANSIENT_STATE_MIN_INDEX; index < DEVICE_POWER_TRANSIENT_STATE_MAX_INDEX; ++index)
486 if((states & (1ULL << index)) && (transient_state_signal_id[index] > 0))
487 __unregister_transient_state_signal_callback(connection, index);
489 //remove change state wait
490 g_dbus_connection_call_sync(connection,
493 DEVICED_INTERFACE_POWER,
494 "RemoveChangeTransientStateWait",
495 g_variant_new("(t)", states),
497 G_DBUS_CALL_FLAGS_NONE,
498 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
503 void device_power_remove_transient_state_wait_callback(device_power_transient_state_e transient_bits)
505 if (!IS_TRANSIENT_STATE_BIT(transient_bits))
508 unregister_transient_state_signal_callback(transient_bits);
511 static void change_state_async_callback(GObject *source_object, GAsyncResult *res, gpointer user_data)
514 GDBusConnection *connection;
517 struct power_change_state_handler *h;
519 h = (struct power_change_state_handler *) user_data;
526 connection = (GDBusConnection *) source_object;
527 retgv = g_dbus_connection_call_finish(connection, res, &err);
530 if (err->code == G_IO_ERROR_TIMED_OUT)
533 _E("Failed to finish async call, %s(%d)", err->message, err->code);
534 h->callback((unsigned int)h->state, retval, h->user_data);
539 g_variant_get(retgv, "(i)", &retval);
540 h->callback((unsigned int)h->state, retval, h->user_data);
548 int device_power_change_state(device_power_state_e state, int timeout_sec, device_power_change_state_callback cb, void *user_data)
551 GDBusConnection *connection;
552 struct power_change_state_handler *h = NULL;
554 if (!IS_STATE_BIT(state))
555 return DEVICE_ERROR_INVALID_PARAMETER;
557 if (!device_power_check_reboot_allowed()) {
558 if (state == DEVICE_POWER_STATE_POWEROFF) {
559 _E("Failed to Poweroff due to partition cloning.");
560 return DEVICE_ERROR_OPERATION_FAILED;
563 if (state == DEVICE_POWER_STATE_REBOOT) {
564 _E("Failed to Reboot due to partition cloning.");
565 return DEVICE_ERROR_OPERATION_FAILED;
570 h = (struct power_change_state_handler *) calloc(1, sizeof(struct power_change_state_handler));
572 _E("Failed to alloc power_change_state_handler.");
573 return DEVICE_ERROR_OPERATION_FAILED;
578 h->user_data = user_data;
581 if (timeout_sec <= 0)
584 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
586 _E("Failed to get dbus connection, %s", err->message);
589 return DEVICE_ERROR_OPERATION_FAILED;
592 g_dbus_connection_call(connection,
595 DEVICED_INTERFACE_POWER,
597 g_variant_new("(t)", (uint64_t)state),
599 G_DBUS_CALL_FLAGS_NONE,
602 change_state_async_callback,
605 return DEVICE_ERROR_NONE;
608 int device_power_check_reboot_allowed(void)
612 retval = hal_device_board_get_partition_ab_cloned(&cloned);
614 return (retval != 0 || cloned != 0);
617 #ifndef EXCLUDE_INTERNAL_CAPI_SYSTEM_DEVICE
618 int device_power_get_wakeup_reason(device_power_transition_reason_e *reason)
623 return DEVICE_ERROR_INVALID_PARAMETER;
625 ret = gdbus_call_sync_with_reply_int(DEVICED_BUS_NAME,
627 DEVICED_INTERFACE_POWER,
628 "PowerGetWakeupReason",
633 _E("Failed to call dbus method to get wakeup reason");
634 return DEVICE_ERROR_OPERATION_FAILED;
638 return DEVICE_ERROR_NONE;
642 static void power_lock_state_change_cb(GDBusConnection *connection,
643 const gchar *sender_name,
644 const gchar *object_path,
645 const gchar *interface_name,
646 const gchar *signal_name,
647 GVariant *parameters,
650 struct power_lock_state_change_callback_handler *callback_handler;
651 power_lock_e power_lock_type;
652 device_power_lock_state_e power_lock_state;
653 GList *callback_list, *elem, *elem_next;
655 g_variant_get(parameters, "(ii)", &power_lock_type, &power_lock_state);
657 callback_list = power_lock_state_callback_list[power_lock_type];
658 SYS_G_LIST_FOREACH_SAFE(callback_list, elem, elem_next, callback_handler)
659 callback_handler->callback(power_lock_type,
660 power_lock_state, callback_handler->data);
663 static void power_lock_count_change_cb(GDBusConnection *connection,
664 const gchar *sender_name,
665 const gchar *object_path,
666 const gchar *interface_name,
667 const gchar *signal_name,
668 GVariant *parameters,
671 struct power_lock_count_change_callback_handler *callback_handler;
672 power_lock_e power_lock_type;
673 int power_lock_count;
674 GList *callback_list, *elem, *elem_next;
676 g_variant_get(parameters, "(ii)", &power_lock_type, &power_lock_count);
678 callback_list = power_lock_count_callback_list[power_lock_type];
679 SYS_G_LIST_FOREACH_SAFE(callback_list, elem, elem_next, callback_handler)
680 callback_handler->callback(power_lock_type,
681 power_lock_count, callback_handler->data);
684 static void destroy_power_lock_state_change_callback_handler(void *data)
686 struct power_lock_state_change_callback_handler *callback_handler =
687 (struct power_lock_state_change_callback_handler *)data;
688 free(callback_handler);
691 int device_power_get_lock_state(power_lock_e power_lock_type,
692 device_power_lock_state_e *power_lock_state)
696 if (!power_is_valid_power_lock_type(power_lock_type)) {
697 _E("Undefined power lock type");
698 return DEVICE_ERROR_INVALID_PARAMETER;
701 if (!power_lock_state) {
702 _E("Invalid parameters");
703 return DEVICE_ERROR_INVALID_PARAMETER;
706 ret = gdbus_call_sync_with_reply_int(DEVICED_BUS_NAME,
707 DEVICED_PATH_DISPLAY,
708 DEVICED_INTERFACE_DISPLAY,
709 "PmlockGetLockState",
710 g_variant_new("(i)", (int)power_lock_type),
713 _E("Failed to call dbus method to get power lock state, return value(%d)", ret);
714 return errno_to_device_error(ret);
717 *power_lock_state = (bool)reply;
719 return DEVICE_ERROR_NONE;
722 int device_power_get_lock_count(power_lock_e power_lock_type,
723 int *power_lock_count)
727 if (!power_is_valid_power_lock_type(power_lock_type)) {
728 _E("Undefined power lock type");
729 return DEVICE_ERROR_INVALID_PARAMETER;
732 if (!power_lock_count) {
733 _E("Invalid parameters");
734 return DEVICE_ERROR_INVALID_PARAMETER;
737 ret = gdbus_call_sync_with_reply_int(DEVICED_BUS_NAME,
738 DEVICED_PATH_DISPLAY,
739 DEVICED_INTERFACE_DISPLAY,
740 "PmlockGetLockCount",
741 g_variant_new("(i)", (int)power_lock_type),
744 _E("Failed to call dbus method to get power lock count, return value(%d)", ret);
745 return errno_to_device_error(ret);
748 *power_lock_count = reply;
750 return DEVICE_ERROR_NONE;
753 int device_power_add_lock_state_change_callback(power_lock_e power_lock_type,
754 device_power_lock_state_change_callback power_lock_state_change_callback,
758 GDBusConnection *connection;
759 int signal_subscription_id = 0;
761 if (!power_is_valid_power_lock_type(power_lock_type)) {
762 _E("Undefined power lock type");
763 return DEVICE_ERROR_INVALID_PARAMETER;
766 if (!power_lock_state_change_callback) {
767 _E("Invalid parameters");
768 return DEVICE_ERROR_INVALID_PARAMETER;
771 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
773 _E("Failed to get dbus connection, %s", err->message);
775 return DEVICE_ERROR_OPERATION_FAILED;
778 struct power_lock_state_change_callback_handler *callback_handler;
780 callback_handler = malloc(sizeof(struct power_lock_state_change_callback_handler));
781 if (!callback_handler) {
782 _E("Cannot alloc memory for power lock state change callback");
783 return DEVICE_ERROR_OPERATION_FAILED;
785 callback_handler->callback = power_lock_state_change_callback;
786 callback_handler->data = user_data;
788 if (power_lock_state_callback_signal_subscription_id[power_lock_type] == 0) {
789 signal_subscription_id = g_dbus_connection_signal_subscribe(connection,
791 DEVICED_INTERFACE_DISPLAY,
792 DEVICED_SIGNAL_POWER_LOCK_STATE_CHANGED,
793 DEVICED_PATH_DISPLAY,
795 G_DBUS_SIGNAL_FLAGS_NONE,
796 power_lock_state_change_cb,
798 destroy_power_lock_state_change_callback_handler);
799 power_lock_state_callback_signal_subscription_id[power_lock_type] =
800 signal_subscription_id;
803 power_lock_state_callback_list[power_lock_type] =
804 g_list_append(power_lock_state_callback_list[power_lock_type], callback_handler);
806 return DEVICE_ERROR_NONE;
809 int device_power_remove_lock_state_change_callback(power_lock_e power_lock_type,
810 device_power_lock_state_change_callback power_lock_state_change_callback)
812 struct power_lock_state_change_callback_handler *callback_handler;
813 GList **callback_list;
814 GList *elem, *elem_next;
816 GDBusConnection *connection;
818 if (!power_is_valid_power_lock_type(power_lock_type)) {
819 _E("Undefined power lock type");
820 return DEVICE_ERROR_INVALID_PARAMETER;
823 if (!power_lock_state_change_callback) {
824 _E("Invalid parameters");
825 return DEVICE_ERROR_INVALID_PARAMETER;
828 callback_list = &power_lock_state_callback_list[power_lock_type];
829 if (g_list_length(*callback_list) <= 0) {
830 _W("No callback functions for power_lock_type(%d)", power_lock_type);
831 return DEVICE_ERROR_NONE;
834 SYS_G_LIST_FOREACH_SAFE(*callback_list, elem, elem_next, callback_handler) {
835 if (callback_handler->callback == power_lock_state_change_callback)
839 SYS_G_LIST_REMOVE(*callback_list, callback_handler);
840 free(callback_handler);
842 if (SYS_G_LIST_LENGTH(*callback_list) == 0) {
843 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
845 _E("Failed to get dbus connection, %s", err->message);
847 return DEVICE_ERROR_OPERATION_FAILED;
849 g_dbus_connection_signal_unsubscribe(connection,
850 power_lock_state_callback_signal_subscription_id[power_lock_type]);
851 power_lock_state_callback_signal_subscription_id[power_lock_type] = 0;
854 return DEVICE_ERROR_NONE;
857 int device_power_add_lock_count_change_callback(power_lock_e power_lock_type,
858 device_power_lock_count_change_callback power_lock_count_change_callback,
862 GDBusConnection *connection;
863 int signal_subscription_id = 0;
865 if (!power_is_valid_power_lock_type(power_lock_type)) {
866 _E("Undefined power lock type");
867 return DEVICE_ERROR_INVALID_PARAMETER;
870 if (!power_lock_count_change_callback) {
871 _E("Invalid parameters");
872 return DEVICE_ERROR_INVALID_PARAMETER;
875 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
877 _E("Failed to get dbus connection, %s", err->message);
879 return DEVICE_ERROR_OPERATION_FAILED;
882 struct power_lock_count_change_callback_handler *callback_handler;
884 callback_handler = malloc(sizeof(struct power_lock_count_change_callback_handler));
885 if (!callback_handler) {
886 _E("Cannot alloc memory for power lock count change callback");
887 return DEVICE_ERROR_OPERATION_FAILED;
889 callback_handler->callback = power_lock_count_change_callback;
890 callback_handler->data = user_data;
892 if (power_lock_count_callback_signal_subscription_id[power_lock_type] == 0) {
893 signal_subscription_id = g_dbus_connection_signal_subscribe(connection,
895 DEVICED_INTERFACE_DISPLAY,
896 DEVICED_SIGNAL_POWER_LOCK_COUNT_CHANGED,
897 DEVICED_PATH_DISPLAY,
899 G_DBUS_SIGNAL_FLAGS_NONE,
900 power_lock_count_change_cb,
903 power_lock_count_callback_signal_subscription_id[power_lock_type] =
904 signal_subscription_id;
907 power_lock_count_callback_list[power_lock_type] =
908 g_list_append(power_lock_count_callback_list[power_lock_type], callback_handler);
910 return DEVICE_ERROR_NONE;
913 int device_power_remove_lock_count_change_callback(power_lock_e power_lock_type,
914 device_power_lock_count_change_callback power_lock_count_change_callback)
916 struct power_lock_count_change_callback_handler *callback_handler;
917 GList **callback_list;
918 GList *elem, *elem_next;
920 GDBusConnection *connection;
922 if (!power_is_valid_power_lock_type(power_lock_type)) {
923 _E("Undefined power lock type");
924 return DEVICE_ERROR_INVALID_PARAMETER;
927 if (!power_lock_count_change_callback) {
928 _E("Invalid parameters");
929 return DEVICE_ERROR_INVALID_PARAMETER;
932 callback_list = &power_lock_count_callback_list[power_lock_type];
933 if (g_list_length(*callback_list) <= 0) {
934 _W("No callback functions for power_lock_type(%d)", power_lock_type);
935 return DEVICE_ERROR_NONE;
938 SYS_G_LIST_FOREACH_SAFE(*callback_list, elem, elem_next, callback_handler) {
939 if (callback_handler->callback == power_lock_count_change_callback)
943 SYS_G_LIST_REMOVE(*callback_list, callback_handler);
944 free(callback_handler);
946 if (SYS_G_LIST_LENGTH(*callback_list) == 0) {
947 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
949 _E("Failed to get dbus connection, %s", err->message);
951 return DEVICE_ERROR_OPERATION_FAILED;
953 g_dbus_connection_signal_unsubscribe(connection,
954 power_lock_count_callback_signal_subscription_id[power_lock_type]);
955 power_lock_count_callback_signal_subscription_id[power_lock_type] = 0;
958 return DEVICE_ERROR_NONE;