Fix mismatched size
[platform/core/appfw/alarm-manager.git] / server / alarm-manager-dbus.c
1 /*
2  * Copyright (c) 2019 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 #define _GNU_SOURCE
17 #include <stdlib.h>
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <sys/socket.h>
21 #include <sys/types.h>
22 #include <sys/un.h>
23
24 #include "alarm.h"
25 #include "alarm-internal.h"
26 #include "alarm-manager-dbus.h"
27 #include "alarm-manager-util.h"
28
29 /*  GDBus Declaration */
30 #define ALARM_MGR_DBUS_PATH     "/org/tizen/alarm/manager"
31 #define ALARM_MGR_DBUS_NAME     "org.tizen.alarm.manager"
32
33 extern __alarm_server_context_t alarm_context;
34 extern GSList *g_expired_alarm_list;
35
36 struct watch_info_t {
37         int watch_id;
38         alarm_id_t alarm_id;
39 };
40
41 static GDBusNodeInfo *introspection_data;
42 static const gchar introspection_xml[] =
43 "<node name='/org/tizen/alarm/manager'>"
44 "  <interface name='org.tizen.alarm.manager'>"
45 "    <method name='alarm_create_periodic'>"
46 "      <arg type='s' name='app_service_name' direction='in' />"
47 "      <arg type='s' name='app_service_name_mod' direction='in' />"
48 "      <arg type='i' name='interval' direction='in' />"
49 "      <arg type='i' name='is_ref' direction='in' />"
50 "      <arg type='i' name='method' direction='in' />"
51 "      <arg type='i' name='alarm_id' direction='out' />"
52 "      <arg type='i' name='return_code' direction='out' />"
53 "    </method>"
54 "    <method name='alarm_create'>"
55 "      <arg type='s' name='app_service_name' direction='in' />"
56 "      <arg type='s' name='app_service_name_mod' direction='in' />"
57 "      <arg type='i' name='alarm_info_start_year' direction='in' />"
58 "      <arg type='i' name='alarm_info_start_month' direction='in' />"
59 "      <arg type='i' name='alarm_info_start_day' direction='in' />"
60 "      <arg type='i' name='alarm_info_start_hour' direction='in' />"
61 "      <arg type='i' name='alarm_info_start_min' direction='in' />"
62 "      <arg type='i' name='alarm_info_start_sec' direction='in' />"
63 "      <arg type='i' name='alarm_info_msec' direction='in' />"
64 "      <arg type='i' name='alarm_info_end_year' direction='in' />"
65 "      <arg type='i' name='alarm_info_end_month' direction='in' />"
66 "      <arg type='i' name='alarm_info_end_day' direction='in' />"
67 "      <arg type='i' name='alarm_info_mode_day_of_week' direction='in' />"
68 "      <arg type='i' name='alarm_info_mode_repeat' direction='in' />"
69 "      <arg type='i' name='alarm_info_alarm_type' direction='in' />"
70 "      <arg type='x' name='alarm_info_reserved_info' direction='in' />"
71 "      <arg type='s' name='alarm_info_reserved_service_name' direction='in' />"
72 "      <arg type='s' name='alarm_info_reserved_service_name_mod' direction='in' />"
73 "      <arg type='i' name='alarm_id' direction='out' />"
74 "      <arg type='i' name='return_code' direction='out' />"
75 "    </method>"
76 "      <method name='alarm_create_appsvc'>"
77 "      <arg type='i' name='alarm_info_start_year' direction='in' />"
78 "      <arg type='i' name='alarm_info_start_month' direction='in' />"
79 "      <arg type='i' name='alarm_info_start_day' direction='in' />"
80 "      <arg type='i' name='alarm_info_start_hour' direction='in' />"
81 "      <arg type='i' name='alarm_info_start_min' direction='in' />"
82 "      <arg type='i' name='alarm_info_start_sec' direction='in' />"
83 "      <arg type='i' name='alarm_info_end_year' direction='in' />"
84 "      <arg type='i' name='alarm_info_end_month' direction='in' />"
85 "      <arg type='i' name='alarm_info_end_day' direction='in' />"
86 "      <arg type='i' name='alarm_info_mode_day_of_week' direction='in' />"
87 "      <arg type='x' name='alarm_info_mode_interval' direction='in' />"
88 "      <arg type='i' name='alarm_info_mode_repeat' direction='in' />"
89 "      <arg type='i' name='alarm_info_alarm_type' direction='in' />"
90 "      <arg type='x' name='alarm_info_reserved_info' direction='in' />"
91 "      <arg type='s' name='alarm_info_bundle_data' direction='in' />"
92 "      <arg type='i' name='alarm_id' direction='out' />"
93 "      <arg type='i' name='return_code' direction='out' />"
94 "    </method>"
95 "      <method name='alarm_create_noti'>"
96 "      <arg type='i' name='alarm_info_start_year' direction='in' />"
97 "      <arg type='i' name='alarm_info_start_month' direction='in' />"
98 "      <arg type='i' name='alarm_info_start_day' direction='in' />"
99 "      <arg type='i' name='alarm_info_start_hour' direction='in' />"
100 "      <arg type='i' name='alarm_info_start_min' direction='in' />"
101 "      <arg type='i' name='alarm_info_start_sec' direction='in' />"
102 "      <arg type='i' name='alarm_info_end_year' direction='in' />"
103 "      <arg type='i' name='alarm_info_end_month' direction='in' />"
104 "      <arg type='i' name='alarm_info_end_day' direction='in' />"
105 "      <arg type='i' name='alarm_info_mode_day_of_week' direction='in' />"
106 "      <arg type='x' name='alarm_info_mode_interval' direction='in' />"
107 "      <arg type='i' name='alarm_info_mode_repeat' direction='in' />"
108 "      <arg type='i' name='alarm_info_alarm_type' direction='in' />"
109 "      <arg type='x' name='alarm_info_reserved_info' direction='in' />"
110 "      <arg type='s' name='alarm_info_noti_data' direction='in' />"
111 "      <arg type='i' name='alarm_id' direction='out' />"
112 "      <arg type='i' name='return_code' direction='out' />"
113 "    </method>"
114 "    <method name='alarm_delete'>"
115 "      <arg type='i' name='alarm_id' direction='in' />"
116 "      <arg type='i' name='alarm_info_return_code' direction='out' />"
117 "    </method>"
118 "    <method name='alarm_delete_all'>"
119 "      <arg type='i' name='alarm_info_return_code' direction='out' />"
120 "    </method>"
121 "    <method name='alarm_update'>"
122 "      <arg type='i' name='alarm_id' direction='in' />"
123 "      <arg type='i' name='alarm_info_start_year' direction='in' />"
124 "      <arg type='i' name='alarm_info_start_month' direction='in' />"
125 "      <arg type='i' name='alarm_info_start_day' direction='in' />"
126 "      <arg type='i' name='alarm_info_start_hour' direction='in' />"
127 "      <arg type='i' name='alarm_info_start_min' direction='in' />"
128 "      <arg type='i' name='alarm_info_start_sec' direction='in' />"
129 "      <arg type='i' name='alarm_info_end_year' direction='in' />"
130 "      <arg type='i' name='alarm_info_end_month' direction='in' />"
131 "      <arg type='i' name='alarm_info_end_day' direction='in' />"
132 "      <arg type='x' name='alarm_info_mode_interval' direction='in' />"
133 "      <arg type='i' name='alarm_info_mode_repeat' direction='in' />"
134 "      <arg type='i' name='alarm_info_alarm_type' direction='in' />"
135 "      <arg type='x' name='alarm_info_reserved_info' direction='in' />"
136 "      <arg type='i' name='update_flag' direction='in' />"
137 "      <arg type='i' name='return_code' direction='out' />"
138 "    </method>"
139 "    <method name='alarm_get_number_of_ids'>"
140 "      <arg type='i' name='number_of_ids' direction='out' />"
141 "      <arg type='i' name='return_code' direction='out' />"
142 "    </method>"
143 "    <method name='alarm_get_list_of_ids'>"
144 "      <arg type='i' name='max_number_of_ids' direction='in' />"
145 "      <arg type='a(i)' name='alarm_id' direction='out' />"
146 "      <arg type='i' name='number_of_ids' direction='out' />"
147 "      <arg type='i' name='return_code' direction='out' />"
148 "    </method>"
149 "    <method name='alarm_get_appsvc_info'>"
150 "      <arg type='i' name='alarm_id' direction='in' />"
151 "      <arg type='s' name='b_data' direction='out' />"
152 "      <arg type='i' name='return_code' direction='out' />"
153 "    </method>"
154 "    <method name='alarm_get_noti_info'>"
155 "      <arg type='i' name='alarm_id' direction='in' />"
156 "      <arg type='s' name='noti_data' direction='out' />"
157 "      <arg type='i' name='return_code' direction='out' />"
158 "    </method>"
159 "    <method name='alarm_get_info'>"
160 "      <arg type='i' name='alarm_id' direction='in' />"
161 "      <arg type='i' name='alarm_info_start_year' direction='out' />"
162 "      <arg type='i' name='alarm_info_start_month' direction='out' />"
163 "      <arg type='i' name='alarm_info_start_day' direction='out' />"
164 "      <arg type='i' name='alarm_info_start_hour' direction='out' />"
165 "      <arg type='i' name='alarm_info_start_min' direction='out' />"
166 "      <arg type='i' name='alarm_info_start_sec' direction='out' />"
167 "      <arg type='i' name='alarm_info_end_year' direction='out' />"
168 "      <arg type='i' name='alarm_info_end_month' direction='out' />"
169 "      <arg type='i' name='alarm_info_end_day' direction='out' />"
170 "      <arg type='i' name='alarm_info_mode_day_of_week' direction='out' />"
171 "      <arg type='i' name='alarm_info_mode_repeat' direction='out' />"
172 "      <arg type='i' name='alarm_info_alarm_type' direction='out' />"
173 "      <arg type='x' name='alarm_info_reserved_info' direction='out' />"
174 "      <arg type='i' name='return_code' direction='out' />"
175 "    </method>"
176 "      <method name='alarm_set_rtc_time'>"
177 "      <arg type='i' name='alarm_info_year' direction='in' />"
178 "      <arg type='i' name='alarm_info_month' direction='in' />"
179 "      <arg type='i' name='alarm_info_day' direction='in' />"
180 "      <arg type='i' name='alarm_info_hour' direction='in' />"
181 "      <arg type='i' name='alarm_info_min' direction='in' />"
182 "      <arg type='i' name='alarm_info_sec' direction='in' />"
183 "      <arg type='i' name='return_code' direction='out' />"
184 "    </method>"
185 "    <method name='alarm_get_next_duetime'>"
186 "      <arg type='i' name='alarm_id' direction='in' />"
187 "      <arg type='x' name='duetime' direction='out' />"
188 "      <arg type='i' name='return_code' direction='out' />"
189 "    </method>"
190 "    <method name='alarm_get_all_info'>"
191 "      <arg type='s' name='db_path' direction='out' />"
192 "      <arg type='i' name='return_code' direction='out' />"
193 "    </method>"
194 "    <method name='alarm_set_time'>"
195 "      <arg type='x' name='time' direction='in' />"
196 "      <arg type='i' name='return_code' direction='out' />"
197 "    </method>"
198 "    <method name='alarm_set_time_with_propagation_delay'>"
199 "      <arg type='x' name='new_sec' direction='in' />"
200 "      <arg type='x' name='new_nsec' direction='in' />"
201 "      <arg type='x' name='req_sec' direction='in' />"
202 "      <arg type='x' name='req_nsec' direction='in' />"
203 "      <arg type='i' name='return_code' direction='out' />"
204 "    </method>"
205 "    <method name='alarm_set_timezone'>"
206 "      <arg type='s' name='tzpath_str' direction='in' />"
207 "      <arg type='i' name='return_code' direction='out' />"
208 "    </method>"
209 "    <method name='alarm_set_global'>"
210 "      <arg type='i' name='alarm_id' direction='in' />"
211 "      <arg type='b' name='global' direction='in' />"
212 "      <arg type='i' name='return_code' direction='out' />"
213 "    </method>"
214 "    <method name='alarm_get_global'>"
215 "      <arg type='i' name='alarm_id' direction='in' />"
216 "      <arg type='b' name='global' direction='out' />"
217 "      <arg type='i' name='return_code' direction='out' />"
218 "    </method>"
219 "    <signal name='alarm_expired'>"
220 "      <arg type='i' name='alarm_id' />"
221 "      <arg type='s' name='app_service_name' />"
222 "    </signal>"
223 "  </interface>"
224 "</node>";
225
226 static gboolean __send_noti_to_session_bus(char *service_name,
227                 alarm_id_t alarm_id, int msec, uid_t uid)
228 {
229         int fd;
230         int ret;
231         size_t len;
232         struct sockaddr_un saddr;
233         uint8_t *data;
234         GVariant *gv;
235         uint8_t *gv_data;
236
237         fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
238         if (fd < 0)
239                 return FALSE;
240
241         saddr.sun_family = AF_UNIX;
242         snprintf(saddr.sun_path, sizeof(saddr.sun_path),
243                         "/run/alarm_agent/%d", uid);
244
245         ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr));
246         if (ret < 0) {
247                 LOGE("connect failed - (errno %d)", errno);
248                 close(fd);
249                 return FALSE;
250         }
251
252         gv = g_variant_new("(iis)", alarm_id, msec, service_name);
253         if (!gv) {
254                 close(fd);
255                 return FALSE;
256         }
257
258         len = g_variant_get_size(gv);
259
260         gv_data = NULL;
261         if (len > 0)
262                 gv_data = (uint8_t *)malloc(len);
263
264         if (!gv_data) {
265                 g_variant_unref(gv);
266                 close(fd);
267                 return FALSE;
268         }
269
270         g_variant_store(gv, gv_data);
271         g_variant_unref(gv);
272
273         data = (uint8_t *)malloc(len + sizeof(len));
274         if (!data) {
275                 close(fd);
276                 free(gv_data);
277                 return FALSE;
278         }
279
280         memcpy(data, &len, sizeof(len));
281         memcpy(data + sizeof(len), gv_data, len);
282         free(gv_data);
283
284         if (send(fd, data, len + sizeof(len), 0) == -1) {
285                 LOGE("sendto() failed (errno %d)", errno);
286                 free(data);
287                 close(fd);
288                 return FALSE;
289         }
290
291         free(data);
292         close(fd);
293         return TRUE;
294 }
295
296 static void __on_name_appeared(GDBusConnection *connection,
297                 const gchar     *name,
298                 const gchar     *name_owner,
299                 gpointer         user_data)
300 {
301         SECURE_LOGW("alarm sender name appeared : %s  %s", name, name_owner);
302
303         struct watch_info_t *watch_info = (struct watch_info_t *)user_data;
304         GSList *gs_iter;
305         __alarm_info_t *entry;
306         alarm_id_t alarm_id = watch_info->alarm_id;
307
308         g_bus_unwatch_name(watch_info->watch_id);
309         free(watch_info);
310
311         for (gs_iter = alarm_context.alarms; gs_iter != NULL; gs_iter = g_slist_next(gs_iter)) {
312                 entry = gs_iter->data;
313                 if (alarm_id == entry->alarm_id) {
314                         entry->zombie_mode = false;
315
316                         _alarm_disable_timer(alarm_context);
317                         _clear_scheduled_alarm_list();
318                         _alarm_schedule();
319                         _rtc_set();
320
321                         return;
322                 }
323         }
324 }
325
326 static void __alarm_send_noti_to_application_reply(
327                 GObject *source_object, GAsyncResult *res, gpointer user_data) {
328
329         GVariant *message;
330         GDBusConnection *conn;
331         GError *error = NULL;
332         alarm_id_t *reply_alarm_id = (alarm_id_t *)user_data;
333         char *service_name = "NULL";
334         char *app_unique_name = "NULL";
335         struct watch_info_t *watch_info;
336         char log_message[ALARMMGR_LOG_MESSAGE_SIZE] = {0,};
337
338         GSList *gs_iter;
339         __alarm_info_t *entry;
340         bool is_existed = false;
341
342         conn = G_DBUS_CONNECTION(source_object);
343         message = g_dbus_connection_call_finish(conn, res, &error);
344
345         if (error == NULL) {
346                 g_variant_unref(message);
347                 free(reply_alarm_id);
348                 return;
349         }
350
351         LOGE("g_dbus_connection_call_finish Error[%d] : [%s] ", error->code, error->message);
352         if (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN) {
353                 for (gs_iter = alarm_context.alarms; gs_iter != NULL; gs_iter = g_slist_next(gs_iter) ) {
354                         entry = gs_iter->data;
355
356                         if (*reply_alarm_id == entry->alarm_id) {
357                                 is_existed = true;
358
359                                 app_unique_name =  entry->app_unique_name;
360
361                                 if (entry->dst_service_name == NULL)
362                                         service_name = entry->app_service_name_mod;
363                                 else
364                                         service_name = entry->dst_service_name_mod;
365
366                                 break;
367                         }
368                 }
369
370                 LOGE("failed to send alarm expired noti [%d: %s] [id : %d, %s -> %s]",
371                                 error->code, error->message, *reply_alarm_id,
372                                 app_unique_name, service_name);
373
374                 snprintf(log_message, sizeof(log_message),
375                                 "failed to send alarm expired noti [%d: %s] [id : %d, %s -> %s]",
376                                 error->code, error->message, *reply_alarm_id, app_unique_name, service_name);
377                 _save_module_log("EXPIRED_FAIL", log_message);
378
379                 g_error_free(error);
380
381                 if (is_existed) {
382                         watch_info = (struct watch_info_t *)calloc(1, sizeof(struct watch_info_t));
383                         if (watch_info == NULL) {
384                                 LOGE("Out of memory");
385                                 free(reply_alarm_id);
386                                 return;
387                         }
388
389                         entry->zombie_mode = true;
390
391                         watch_info->alarm_id = entry->alarm_id;
392                         watch_info->watch_id = g_bus_watch_name_on_connection(
393                                         alarm_context.connection,
394                                         service_name,
395                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
396                                         __on_name_appeared,
397                                         NULL,
398                                         watch_info,
399                                         NULL);
400
401                         alarm_context.c_due_time = -1;
402                         _alarm_disable_timer(alarm_context);
403                         _clear_scheduled_alarm_list();
404                         _alarm_schedule();
405                         _rtc_set();
406                 }
407         }
408
409         free(reply_alarm_id);
410 }
411
412 void _alarm_send_noti_to_application_by_dbus(const char *app_service_name,
413                 alarm_id_t alarm_id, int msec, uid_t uid)
414 {
415         char service_name[MAX_SERVICE_NAME_LEN] = {0,};
416         gboolean ret;
417         alarm_id_t *reply_alarm_id;
418
419         if (app_service_name == NULL || strlen(app_service_name) == 0) {
420                 LOGE("This alarm destination is invalid.");
421                 return;
422         }
423
424         if (_can_skip_expired_cb(alarm_id))
425                 return;
426
427         strncpy(service_name, app_service_name, sizeof(service_name) - 1);
428         SECURE_LOGI("[send expired_alarm(alarm_id=%d) to app_service_name(%s)]",
429                         alarm_id, service_name);
430
431         if (uid >= REGULAR_UID_MIN) {
432                 ret = __send_noti_to_session_bus(service_name, alarm_id, msec, uid);
433                 if (ret != TRUE)
434                         LOGE("failed to send alarm expired noti for %d, %s",
435                                         alarm_id, service_name);
436         } else {
437                 reply_alarm_id = (alarm_id_t *)calloc(1, sizeof(alarm_id_t));
438                 if (reply_alarm_id == NULL) {
439                         LOGE("Out of memory");
440                         return;
441                 }
442
443                 *reply_alarm_id = alarm_id;
444                 g_dbus_connection_call(alarm_context.connection,
445                                 service_name,
446                                 "/org/tizen/alarm/client",
447                                 "org.tizen.alarm.client",
448                                 "alarm_expired",
449                                 g_variant_new("(iis)", alarm_id, msec, service_name),
450                                 NULL,
451                                 G_DBUS_CALL_FLAGS_NONE,
452                                 -1,
453                                 NULL,
454                                 __alarm_send_noti_to_application_reply,
455                                 reply_alarm_id);
456         }
457 }
458
459 static uid_t __get_caller_uid(const char *name)
460 {
461         guint uid;
462         GVariant *ret;
463         GError *error = NULL;
464
465         ret = g_dbus_connection_call_sync(
466                         alarm_context.connection,
467                         "org.freedesktop.DBus",
468                         "/org/freedesktop/DBus",
469                         "org.freedesktop.DBus",
470                         "GetConnectionUnixUser",
471                         g_variant_new("(s)", name),
472                         NULL,
473                         G_DBUS_CALL_FLAGS_NONE,
474                         -1,
475                         NULL,
476                         &error);
477         if (!ret) {
478                 LOGE("failed to get caller uid");
479                 if (error) {
480                         LOGE("dbus error message :  %s", error->message);
481                         g_error_free(error);
482                 }
483                 return -1;
484         }
485         g_variant_get(ret, "(u)", &uid);
486         g_variant_unref(ret);
487
488         return uid;
489 }
490
491 static pid_t __get_caller_pid(const char *name)
492 {
493         guint pid;
494         GVariant *ret;
495         GError *error = NULL;
496
497         ret = g_dbus_connection_call_sync(alarm_context.connection,
498                                         "org.freedesktop.DBus",
499                                         "/org/freedesktop/DBus",
500                                         "org.freedesktop.DBus",
501                                         "GetConnectionUnixProcessID",
502                                         g_variant_new("(s)", name),
503                                         NULL,
504                                         G_DBUS_CALL_FLAGS_NONE,
505                                         -1,
506                                         NULL,
507                                         &error);
508         if (!ret) {
509                 LOGE("failed to get caller pid");
510                 if (error) {
511                         LOGE("dbus error message :  %s", error->message);
512                         g_error_free(error);
513                 }
514                 return -1;
515         }
516         g_variant_get(ret, "(u)", &pid);
517         g_variant_unref(ret);
518
519         return pid;
520 }
521
522 void _display_lock_state(char *state, char *flag, unsigned int timeout)
523 {
524         GDBusMessage *msg = NULL;
525         GDBusMessage *reply = NULL;
526         GVariant *body = NULL;
527         int val = -1;
528
529         LOGD("Lock the display not to enter LCD OFF");
530
531         msg = g_dbus_message_new_method_call(
532                         DEVICED_BUS_NAME,
533                         DEVICED_PATH_DISPLAY,
534                         DEVICED_INTERFACE_DISPLAY,
535                         DEVICED_LOCK_STATE);
536         if (!msg) {
537                 LOGE("g_dbus_message_new_method_call() is failed. (%s:%s-%s)",
538                                 DEVICED_BUS_NAME, DEVICED_INTERFACE_DISPLAY, DEVICED_LOCK_STATE);
539                 return;
540         }
541
542         g_dbus_message_set_body(
543                         msg, g_variant_new("(sssi)", state, flag, "NULL", timeout));
544
545         reply = g_dbus_connection_send_message_with_reply_sync(
546                         alarm_context.connection,
547                         msg,
548                         G_DBUS_SEND_MESSAGE_FLAGS_NONE,
549                         DEVICED_DBUS_REPLY_TIMEOUT, NULL, NULL, NULL);
550         if (!reply) {
551                 LOGE("No reply.\
552                                 g_dbus_connection_send_message_with_reply_sync() is failed.");
553         } else {
554                 body = g_dbus_message_get_body(reply);
555                 if (!body) {
556                         LOGE("g_dbus_message_get_body() is failed.");
557                 } else {
558                         g_variant_get(body, "(i)", &val);
559                         if (val != 0) {
560                                 LOGE("Failed to lock display");
561                         } else {
562                                 LOGD("Lock LCD OFF is successfully done");
563                         }
564                 }
565         }
566
567         g_dbus_connection_flush_sync(alarm_context.connection, NULL, NULL);
568         g_object_unref(msg);
569         if (reply)
570                 g_object_unref(reply);
571 }
572
573 void _display_unlock_state(char *state, char *flag)
574 {
575         GDBusMessage *msg = NULL;
576         GDBusMessage *reply = NULL;
577         GVariant *body = NULL;
578         int val = -1;
579
580         LOGD("Unlock the display from LCD OFF");
581
582         msg = g_dbus_message_new_method_call(
583                         DEVICED_BUS_NAME,
584                         DEVICED_PATH_DISPLAY,
585                         DEVICED_INTERFACE_DISPLAY,
586                         DEVICED_UNLOCK_STATE);
587         if (!msg) {
588                 LOGE("g_dbus_message_new_method_call() is failed. (%s:%s-%s)",
589                                 DEVICED_BUS_NAME, DEVICED_INTERFACE_DISPLAY, DEVICED_UNLOCK_STATE);
590                 return;
591         }
592
593         g_dbus_message_set_body(msg, g_variant_new("(ss)", state, flag));
594
595         reply = g_dbus_connection_send_message_with_reply_sync(
596                         alarm_context.connection,
597                         msg,
598                         G_DBUS_SEND_MESSAGE_FLAGS_NONE,
599                         DEVICED_DBUS_REPLY_TIMEOUT, NULL, NULL, NULL);
600         if (!reply) {
601                 LOGE("No reply.\
602                                 g_dbus_connection_send_message_with_reply_sync() is failed.");
603         } else {
604                 body = g_dbus_message_get_body(reply);
605                 if (!body) {
606                         LOGE("g_dbus_message_get_body() is failed.");
607                 } else {
608                         g_variant_get(body, "(i)", &val);
609                         if (val != 0) {
610                                 LOGE("Failed to unlock display");
611                         } else {
612                                 LOGD("Unlock LCD OFF is successfully done");
613                         }
614                 }
615         }
616
617         g_dbus_connection_flush_sync(alarm_context.connection, NULL, NULL);
618         g_object_unref(msg);
619         if (reply)
620                 g_object_unref(reply);
621 }
622
623 static void handle_method_call(GDBusConnection *connection,
624         const gchar *sender, const gchar *object_path,
625         const gchar *interface_name, const gchar *method_name,
626         GVariant *parameters, GDBusMethodInvocation *invoc,
627         gpointer user_data)
628 {
629         int ret = ALARMMGR_RESULT_SUCCESS;
630         int num_of_alarm = 0;
631         int alarm_id = 0;
632         const char *name = g_dbus_method_invocation_get_sender(invoc);
633         uid_t uid = __get_caller_uid(name);
634         pid_t pid = __get_caller_pid(name);
635
636         if (g_strcmp0(method_name, "alarm_create_periodic") == 0) {
637                 ret = alarm_manager_alarm_create_periodic(parameters, uid, pid, sender, &alarm_id);
638                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(ii)", alarm_id, ret));
639         } else if (g_strcmp0(method_name, "alarm_create") == 0) {
640                 ret = alarm_manager_alarm_create(parameters, uid, pid, sender, &alarm_id);
641                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(ii)", alarm_id, ret));
642         } else if (g_strcmp0(method_name, "alarm_create_appsvc") == 0) {
643                 ret = alarm_manager_alarm_create_appsvc(parameters, uid, pid, sender, &alarm_id);
644                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(ii)", alarm_id, ret));
645         } else if (g_strcmp0(method_name, "alarm_create_noti") == 0) {
646                 const char *notification_priv = "http://tizen.org/privilege/notification";
647                 ret = _cynara_check(invoc, notification_priv, pid);
648                 if (ret == ALARMMGR_RESULT_SUCCESS) {
649                         ret = alarm_manager_alarm_create_noti(parameters, uid, pid, sender, &alarm_id);
650                 }
651                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(ii)", alarm_id, ret));
652         } else if (g_strcmp0(method_name, "alarm_delete") == 0) {
653                 ret = alarm_manager_alarm_delete(parameters, uid, pid, sender);
654                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
655         } else if (g_strcmp0(method_name, "alarm_delete_all") == 0) {
656                 ret = alarm_manager_alarm_delete_all(parameters, uid, pid, sender);
657                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
658         } else if (g_strcmp0(method_name, "alarm_update") == 0) {
659                 ret = alarm_manager_alarm_update(parameters, uid, pid, sender);
660                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
661         } else if (g_strcmp0(method_name, "alarm_get_number_of_ids") == 0) {
662                 ret = alarm_manager_alarm_get_number_of_ids(uid, pid, sender, &num_of_alarm);
663                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(ii)", num_of_alarm, ret));
664         } else if (g_strcmp0(method_name, "alarm_get_list_of_ids") == 0) {
665                 GVariantBuilder *arr = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
666
667                 ret = alarm_manager_alarm_get_list_of_ids(parameters, uid, pid, sender, arr, &num_of_alarm);
668                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(a(i)ii)", arr, num_of_alarm, ret));
669
670                 g_variant_builder_unref(arr);
671         } else if (g_strcmp0(method_name, "alarm_get_appsvc_info") == 0) {
672                 gchar *b_data = NULL;
673
674                 ret = alarm_manager_alarm_get_appsvc_info(parameters, uid, &b_data);
675                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(si)", b_data, ret));
676                 if (b_data)
677                         free(b_data);
678         } else if (g_strcmp0(method_name, "alarm_get_noti_info") == 0) {
679                 gchar *noti_data = NULL;
680
681                 ret = alarm_manager_alarm_get_noti_info(parameters, uid, &noti_data);
682                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(si)", noti_data, ret));
683
684                 if (noti_data)
685                         free(noti_data);
686         } else if (g_strcmp0(method_name, "alarm_get_info") == 0) {
687                 base_info_t base_info = { 0, };
688
689                 ret = alarm_manager_alarm_get_info(parameters, uid, &base_info);
690
691                 g_dbus_method_invocation_return_value(
692                                 invoc, g_variant_new("(iiiiiiiiiiiixi)",
693                                         base_info.start.year, base_info.start.month,
694                                         base_info.start.day, base_info.start.hour,
695                                         base_info.start.min, base_info.start.sec,
696                                         base_info.end.year, base_info.end.month,
697                                         base_info.end.day, base_info.mode.u_interval.day_of_week,
698                                         base_info.mode.repeat, base_info.alarm_type,
699                                         (gint64)base_info.reserved_info, ret));
700         } else if (g_strcmp0(method_name, "alarm_get_next_duetime") == 0) {
701                 time_t duetime;
702                 ret = alarm_manager_alarm_get_next_duetime(parameters, uid, &duetime);
703
704                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(xi)", (gint64)duetime, ret));
705         } else if (g_strcmp0(method_name, "alarm_get_all_info") == 0) {
706                 char *db_path = NULL;
707
708                 ret = alarm_manager_alarm_get_all_info(uid, &db_path);
709                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(si)", db_path, ret));
710
711                 if (db_path)
712                         free(db_path);
713         } else if (g_strcmp0(method_name, "alarm_set_rtc_time") == 0) {
714                 _display_lock_state(DEVICED_LCD_OFF, DEVICED_STAY_CUR_STATE, 0);
715                 ret = alarm_manager_alarm_set_rtc_time(parameters);
716                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
717                 _display_unlock_state(DEVICED_LCD_OFF, DEVICED_SLEEP_MARGIN);
718         } else if (g_strcmp0(method_name, "alarm_set_time") == 0) {
719                 _display_lock_state(DEVICED_LCD_OFF, DEVICED_STAY_CUR_STATE, 0);
720                 ret = alarm_manager_alarm_set_time(parameters, pid, sender);
721                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
722                 _display_unlock_state(DEVICED_LCD_OFF, DEVICED_SLEEP_MARGIN);
723         } else if (g_strcmp0(method_name, "alarm_set_time_with_propagation_delay") == 0) {
724                 _display_lock_state(DEVICED_LCD_OFF, DEVICED_STAY_CUR_STATE, 0);
725                 ret = alarm_manager_alarm_set_time_with_propagation_delay(parameters, pid, sender);
726                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
727                 _display_unlock_state(DEVICED_LCD_OFF, DEVICED_SLEEP_MARGIN);
728         } else if (g_strcmp0(method_name, "alarm_set_timezone") == 0) {
729                 _display_lock_state(DEVICED_LCD_OFF, DEVICED_STAY_CUR_STATE, 0);
730                 ret = alarm_manager_alarm_set_timezone(parameters);
731                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
732                 _display_unlock_state(DEVICED_LCD_OFF, DEVICED_SLEEP_MARGIN);
733         } else if (g_strcmp0(method_name, "alarm_set_global") == 0) {
734                 ret = alarm_manager_alarm_set_global(parameters, uid);
735                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(i)", ret));
736         } else if (g_strcmp0(method_name, "alarm_get_global") == 0) {
737                 gboolean global;
738
739                 ret = alarm_manager_alarm_get_global(parameters, &global);
740                 g_dbus_method_invocation_return_value(invoc, g_variant_new("(bi)", global, ret));
741         }
742 }
743
744 static const GDBusInterfaceVTable interface_vtable = {
745         handle_method_call,
746         NULL,
747         NULL
748 };
749
750 static void __on_bus_name_acquired(GDBusConnection  *connection,
751                                 const gchar *name,
752                                 gpointer user_data)
753 {
754         LOGD("bus acquired(%s)", name);
755 }
756
757 static void __on_bus_name_owner_changed(GDBusConnection  *connection,
758                                 const gchar *sender_name,
759                                 const gchar *object_path,
760                                 const gchar *interface_name,
761                                 const gchar *signal_name,
762                                 GVariant *parameters,
763                                 gpointer user_data)
764 {
765         GSList *entry = NULL;
766         __expired_alarm_t *expire_info = NULL;
767         char *service_name = NULL;
768
769         /* On expiry, the killed app can be launched by aul. Then, the owner of the bus name which was registered by the app is changed.
770          * In this case, "NameOwnerChange" signal is broadcasted. */
771         if (signal_name && strcmp(signal_name, "NameOwnerChanged") == 0) {
772                 g_variant_get(parameters, "(&sss)", &service_name, NULL, NULL);
773
774                 for (entry = g_expired_alarm_list; entry;) {
775                         expire_info = (__expired_alarm_t *) entry->data;
776                         entry = entry->next;
777
778                         if (expire_info) {
779                                 SECURE_LOGD("expired service(%s), owner changed service(%s)",
780                                                 expire_info->service_name, service_name);
781
782                                 if (strcmp(expire_info->service_name, service_name) == 0) {
783                                         SECURE_LOGE("expired service name(%s) alarm_id (%d)",
784                                                         expire_info->service_name, expire_info->alarm_id);
785                                         _alarm_send_noti_to_application_by_dbus(
786                                                         expire_info->service_name,
787                                                         expire_info->alarm_id,
788                                                         0,
789                                                         expire_info->uid);
790                                         g_expired_alarm_list =
791                                                 g_slist_remove(g_expired_alarm_list, (gpointer)expire_info);
792                                         g_free(expire_info);
793                                 }
794                         }
795                 }
796         }
797 }
798
799 bool _initialize_dbus(void)
800 {
801         GDBusConnection *connection = NULL;
802         GError *error = NULL;
803         guint subsc_id;
804         guint owner_id;
805         guint reg_id;
806
807         LOGD("__initialize_dbus Enter");
808
809         connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
810         if (connection == NULL) {
811                 LOGE("g_bus_get_sync() is failed");
812                 if (error) {
813                         LOGE("dbus error message : %s", error->message);
814                         g_error_free(error);
815                 }
816                 return false;
817         }
818
819         subsc_id = g_dbus_connection_signal_subscribe(connection,
820                         "org.freedesktop.DBus", "org.freedesktop.DBus",
821                         "NameOwnerChanged", "/org/freedesktop/DBus", NULL,
822                         G_DBUS_SIGNAL_FLAGS_NONE, __on_bus_name_owner_changed, NULL, NULL);
823         if (subsc_id == 0) {
824                 LOGE("Subscribing to signal for invoking callback is failed.");
825                 g_object_unref(connection);
826                 return false;
827         }
828
829         introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
830         if (!introspection_data) {
831                 LOGE("g_dbus_node_info_new_for_xml error(%s)", error->message);
832                 g_object_unref(connection);
833                 g_error_free(error);
834                 return false;
835         }
836
837         reg_id = g_dbus_connection_register_object(connection,
838                         ALARM_MGR_DBUS_PATH,
839                         introspection_data->interfaces[0],
840                         &interface_vtable,
841                         NULL, NULL, &error);
842         if (reg_id == 0) {
843                 LOGE("g_dbus_connection_register_object error(%s)", error->message);
844                 g_dbus_node_info_unref(introspection_data);
845                 g_object_unref(connection);
846                 g_error_free(error);
847         }
848
849         owner_id = g_bus_own_name_on_connection(connection,
850                         ALARM_MGR_DBUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE,
851                         __on_bus_name_acquired, NULL, NULL, NULL);
852         if (owner_id == 0) {
853                 LOGE("Acquiring the own name is failed.");
854                 g_dbus_node_info_unref(introspection_data);
855                 g_object_unref(connection);
856                 return false;
857         }
858
859         alarm_context.connection = connection;
860
861         return true;
862 }