Remove security-server dependency
[apps/core/preloaded/lockscreen.git] / src / dbus.c
1 /*
2  * Copyright (c) 2009-2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <Elementary.h>
18 #include <dbus/dbus-glib.h>
19 #include <dbus/dbus-glib-lowlevel.h>
20
21 #include "lockscreen.h"
22 #include "log.h"
23 #include "dbus.h"
24 #include "property.h"
25 #include "lock_time.h"
26 #include "default_lock.h"
27
28 static struct _s_info {
29         DBusConnection *connection;
30         Eina_List *cbs_list[DBUS_EVENT_MAX];
31         int is_rotate_signal_added;
32 } s_info = {
33         .connection = NULL,
34         .cbs_list = { NULL, },
35         .is_rotate_signal_added = 0,
36 };
37
38 typedef struct {
39         void (*result_cb)(void *, void *);
40         void *result_data;
41 } dbus_cb_s;
42
43 static void _execute_cbs(int type, void *event_info)
44 {
45         dbus_cb_s *cb = NULL;
46
47         Eina_List *list = eina_list_clone(s_info.cbs_list[type]);
48         EINA_LIST_FREE(list, cb) {
49                 continue_if(!cb);
50                 continue_if(!cb->result_cb);
51
52                 cb->result_cb(cb->result_data, event_info);
53         }
54 }
55
56 static void _cbs_fini(void)
57 {
58         int i = 0;
59
60         const Eina_List *l = NULL;
61         const Eina_List *n = NULL;
62         dbus_cb_s *cb = NULL;
63
64         for (i = 0; i < DBUS_EVENT_MAX; i++) {
65                 EINA_LIST_FOREACH_SAFE(s_info.cbs_list[i], l, n, cb) {
66                         free(cb);
67                 }
68         }
69 }
70
71 static DBusConnection *_dbus_connection_get(void)
72 {
73         if (!s_info.connection) {
74                 DBusError derror;
75                 DBusConnection *connection = NULL;
76
77                 dbus_error_init(&derror);
78                 connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &derror);
79                 if (!connection) {
80                         _E("Failed to get dbus connection : %s", derror.message);
81                         dbus_error_free(&derror);
82                         return NULL;
83                 }
84                 dbus_connection_setup_with_g_main(connection, NULL);
85                 dbus_error_free(&derror);
86
87                 s_info.connection = connection;
88         }
89
90         return s_info.connection;
91 }
92
93 static DBusHandlerResult _dbus_message_recv_cb(DBusConnection *connection, DBusMessage *message, void *data)
94 {
95         if (dbus_message_is_signal(message, DBUS_DEVICED_DISPLAY_INTERFACE, DBUS_DEVICED_DISPLAY_MEMBER_LCD_ON)) {
96                 _I("LCD on");
97                 int ret = 0;
98                 DBusError derror;
99                 const char *state = NULL;
100                 dbus_error_init(&derror);
101                 ret = dbus_message_get_args(message, &derror, DBUS_TYPE_STRING, &state, DBUS_TYPE_INVALID);
102                 if (!ret) {
103                         _E("Failed to get reply (%s:%s)", derror.name, derror.message);
104                 }
105                 _execute_cbs(DBUS_EVENT_LCD_ON, (void*)state);
106                 dbus_error_free(&derror);
107         } else if (dbus_message_is_signal(message, DBUS_DEVICED_DISPLAY_INTERFACE, DBUS_DEVICED_DISPLAY_MEMBER_LCD_OFF)) {
108                 _I("LCD off");
109                 int ret = 0;
110                 DBusError derror;
111                 const char *state = NULL;
112                 dbus_error_init(&derror);
113                 ret = dbus_message_get_args(message, &derror, DBUS_TYPE_STRING, &state, DBUS_TYPE_INVALID);
114                 if (!ret) {
115                         _E("Failed to get reply (%s:%s)", derror.name, derror.message);
116                 }
117                 _execute_cbs(DBUS_EVENT_LCD_OFF, (void*)state);
118                 dbus_error_free(&derror);
119         } else if (dbus_message_is_signal(message, DBUS_ROTATION_INTERFACE, DBUS_ROTATION_MEMBER_CHANGED)) {
120                 int ret = 0;
121                 DBusError derror;
122                 int state = 0;
123                 dbus_error_init(&derror);
124                 ret = dbus_message_get_args(message, &derror, DBUS_TYPE_INT32, &state, DBUS_TYPE_INVALID);
125                 if (!ret) {
126                         _E("Failed to get reply (%s:%s)", derror.name, derror.message);
127                 }
128
129                 int angle = (state - 1) * 90;
130                 angle = (angle < 0) ? 0 : angle;
131
132                 _I("rotation changed : %d", angle);
133                 _execute_cbs(DBUS_EVENT_ANGLE_CHANGED, (void*)angle);
134                 dbus_error_free(&derror);
135         }
136
137         return DBUS_HANDLER_RESULT_HANDLED;
138 }
139
140 static lock_error_e _dbus_sig_attach(char *path, char *interface, char *member)
141 {
142         DBusError derror;
143         DBusConnection *connection = NULL;
144
145         retv_if(!path, LOCK_ERROR_INVALID_PARAMETER);
146         retv_if(!interface, LOCK_ERROR_INVALID_PARAMETER);
147         retv_if(!member, LOCK_ERROR_INVALID_PARAMETER);
148
149         /* DBUS */
150         connection = _dbus_connection_get();
151         if (!connection) {
152                 _E("Failed to get DBUS connection");
153                 return LOCK_ERROR_FAIL;
154         }
155
156         dbus_error_init(&derror);
157
158         /* Set the DBus rule for the wakeup gesture signal */
159         char rules[512] = { 0, };
160         snprintf(rules, sizeof(rules) - 1, "path='%s',type='signal',interface='%s', member='%s'", path, interface, member);
161         dbus_bus_add_match(connection, rules, &derror);
162         if (dbus_error_is_set(&derror)) {
163                 _E("D-BUS rule adding error: %s", derror.message);
164                 dbus_error_free(&derror);
165                 return LOCK_ERROR_FAIL;
166         }
167
168         /* Set the callback function */
169         if (dbus_connection_add_filter(connection, _dbus_message_recv_cb, NULL, NULL) == FALSE) {
170                 _E("Failed to add dbus filter : %s", derror.message);
171                 dbus_error_free(&derror);
172                 return LOCK_ERROR_FAIL;
173         }
174
175         dbus_error_free(&derror);
176
177         return LOCK_ERROR_OK;
178 }
179
180 static lock_error_e _dbus_sig_dettach(const char *path, const char *interface, const char *member)
181 {
182         DBusError err;
183         DBusConnection *connection = NULL;
184
185         int ret = LOCK_ERROR_OK;
186
187         retv_if(!path, LOCK_ERROR_INVALID_PARAMETER);
188         retv_if(!interface, LOCK_ERROR_INVALID_PARAMETER);
189         retv_if(!member, LOCK_ERROR_INVALID_PARAMETER);
190
191         connection = _dbus_connection_get();
192         if (!connection) {
193                 _E("failed to get DBUS connection");
194                 return LOCK_ERROR_FAIL;
195         }
196
197         dbus_error_init(&err);
198         dbus_connection_remove_filter(connection, _dbus_message_recv_cb, NULL);
199
200         char rules[512] = { 0, };
201
202         snprintf(rules, sizeof(rules), "path='%s',type='signal',interface='%s',member='%s'", path, interface, member);
203         dbus_bus_remove_match(connection, rules, &err);
204         if (dbus_error_is_set(&err)) {
205                 _E("Failed to dbus_bus_remove_match : %s", err.message);
206                 ret = LOCK_ERROR_FAIL;
207         }
208
209         dbus_error_free(&err);
210
211         return ret;
212 }
213
214 int lock_dbus_register_cb(int type, void (*result_cb)(void *, void *), void *result_data)
215 {
216         retv_if(!result_cb, LOCK_ERROR_FAIL);
217
218         dbus_cb_s *cb = calloc(1, sizeof(dbus_cb_s));
219         retv_if(!cb, LOCK_ERROR_FAIL);
220
221         cb->result_cb = result_cb;
222         cb->result_data = result_data;
223
224         s_info.cbs_list[type] = eina_list_prepend(s_info.cbs_list[type], cb);
225         retv_if(!s_info.cbs_list[type], LOCK_ERROR_FAIL);
226
227         return LOCK_ERROR_OK;
228 }
229
230 void lock_dbus_unregister_cb(int type,  void (*result_cb)(void *, void *))
231 {
232         const Eina_List *l;
233         const Eina_List *n;
234         dbus_cb_s *cb;
235         EINA_LIST_FOREACH_SAFE(s_info.cbs_list[type], l, n, cb) {
236                 continue_if(!cb);
237                 if (result_cb != cb->result_cb) continue;
238                 s_info.cbs_list[type] = eina_list_remove(s_info.cbs_list[type], cb);
239                 free(cb);
240                 return;
241         }
242 }
243
244 static void _lcd_on_cb(void *user_data, void *event_info)
245 {
246         _I("Dbus LCD on");
247
248         lock_time_resume();
249
250         lockscreen_lcd_off_timer_set();
251 }
252
253 static void _lcd_off_cb(void *user_data, void *event_info)
254 {
255         _I("Dbus LCD off");
256
257         lock_time_pause();
258
259         lockscreen_lcd_off_timer_unset();
260         lockscreen_lcd_off_count_reset();
261 }
262
263 void lock_dbus_init(void *data)
264 {
265         if (_dbus_sig_attach(DBUS_DEVICED_DISPLAY_PATH,
266                                 DBUS_DEVICED_DISPLAY_INTERFACE,
267                                 DBUS_DEVICED_DISPLAY_MEMBER_LCD_ON) != LOCK_ERROR_OK) {
268                 _E("Failed to attach LCD on signal filter");
269         }
270
271         if (_dbus_sig_attach(DBUS_DEVICED_DISPLAY_PATH,
272                                 DBUS_DEVICED_DISPLAY_INTERFACE,
273                                 DBUS_DEVICED_DISPLAY_MEMBER_LCD_OFF) != LOCK_ERROR_OK) {
274                 _E("Failed to attach LCD off signal filter");
275         }
276
277         if (lock_property_rotation_enabled_get()) {
278                 if (_dbus_sig_attach(DBUS_ROTATION_PATH,
279                                         DBUS_ROTATION_INTERFACE,
280                                         DBUS_ROTATION_MEMBER_CHANGED) != LOCK_ERROR_OK) {
281                         _E("Failed to attach rotation signal filter");
282                 }
283         }
284
285         if (lock_dbus_register_cb(DBUS_EVENT_LCD_ON, _lcd_on_cb, NULL) != LOCK_ERROR_OK) {
286                 _E("Failed to register lcd status changed cb");
287         }
288
289         if (lock_dbus_register_cb(DBUS_EVENT_LCD_OFF, _lcd_off_cb, NULL) != LOCK_ERROR_OK) {
290                 _E("Failed to register lcd status changed cb");
291         }
292 }
293
294 void lock_dbus_fini(void *data)
295 {
296         _dbus_sig_dettach(DBUS_DEVICED_DISPLAY_PATH,
297                         DBUS_DEVICED_DISPLAY_INTERFACE,
298                         DBUS_DEVICED_DISPLAY_MEMBER_LCD_ON);
299
300         _dbus_sig_dettach(DBUS_DEVICED_DISPLAY_PATH,
301                         DBUS_DEVICED_DISPLAY_INTERFACE,
302                         DBUS_DEVICED_DISPLAY_MEMBER_LCD_OFF);
303
304         if (lock_property_rotation_enabled_get()) {
305                 _dbus_sig_dettach(DBUS_ROTATION_PATH,
306                                 DBUS_ROTATION_INTERFACE,
307                                 DBUS_ROTATION_MEMBER_CHANGED);
308         }
309
310         if (s_info.connection != NULL) {
311                 dbus_connection_close(s_info.connection);
312                 dbus_connection_unref(s_info.connection);
313                 s_info.connection = NULL;
314
315                 _D("DBUS connection is closed");
316         }
317
318         _cbs_fini();
319
320         lock_dbus_unregister_cb(DBUS_EVENT_LCD_ON, _lcd_on_cb);
321         lock_dbus_unregister_cb(DBUS_EVENT_LCD_OFF, _lcd_off_cb);
322 }