power: add signal handler for wakeup signal
[platform/core/api/device.git] / src / power-internal.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <gio/gio.h>
4 #include <libsyscommon/libgdbus.h>
5
6 #include "power-internal.h"
7 #include "common.h"
8
9 #define SLEEP_DBUS_SIGNAME                  "sleep"
10 #define WAKEUP_DBUS_SIGNAME                 "wakeup"
11 #define DBUS_METHOD_SYNC_CALL_TIMEOUT_MS    10000 /* 10 second */
12
13 struct userdata {
14         void *data;
15         sleep_callback callback;
16 };
17
18 static int sleep_signal_subscribe_id = -1;
19 static int wakeup_signal_subscribe_id = -1;
20
21 static void signal_unsubscribed_callback(void *data)
22 {
23         struct userdata *ud = (struct userdata *) data;
24
25         free(ud);
26 }
27
28 static void handle_sleep_signal(GDBusConnection *connection, GVariant *parameters, void *user_data)
29 {
30         struct userdata *ud = (struct userdata *) user_data;
31         guint64 sig_time_ms;
32         guint64 sleep_id;
33         int retval;
34
35         if (!ud || !ud->callback)
36                 return;
37
38         g_variant_get(parameters, "(tt)", &sig_time_ms, &sleep_id);
39
40         retval = ud->callback(sig_time_ms, DEVICE_SIG_SLEEP_SHORTKEY, ud->data);
41         if (retval == DEVICE_SLEEP_READY) {
42                 g_dbus_connection_call_sync(connection,
43                         DEVICED_BUS_NAME,
44                         DEVICED_PATH_POWER,
45                         DEVICED_INTERFACE_POWER,
46                         "ConfirmSleepWait",
47                         g_variant_new("(i)", sleep_id),
48                         NULL,
49                         G_DBUS_CALL_FLAGS_NONE,
50                         DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
51                         NULL,
52                         NULL);
53         }
54 }
55
56 static void handle_wakeup_signal(GVariant *parameters, void *user_data)
57 {
58         struct userdata *ud = (struct userdata *) user_data;
59         guint64 sig_time_ms;
60         enum device_siginfo siginfo;
61
62         if (!ud || !ud->callback)
63                 return;
64
65         g_variant_get(parameters, "(tt)", &sig_time_ms, &siginfo);
66         ud->callback(sig_time_ms, siginfo, ud->data);
67 }
68
69 static void signal_callback(GDBusConnection *connection,
70         const gchar *sender_name,
71         const gchar *object_path,
72         const gchar *interface_name,
73         const gchar *signal_name,
74         GVariant *parameters,
75         gpointer user_data)
76 {
77
78         if (!strncmp(signal_name, SLEEP_DBUS_SIGNAME, sizeof(SLEEP_DBUS_SIGNAME)))
79                 handle_sleep_signal(connection, parameters, user_data);
80         else if (!strncmp(signal_name, WAKEUP_DBUS_SIGNAME, sizeof(WAKEUP_DBUS_SIGNAME)))
81                 handle_wakeup_signal(parameters, user_data);
82 }
83
84 int device_power_add_sleep_callback(sleep_callback cb, void *data)
85 {
86         GDBusConnection *connection;
87         GVariant *retval;
88         GError *err = NULL;
89         struct userdata *ud;
90
91         if (sleep_signal_subscribe_id != -1)
92                 return DEVICE_ERROR_ALREADY_IN_PROGRESS;
93
94         connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
95         if (!connection) {
96                 _E("Failed to get dbus connection, %s", err->message);
97                 g_clear_error(&err);
98                 return DEVICE_ERROR_OPERATION_FAILED;
99         }
100
101         ud = malloc(sizeof(struct userdata));
102         if (!ud) {
103                 _E("Failed to alloc user data");
104                 return DEVICE_ERROR_OPERATION_FAILED;
105         }
106
107         retval = g_dbus_connection_call_sync(connection,
108                 DEVICED_BUS_NAME,
109                 DEVICED_PATH_POWER,
110                 DEVICED_INTERFACE_POWER,
111                 "AddSleepWait",
112                 NULL,
113                 NULL,
114                 G_DBUS_CALL_FLAGS_NONE,
115                 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
116                 NULL,
117                 &err);
118         if (!retval || err) {
119                 _E("Failed to request AddSleepWait, %s", err->message);
120                 g_error_free(err);
121                 return DEVICE_ERROR_OPERATION_FAILED;
122         }
123
124         ud->data = data;
125         ud->callback = cb;
126
127         sleep_signal_subscribe_id = g_dbus_connection_signal_subscribe(connection,
128                 DEVICED_BUS_NAME,
129                 DEVICED_INTERFACE_POWER,
130                 SLEEP_DBUS_SIGNAME,
131                 DEVICED_PATH_POWER,
132                 NULL,
133                 G_DBUS_SIGNAL_FLAGS_NONE,
134                 signal_callback,
135                 ud,
136                 signal_unsubscribed_callback);
137
138         wakeup_signal_subscribe_id = g_dbus_connection_signal_subscribe(connection,
139                 DEVICED_BUS_NAME,
140                 DEVICED_INTERFACE_POWER,
141                 WAKEUP_DBUS_SIGNAME,
142                 DEVICED_PATH_POWER,
143                 NULL,
144                 G_DBUS_SIGNAL_FLAGS_NONE,
145                 signal_callback,
146                 ud,
147                 NULL);
148
149         return DEVICE_ERROR_NONE;
150 }
151
152 void device_power_remove_sleep_callback(void)
153 {
154         GError *err = NULL;
155         GDBusConnection *connection;
156
157         if (sleep_signal_subscribe_id == -1)
158                 return;
159
160         connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
161         if (!connection) {
162                 _E("Failed to get dbus connection, %s", err->message);
163                 g_clear_error(&err);
164                 return;
165         }
166
167         g_dbus_connection_signal_unsubscribe(connection, sleep_signal_subscribe_id);
168         sleep_signal_subscribe_id = -1;
169         g_dbus_connection_signal_unsubscribe(connection, wakeup_signal_subscribe_id);
170         wakeup_signal_subscribe_id = -1;
171
172         g_dbus_connection_call_sync(connection,
173                 DEVICED_BUS_NAME,
174                 DEVICED_PATH_POWER,
175                 DEVICED_INTERFACE_POWER,
176                 "RemoveSleepWait",
177                 NULL,
178                 NULL,
179                 G_DBUS_CALL_FLAGS_NONE,
180                 DBUS_METHOD_SYNC_CALL_TIMEOUT_MS,
181                 NULL,
182                 NULL);
183 }