Add default viewer launch feature for ex-noti
[platform/core/appfw/data-provider-master.git] / src / notification_service.c
1 /*
2  * Copyright 2016  Samsung Electronics Co., Ltd
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 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19
20 #include <gio/gio.h>
21 #include <gio/gunixfdlist.h>
22
23 #include <dlog.h>
24 #include <sys/smack.h>
25 #include <pkgmgr-info.h>
26 #include <notification.h>
27 #include <alarm.h>
28 #include <aul.h>
29
30 #include "pkgmgr.h"
31 #include "service_common.h"
32 #include "notification_service.h"
33 #include "debug.h"
34
35 #include <notification_noti.h>
36 #include <notification_internal.h>
37 #include <notification_ipc.h>
38 #include <notification_setting_service.h>
39 #include <notification_db.h>
40 #include <notification_viewer.h>
41 #include <notification_shared_file.h>
42
43 #define PROVIDER_NOTI_INTERFACE_NAME "org.tizen.data_provider_noti_service"
44 #define PROVIDER_NOTI_EVENT_INTERFACE_NAME "org.tizen.data_provider_noti_event_service"
45 #define NOTI_TEMPLATE_LIMIT 10
46 #define BUF_LEN 256
47
48 typedef struct _dnd_alarm_id dnd_alarm_id_s;
49
50 static GHashTable *_monitoring_hash;
51
52 static GList *_dnd_alarm_id_list;
53
54 typedef struct _dnd_alarm_id {
55         uid_t uid;
56         alarm_id_t dnd_start_id;
57         alarm_id_t dnd_end_id;
58 } dnd_alarm_id_s;
59
60 static GList *__event_list;
61
62 typedef struct _event_sender_info {
63         int priv_id;
64         char *busname;
65         guint watcher_id;
66 } event_sender_info_s;
67
68 static int _update_noti(GVariant **reply_body, notification_h noti, uid_t uid);
69 static int _delete_noti(const char *app_id, int priv_id, uid_t uid);
70
71 /*!
72  * SERVICE HANDLER
73  */
74
75 /*!
76  * NOTIFICATION SERVICE INITIALIZATION
77  */
78 static void __print_noti(notification_h noti)
79 {
80         char *pkgname = NULL;
81         char *text = NULL;
82         char *content = NULL;
83         const char *tag = NULL;
84
85         notification_get_pkgname(noti, &pkgname);
86         notification_get_text(noti, NOTIFICATION_TEXT_TYPE_TITLE, &text);
87         notification_get_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT, &content);
88         notification_get_tag(noti, &tag);
89
90         DBG("Noti-info : pkgname[%s] title[%s] content[%s] tag[%s]",
91                 pkgname, text, content, tag);
92 }
93
94 static void _on_name_appeared(GDBusConnection *connection,
95                 const gchar     *name,
96                 const gchar     *name_owner,
97                 gpointer         user_data)
98 {
99         monitoring_info_s *info = (monitoring_info_s *)user_data;
100
101         DBG("name[%s], uid[%d]", name, info->uid);
102 }
103
104 static void _on_name_vanished(GDBusConnection *connection,
105                 const gchar     *name,
106                 gpointer         user_data)
107 {
108         monitoring_info_s *info = (monitoring_info_s *)user_data;
109
110         if (info) {
111                 DBG("name[%s], uid[%d]", name, info->uid);
112                 notification_remove_private_sharing_target_id(name, info->uid);
113                 g_bus_unwatch_name(info->watcher_id);
114                 delete_monitoring_list(&_monitoring_hash, info->bus_name, info->uid);
115
116                 if (info->bus_name)
117                         free(info->bus_name);
118                 free(info);
119         }
120 }
121
122 static void _noti_dbus_method_call_handler(GDBusConnection *conn,
123                 const gchar *sender, const gchar *object_path,
124                 const gchar *iface_name, const gchar *method_name,
125                 GVariant *parameters, GDBusMethodInvocation *invocation,
126                 gpointer user_data)
127 {
128         /* TODO : sender authority(privilege) check */
129         INFO("notification method_name[%s] sender[%s]", method_name, sender);
130
131         GVariant *reply_body = NULL;
132         int ret = NOTIFICATION_ERROR_INVALID_OPERATION;
133         uid_t uid = get_sender_uid(sender);
134         pid_t pid = get_sender_pid(sender);
135
136         if (g_strcmp0(method_name, "noti_service_register") == 0) {
137                 ret = service_register(parameters, &reply_body, sender,
138                                 _on_name_appeared, _on_name_vanished, &_monitoring_hash, uid);
139                 if (ret == NOTIFICATION_ERROR_NONE)
140                         notification_add_private_sharing_target_id(pid, sender, uid);
141         } else if (g_strcmp0(method_name, "update_noti") == 0) {
142                 ret = notification_update_noti(parameters, &reply_body, pid, uid);
143         } else if (g_strcmp0(method_name, "add_noti") == 0) {
144                 ret = notification_add_noti(parameters, &reply_body, sender, pid, uid);
145         } else if (g_strcmp0(method_name, "refresh_noti") == 0) {
146                 ret = notification_refresh_noti(parameters, &reply_body, uid);
147         } else if (g_strcmp0(method_name, "del_noti_single") == 0) {
148                 ret = notification_del_noti_single(parameters, &reply_body, uid);
149         } else if (g_strcmp0(method_name, "del_noti_multiple") == 0) {
150                 ret = notification_del_noti_multiple(parameters, &reply_body, uid);
151         } else if (g_strcmp0(method_name, "get_noti_count") == 0) {
152                 ret = notification_get_noti_count(parameters, &reply_body, uid);
153         } else if (g_strcmp0(method_name, "get_noti_all_count") == 0) {
154                 ret = notification_get_noti_all_count(parameters, &reply_body, uid);
155         } else if (g_strcmp0(method_name, "update_noti_setting") == 0) {
156                 ret = notification_update_noti_setting(parameters, &reply_body, uid);
157         } else if (g_strcmp0(method_name, "update_noti_sys_setting") == 0) {
158                 ret = notification_update_noti_sys_setting(parameters, &reply_body, uid);
159         } else if (g_strcmp0(method_name, "load_noti_by_tag") == 0) {
160                 ret = notification_load_noti_by_tag(parameters, &reply_body, uid);
161         } else if (g_strcmp0(method_name, "load_noti_by_priv_id") == 0) {
162                 ret = notification_load_noti_by_priv_id(parameters, &reply_body, uid);
163         } else if (g_strcmp0(method_name, "load_noti_grouping_list") == 0) {
164                 notification_add_private_sharing_target_id(pid, sender, uid);
165                 notification_load_grouping_list(invocation, parameters, uid);
166                 return;
167         } else if (g_strcmp0(method_name, "load_noti_detail_list") == 0) {
168                 notification_add_private_sharing_target_id(pid, sender, uid);
169                 ret = notification_load_detail_list(parameters, &reply_body, uid);
170         } else if (g_strcmp0(method_name, "get_setting_array") == 0) {
171                 ret = notification_get_setting_array(parameters, &reply_body, uid);
172         } else if (g_strcmp0(method_name, "get_setting_by_app_id") == 0) {
173                 ret = notification_get_setting_by_app_id(parameters, &reply_body, uid);
174         } else if (g_strcmp0(method_name, "load_system_setting") == 0) {
175                 ret = notification_load_system_setting(parameters, &reply_body, uid);
176         } else if (g_strcmp0(method_name, "save_as_template") == 0) {
177                 ret = notification_add_noti_template(parameters, &reply_body, uid);
178         } else if (g_strcmp0(method_name, "create_from_template") == 0) {
179                 ret = notification_get_noti_template(parameters, &reply_body, pid, uid);
180         } else if (g_strcmp0(method_name, "create_from_package_template") == 0) {
181                 ret = notification_get_noti_package_template(parameters, &reply_body, uid);
182         } else if (g_strcmp0(method_name, "get_noti_block_state") == 0) {
183                 ret = notification_get_block_state(parameters, &reply_body, uid);
184         } else if (g_strcmp0(method_name, "load_dnd_allow_exception") == 0) {
185                 ret = notification_load_dnd_allow_exception(parameters, &reply_body, uid);
186         } else if (g_strcmp0(method_name, "update_dnd_allow_exception") == 0) {
187                 ret = notification_update_dnd_allow_exception(parameters, &reply_body, uid);
188         } else if (g_strcmp0(method_name, "send_noti_event") == 0) {
189                 ret = notification_send_noti_event(parameters, &reply_body);
190         } else if (g_strcmp0(method_name, "send_noti_event_by_priv_id") == 0) {
191                 ret = notification_send_noti_event_by_priv_id(parameters, &reply_body);
192         } else if (g_strcmp0(method_name, "check_event_receiver") == 0) {
193                 ret = notification_check_event_receiver(parameters, &reply_body);
194         } else if (g_strcmp0(method_name, "reset_event_handler") == 0) {
195                 ret = notification_reset_event_receiver(parameters, &reply_body, sender);
196         } else if (g_strcmp0(method_name, "del_noti_by_display_applist") == 0) {
197                 ret = notification_del_noti_by_display_applist(parameters, &reply_body, uid);
198         }
199
200         if (ret == NOTIFICATION_ERROR_NONE) {
201                 INFO("notification service success, method name[%s]", method_name);
202                 g_dbus_method_invocation_return_value(
203                                 invocation, reply_body);
204         } else {
205                 ERR("notification service fail, method_name[%s] err[%d]",
206                         method_name, ret);
207                 g_dbus_method_invocation_return_error(
208                                 invocation,
209                                 NOTIFICATION_ERROR,
210                                 ret,
211                                 "notification service error");
212         }
213 }
214
215 static const GDBusInterfaceVTable _noti_interface_vtable = {
216                 _noti_dbus_method_call_handler,
217                 NULL,
218                 NULL
219 };
220
221 int notification_register_dbus_interface(void)
222 {
223         static gchar introspection_xml[] =
224                         "  <node>"
225                         "  <interface name='org.tizen.data_provider_noti_service'>"
226                         "        <method name='noti_service_register'>"
227                         "          <arg type='i' name='uid' direction='in'/>"
228                         "        </method>"
229
230                         "        <method name='add_noti'>"
231                         "          <arg type='v' name='noti' direction='in'/>"
232                         "          <arg type='i' name='priv_id' direction='out'/>"
233                         "        </method>"
234
235                         "        <method name='update_noti'>"
236                         "          <arg type='v' name='noti' direction='in'/>"
237                         "          <arg type='i' name='priv_id' direction='out'/>"
238                         "        </method>"
239
240                         "        <method name='refresh_noti'>"
241                         "          <arg type='i' name='uid' direction='in'/>"
242                         "        </method>"
243
244                         "        <method name='del_noti_single'>"
245                         "          <arg type='s' name='app_id' direction='in'/>"
246                         "          <arg type='i' name='priv_id' direction='in'/>"
247                         "          <arg type='i' name='uid' direction='in'/>"
248                         "          <arg type='i' name='priv_id' direction='out'/>"
249                         "        </method>"
250
251                         "        <method name='del_noti_multiple'>"
252                         "          <arg type='s' name='app_id' direction='in'/>"
253                         "          <arg type='i' name='priv_id' direction='in'/>"
254                         "          <arg type='i' name='uid' direction='in'/>"
255                         "          <arg type='i' name='priv_id' direction='out'/>"
256                         "        </method>"
257
258                         "        <method name='load_noti_by_tag'>"
259                         "          <arg type='s' name='app_id' direction='in'/>"
260                         "          <arg type='s' name='tag' direction='in'/>"
261                         "          <arg type='i' name='uid' direction='in'/>"
262                         "          <arg type='v' name='noti' direction='out'/>"
263                         "        </method>"
264
265                         "        <method name='load_noti_by_priv_id'>"
266                         "          <arg type='s' name='app_id' direction='in'/>"
267                         "          <arg type='i' name='priv_id' direction='in'/>"
268                         "          <arg type='i' name='uid' direction='in'/>"
269                         "          <arg type='v' name='noti' direction='out'/>"
270                         "        </method>"
271
272                         "        <method name='load_noti_grouping_list'>"
273                         "          <arg type='i' name='type' direction='in'/>"
274                         "          <arg type='i' name='count' direction='in'/>"
275                         "          <arg type='i' name='count_per_page' direction='in'/>"
276                         "          <arg type='i' name='uid' direction='in'/>"
277                         "          <arg type='i' name='list_count' direction='out'/>"
278                         "        </method>"
279
280                         "        <method name='load_noti_detail_list'>"
281                         "          <arg type='s' name='app_id' direction='in'/>"
282                         "          <arg type='i' name='group_id' direction='in'/>"
283                         "          <arg type='i' name='priv_id' direction='in'/>"
284                         "          <arg type='i' name='count' direction='in'/>"
285                         "          <arg type='i' name='uid' direction='in'/>"
286                         "          <arg type='a(v)' name='noti_list' direction='out'/>"
287                         "        </method>"
288
289                         "        <method name='get_noti_count'>"
290                         "          <arg type='i' name='type' direction='in'/>"
291                         "          <arg type='s' name='app_id' direction='in'/>"
292                         "          <arg type='i' name='group_id' direction='in'/>"
293                         "          <arg type='i' name='priv_id' direction='in'/>"
294                         "          <arg type='i' name='uid' direction='in'/>"
295                         "          <arg type='i' name='ret_count' direction='out'/>"
296                         "        </method>"
297
298                         "        <method name='get_noti_all_count'>"
299                         "          <arg type='i' name='type' direction='in'/>"
300                         "          <arg type='i' name='uid' direction='in'/>"
301                         "          <arg type='i' name='ret_count' direction='out'/>"
302                         "        </method>"
303
304                         "        <method name='update_noti_setting'>"
305                         "          <arg type='s' name='pkgname' direction='in'/>"
306                         "          <arg type='s' name='app_id' direction='in'/>"
307                         "          <arg type='i' name='allow_to_notify' direction='in'/>"
308                         "          <arg type='i' name='do_not_disturb_except' direction='in'/>"
309                         "          <arg type='i' name='visibility_class' direction='in'/>"
310                         "          <arg type='i' name='pop_up_notification' direction='in'/>"
311                         "          <arg type='i' name='lock_screen_content_level' direction='in'/>"
312                         "          <arg type='i' name='uid' direction='in'/>"
313                         "        </method>"
314
315                         "        <method name='update_noti_sys_setting'>"
316                         "          <arg type='i' name='do_not_disturb' direction='in'/>"
317                         "          <arg type='i' name='visibility_class' direction='in'/>"
318                         "          <arg type='i' name='dnd_schedule_enabled' direction='in'/>"
319                         "          <arg type='i' name='dnd_schedule_day' direction='in'/>"
320                         "          <arg type='i' name='dnd_start_hour' direction='in'/>"
321                         "          <arg type='i' name='dnd_start_min' direction='in'/>"
322                         "          <arg type='i' name='dnd_end_hour' direction='in'/>"
323                         "          <arg type='i' name='dnd_end_min' direction='in'/>"
324                         "          <arg type='i' name='lock_screen_level' direction='in'/>"
325                         "          <arg type='i' name='uid' direction='in'/>"
326                         "        </method>"
327
328                         "        <method name='get_setting_array'>"
329                         "          <arg type='i' name='uid' direction='in'/>"
330                         "          <arg type='i' name='setting_cnt' direction='out'/>"
331                         "          <arg type='a(v)' name='setting_arr' direction='out'/>"
332                         "        </method>"
333
334                         "        <method name='get_setting_by_app_id'>"
335                         "          <arg type='s' name='app_id' direction='in'/>"
336                         "          <arg type='i' name='uid' direction='in'/>"
337                         "          <arg type='v' name='setting' direction='out'/>"
338                         "        </method>"
339
340                         "        <method name='load_system_setting'>"
341                         "          <arg type='i' name='uid' direction='in'/>"
342                         "          <arg type='v' name='setting' direction='out'/>"
343                         "        </method>"
344
345                         "        <method name='save_as_template'>"
346                         "          <arg type='v' name='noti' direction='in'/>"
347                         "          <arg type='s' name='name' direction='in'/>"
348                         "        </method>"
349
350                         "        <method name='create_from_template'>"
351                         "          <arg type='s' name='name' direction='in'/>"
352                         "          <arg type='v' name='noti' direction='out'/>"
353                         "        </method>"
354
355                         "        <method name='create_from_package_template'>"
356                         "          <arg type='s' name='app_id' direction='in'/>"
357                         "          <arg type='s' name='name' direction='in'/>"
358                         "          <arg type='v' name='noti' direction='out'/>"
359                         "        </method>"
360
361                         "        <method name='get_noti_block_state'>"
362                         "          <arg type='s' name='app_id' direction='in'/>"
363                         "          <arg type='i' name='uid' direction='in'/>"
364                         "          <arg type='v' name='state' direction='out'/>"
365                         "        </method>"
366
367                         "        <method name='update_dnd_allow_exception'>"
368                         "          <arg type='i' name='type' direction='in'/>"
369                         "          <arg type='i' name='value' direction='in'/>"
370                         "          <arg type='i' name='uid' direction='in'/>"
371                         "        </method>"
372
373                         "        <method name='load_dnd_allow_exception'>"
374                         "          <arg type='i' name='uid' direction='in'/>"
375                         "          <arg type='i' name='count' direction='out'/>"
376                         "          <arg type='a(v)' name='dnd_allow_exception' direction='out'/>"
377                         "        </method>"
378
379                         "        <method name='send_noti_event'>"
380                         "          <arg type='v' name='noti' direction='in'/>"
381                         "          <arg type='i' name='event_type' direction='in'/>"
382                         "        </method>"
383
384                         "        <method name='send_noti_event_by_priv_id'>"
385                         "          <arg type='i' name='priv_id' direction='in'/>"
386                         "          <arg type='i' name='event_type' direction='in'/>"
387                         "        </method>"
388
389                         "        <method name='check_event_receiver'>"
390                         "          <arg type='i' name='priv_id' direction='in'/>"
391                         "          <arg type='i' name='available' direction='out'/>"
392                         "        </method>"
393
394                         "        <method name='reset_event_handler'>"
395                         "          <arg type='i' name='priv_id' direction='in'/>"
396                         "        </method>"
397
398                         "        <method name='del_noti_by_display_applist'>"
399                         "          <arg type='i' name='display_applist' direction='in'/>"
400                         "          <arg type='i' name='uid' direction='in'/>"
401                         "          <arg type='i' name='priv_id' direction='out'/>"
402                         "        </method>"
403
404                         "        <method name='post_toast'>"
405                         "        </method>"
406                         "  </interface>"
407                         "  </node>";
408
409         return service_common_register_dbus_interface(introspection_xml, _noti_interface_vtable);
410 }
411
412 static void __free_event_info(gpointer data)
413 {
414         event_sender_info_s *info = (event_sender_info_s *)data;
415
416         if (info) {
417                 if (info->busname)
418                         free(info->busname);
419                 free(info);
420         }
421 }
422
423 static gint __priv_id_compare(gconstpointer a, gconstpointer b)
424 {
425         event_sender_info_s *info = NULL;
426
427         if (!a)
428                 return -1;
429
430         info = (event_sender_info_s *)a;
431
432         if (info->priv_id == GPOINTER_TO_INT(b))
433                 return 0;
434
435         return 1;
436 }
437
438 static int __check_limit(notification_h noti, uid_t uid)
439 {
440         int ret;
441         int priv_id = NOTIFICATION_PRIV_ID_NONE;
442         char *app_id = NULL;
443         GList *list = NULL;
444         GList *iter_list = NULL;
445
446         ret = notification_noti_check_limit(noti, uid, &list);
447         if (ret == NOTIFICATION_ERROR_NONE && list != NULL) {
448                 ret = notification_get_pkgname(noti, &app_id);
449                 if (ret == NOTIFICATION_ERROR_NONE && app_id != NULL) {
450                         iter_list = list;
451                         while (iter_list) {
452                                 priv_id = GPOINTER_TO_INT(iter_list->data);
453
454                                 ret = _delete_noti((const char *)app_id, priv_id, uid);
455                                 if (ret != NOTIFICATION_ERROR_NONE)
456                                         ERR("Failed to delete noti[%d], err[%d]",
457                                                 priv_id, ret);
458
459                                 iter_list = g_list_next(iter_list);
460                         }
461                 }
462         }
463
464         if (list)
465                 g_list_free(list);
466
467         return ret;
468 }
469
470 /* add noti */
471 static int _add_noti(GVariant **reply_body, notification_h noti, uid_t uid)
472 {
473         int ret;
474         int priv_id = NOTIFICATION_PRIV_ID_NONE;
475         GVariant *body = NULL;
476
477         __print_noti(noti);
478         ret = notification_noti_insert(noti);
479         if (ret != NOTIFICATION_ERROR_NONE) {
480                 ERR("Failed to update a notification [%d]", ret);
481                 return ret;
482         }
483
484         ret = notification_get_id(noti, NULL, &priv_id);
485         if (ret != NOTIFICATION_ERROR_NONE) {
486                 ERR("Failed to gets priv_id [%d]", ret);
487                 return ret;
488         }
489
490         notification_set_private_sharing(noti, uid);
491
492         body = notification_ipc_make_gvariant_from_noti(noti, true);
493         if (body == NULL) {
494                 ERR("Failed to make gvariant to noti");
495                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
496         }
497
498         ret = send_notify(body, "add_noti_notify", &_monitoring_hash,
499                         PROVIDER_NOTI_INTERFACE_NAME, uid);
500         g_variant_unref(body);
501
502         if (ret != NOTIFICATION_ERROR_NONE) {
503                 ERR("Failed to send notify [%d]", ret);
504                 return ret;
505         }
506
507         ret = notification_launch_default_viewer(priv_id,
508                         NOTIFICATION_OP_INSERT, uid);
509         if (ret != NOTIFICATION_ERROR_NONE) {
510                 ERR("Failed to launch default viewer [%d]", ret);
511                 ret = NOTIFICATION_ERROR_NONE;
512         }
513
514
515         *reply_body = g_variant_new("(i)", priv_id);
516         if (*reply_body == NULL) {
517                 ERR("Failed to make reply");
518                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
519         }
520
521         ret = __check_limit(noti, uid);
522         if (ret != NOTIFICATION_ERROR_NONE) {
523                 ERR("Failed to check limit [%d]", ret);
524                 ret = NOTIFICATION_ERROR_NONE;
525         }
526
527         DBG("Success to add notification");
528         return ret;
529 }
530
531 static int _validate_and_set_noti_with_uid(uid_t uid, notification_h noti, uid_t *noti_uid)
532 {
533         int ret = NOTIFICATION_ERROR_NONE;
534
535         ret = notification_get_uid(noti, noti_uid);
536         if (ret != NOTIFICATION_ERROR_NONE) {
537                 ERR("Failed to get uid [%d]", ret);
538                 return ret;
539         }
540
541         if (uid > NORMAL_UID_BASE && uid != *noti_uid) {
542                 ERR("Invalid seder uid[%d] noti_uid[%d]", uid, *noti_uid);
543                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
544         } else if (uid <= NORMAL_UID_BASE) {
545                 if (*noti_uid <= NORMAL_UID_BASE) {
546                         if (*noti_uid != uid)
547                                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
548
549                         DBG("system defualt noti post change noti_uid to default");
550                         /*
551                         IF system (uid <= NORMAL_UID_BASE) try to send noti without specipic destination uid (using notification_pot API)
552                         Send it to default user (TZ_SYS_DEFAULT_USER)
553                         */
554                         *noti_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
555                         ret = notification_set_uid(noti, *noti_uid);
556                         if (ret != NOTIFICATION_ERROR_NONE) {
557                                 ERR("Failed to set uid [%d]", ret);
558                                 return ret;
559                         }
560                         DBG("changed noti_uid[%d]", *noti_uid);
561                 }
562         }
563         return ret;
564 }
565
566 static int _validate_and_set_param_uid_with_uid(uid_t uid, uid_t *param_uid)
567 {
568         if (uid > NORMAL_UID_BASE && uid != *param_uid) {
569                 ERR("invalid seder uid[%d], param_uid[%d]", uid, *param_uid);
570                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
571         } else if (uid <= NORMAL_UID_BASE) {
572                 if (*param_uid <= NORMAL_UID_BASE) {
573                         if (*param_uid != uid)
574                                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
575                         /*
576                         IF system (uid <= NORMAL_UID_BASE) try to send noti without specipic destination uid (using notification_pot API)
577                         Send it to default user (TZ_SYS_DEFAULT_USER)
578                         */
579                         *param_uid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
580                 }
581         }
582         return NOTIFICATION_ERROR_NONE;
583 }
584
585 static void __sender_name_appeared_cb(GDBusConnection *connection,
586                                       const gchar *name,
587                                       const gchar *name_owner,
588                                       gpointer user_data)
589 {
590         DBG("name[%s], name_owner[%s]", name, name_owner);
591 }
592
593 static void __sender_name_vanished_cb(GDBusConnection *connection,
594                                       const gchar *name,
595                                       gpointer user_data)
596 {
597         GList *delete_list = NULL;
598         event_sender_info_s *info;
599
600         if (!user_data)
601                 return;
602
603         info = (event_sender_info_s *)user_data;
604
605         DBG("name[%s], priv_id[%d], watcher_id[%d]",
606                  name, info->priv_id, info->watcher_id);
607
608         delete_list = g_list_find_custom(__event_list, GINT_TO_POINTER(info->priv_id),
609                                          (GCompareFunc)__priv_id_compare);
610         if (delete_list) {
611                 __event_list = g_list_remove(__event_list, info);
612                 g_bus_unwatch_name(info->watcher_id);
613                 __free_event_info(info);
614         }
615 }
616
617 static guint __insert_sender_watcher_id(event_sender_info_s *sender_info)
618 {
619         guint watcher_id = 0;
620
621         watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
622                                       sender_info->busname,
623                                       G_BUS_NAME_WATCHER_FLAGS_NONE,
624                                       __sender_name_appeared_cb,
625                                       __sender_name_vanished_cb,
626                                       sender_info,
627                                       NULL);
628         if (!watcher_id) {
629                 ERR("Failed to watch sender name");
630                 return 0;
631         }
632
633         DBG("Watch on busname[%s] watcher_id[%d]", sender_info->busname, watcher_id);
634         return watcher_id;
635 }
636
637 static void __add_sender_info(int priv_id, const char *busname)
638 {
639         GList *find_list = NULL;
640         event_sender_info_s *sender_info;
641         event_sender_info_s *tmp_info = NULL;
642
643         if (busname == NULL)
644                 return;
645
646         sender_info = (event_sender_info_s *)malloc(sizeof(event_sender_info_s));
647         if (sender_info == NULL) {
648                 ERR("malloc failed");
649                 return;
650         }
651
652         sender_info->priv_id = priv_id;
653         sender_info->busname = strdup(busname);
654
655         if (__event_list == NULL) {
656                 sender_info->watcher_id = __insert_sender_watcher_id(sender_info);
657                 __event_list = g_list_append(__event_list, sender_info);
658         } else {
659                 __event_list = g_list_first(__event_list);
660                 find_list = g_list_find_custom(__event_list, GINT_TO_POINTER(priv_id),
661                                                (GCompareFunc)__priv_id_compare);
662                 if (find_list == NULL) {
663                         sender_info->watcher_id = __insert_sender_watcher_id(sender_info);
664                         __event_list = g_list_append(__event_list, sender_info);
665                 } else {
666                         tmp_info = (event_sender_info_s *)g_list_nth_data(find_list, 0);
667                         if (tmp_info->busname) {
668                                 if (strcmp(tmp_info->busname, busname)) {
669                                         free(tmp_info->busname);
670                                         tmp_info->busname = strdup(busname);
671                                         g_bus_unwatch_name(tmp_info->watcher_id);
672                                         tmp_info->watcher_id = __insert_sender_watcher_id(sender_info);
673                                 }
674                         } else {
675                                 tmp_info->busname = strdup(busname);
676                                 if (!tmp_info->watcher_id)
677                                         g_bus_unwatch_name(tmp_info->watcher_id);
678                                 tmp_info->watcher_id = __insert_sender_watcher_id(tmp_info);
679                         }
680                         __free_event_info(sender_info);
681                 }
682         }
683 }
684
685 int notification_add_noti(GVariant *parameters, GVariant **reply_body,
686                 const char *sender, pid_t pid, uid_t uid)
687 {
688         int ret;
689         int priv_id;
690         bool event_flag;
691         notification_h noti;
692         GVariant *body = NULL;
693         uid_t noti_uid = 0;
694
695         noti = notification_create(NOTIFICATION_TYPE_NOTI);
696         if (noti != NULL) {
697                 g_variant_get(parameters, "(v)", &body);
698                 ret = notification_ipc_make_noti_from_gvariant(noti, body);
699                 g_variant_unref(body);
700
701                 if (uid >= NORMAL_UID_BASE)
702                         notification_set_indirect_request(noti, pid, uid);
703
704                 ret = _validate_and_set_noti_with_uid(uid, noti, &noti_uid);
705                 if (ret != NOTIFICATION_ERROR_NONE)
706                         goto out;
707
708                 ret = notification_noti_check_tag(noti);
709                 if (ret == NOTIFICATION_ERROR_NOT_EXIST_ID)
710                         ret = _add_noti(reply_body, noti, noti_uid);
711                 else if (ret == NOTIFICATION_ERROR_ALREADY_EXIST_ID)
712                         ret = _update_noti(reply_body, noti, noti_uid);
713
714                 if (ret != NOTIFICATION_ERROR_NONE)
715                         goto out;
716
717                 ret = notification_get_event_flag(noti, &event_flag);
718                 if (ret != NOTIFICATION_ERROR_NONE)
719                         goto out;
720
721                 if (event_flag == true) {
722                         ret = notification_get_id(noti, NULL, &priv_id);
723                         if (ret != NOTIFICATION_ERROR_NONE)
724                                 goto out;
725
726                         __add_sender_info(priv_id, sender);
727                 }
728         } else {
729                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
730         }
731
732 out:
733         notification_free(noti);
734
735         return ret;
736 }
737
738 /* update noti */
739 static int _update_noti(GVariant **reply_body, notification_h noti, uid_t uid)
740 {
741         int ret;
742         GVariant *body = NULL;
743         int priv_id = NOTIFICATION_PRIV_ID_NONE;
744         notification_h source_noti;
745
746         __print_noti(noti);
747
748         ret = notification_get_id(noti, NULL, &priv_id);
749         if (ret != NOTIFICATION_ERROR_NONE) {
750                 ERR("Failed to get priv_id [%d]", ret);
751                 return ret;
752         }
753
754         if (notification_validate_private_sharing(noti) == false) {
755                 source_noti = notification_create(NOTIFICATION_TYPE_NOTI);
756                 if (source_noti == NULL)
757                         return get_last_result();
758                 notification_noti_get_by_priv_id(source_noti, priv_id);
759
760                 notification_calibrate_private_sharing(noti, source_noti);
761                 notification_free(source_noti);
762         }
763
764         ret = notification_noti_update(noti);
765         if (ret != NOTIFICATION_ERROR_NONE) {
766                 ERR("Failed to update a notification [%d]", ret);
767                 return ret;
768         }
769
770         notification_set_private_sharing(noti, uid);
771
772         body = notification_ipc_make_gvariant_from_noti(noti, true);
773         if (body == NULL) {
774                 ERR("Failed to make gvariant to noti");
775                 return NOTIFICATION_ERROR_IO_ERROR;
776         }
777
778         ret = send_notify(body, "update_noti_notify", &_monitoring_hash, PROVIDER_NOTI_INTERFACE_NAME, uid);
779         g_variant_unref(body);
780
781         if (ret != NOTIFICATION_ERROR_NONE) {
782                 ERR("Failed to send notify [%d]", ret);
783                 return ret;
784         }
785
786         ret = notification_launch_default_viewer(priv_id,
787                         NOTIFICATION_OP_UPDATE, uid);
788         if (ret != NOTIFICATION_ERROR_NONE) {
789                 ERR("Failed to launch default viewer [%d]", ret);
790                 ret = NOTIFICATION_ERROR_NONE;
791         }
792
793         *reply_body = g_variant_new("(i)", priv_id);
794         if (*reply_body == NULL) {
795                 ERR("Failed to make reply_body");
796                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
797         }
798
799         DBG("Success to update noti");
800         return ret;
801 }
802
803 int notification_update_noti(GVariant *parameters, GVariant **reply_body,
804                 pid_t pid, uid_t uid)
805 {
806         notification_h noti;
807         int ret;
808         GVariant *body = NULL;
809         uid_t noti_uid;
810
811         noti = notification_create(NOTIFICATION_TYPE_NOTI);
812         if (noti != NULL) {
813                 g_variant_get(parameters, "(v)", &body);
814                 ret = notification_ipc_make_noti_from_gvariant(noti, body);
815                 g_variant_unref(body);
816
817                 if (uid >= NORMAL_UID_BASE)
818                         notification_set_indirect_request(noti, pid, uid);
819
820                 ret = _validate_and_set_noti_with_uid(uid, noti, &noti_uid);
821                 if (ret != NOTIFICATION_ERROR_NONE)
822                         goto out;
823
824                 ret = _update_noti(reply_body, noti, noti_uid);
825
826         } else {
827                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
828         }
829
830 out:
831         notification_free(noti);
832         return ret;
833 }
834
835 /* load_noti_by_tag */
836 int notification_load_noti_by_tag(GVariant *parameters, GVariant **reply_body, uid_t uid)
837 {
838         int ret;
839         char *tag = NULL;
840         char *app_id = NULL;
841         notification_h noti;
842         uid_t param_uid;
843
844         noti = notification_create(NOTIFICATION_TYPE_NOTI);
845         if (noti != NULL) {
846                 g_variant_get(parameters, "(&s&si)", &app_id, &tag, &param_uid);
847                 ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
848                 if (ret != NOTIFICATION_ERROR_NONE)
849                         goto out;
850
851                 DBG("_load_noti_by_tag app_id : %s, tag : %s ", app_id, tag);
852                 ret = notification_noti_get_by_tag(noti, app_id, tag, param_uid);
853                 if (ret != NOTIFICATION_ERROR_NONE) {
854                         ERR("No matched tag [%s]", tag);
855                         goto out;
856                 }
857
858                 __print_noti(noti);
859                 *reply_body = notification_ipc_make_gvariant_from_noti(noti, true);
860                 if (*reply_body == NULL) {
861                         ERR("Failed to make reply_body");
862                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
863                 }
864         } else {
865                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
866         }
867
868 out:
869         if (noti)
870                 notification_free(noti);
871
872         return ret;
873 }
874
875 /* load_noti_by_priv_id */
876 int notification_load_noti_by_priv_id(GVariant *parameters, GVariant **reply_body, uid_t uid)
877 {
878         int ret;
879         int priv_id = NOTIFICATION_PRIV_ID_NONE;
880         char *app_id = NULL;
881         notification_h noti;
882         uid_t param_uid;
883
884         noti = notification_create(NOTIFICATION_TYPE_NOTI);
885         if (noti != NULL) {
886                 g_variant_get(parameters, "(&sii)", &app_id, &priv_id, &param_uid);
887                 ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
888                 if (ret != NOTIFICATION_ERROR_NONE)
889                         goto out;
890
891                 DBG("load_noti_by_priv_id app_id : %s, priv_id : %d ", app_id, priv_id);
892                 ret = notification_noti_get_by_priv_id(noti, priv_id);
893                 if (ret != NOTIFICATION_ERROR_NONE)
894                         goto out;
895
896                 *reply_body = notification_ipc_make_gvariant_from_noti(noti, true);
897                 if (*reply_body == NULL) {
898                         ERR("Failed to make reply_body");
899                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
900                 }
901         } else {
902                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
903         }
904
905 out:
906         if (noti)
907                 notification_free(noti);
908
909         return ret;
910 }
911
912 static int __get_socket_from_invocation(GDBusMethodInvocation *invocation, int *fd)
913 {
914         int ret_fd = 0;
915         GError *g_err = NULL;
916         GDBusMessage *msg = NULL;
917         GUnixFDList *fd_list = NULL;
918
919         msg = g_dbus_method_invocation_get_message(invocation);
920         fd_list = g_dbus_message_get_unix_fd_list(msg);
921         if (fd_list == NULL) {
922                 ERR("fd list is null");
923                 return NOTIFICATION_ERROR_IO_ERROR;
924         }
925
926         ret_fd = g_unix_fd_list_get(fd_list, 0, &g_err);
927         if (ret_fd == -1 || g_err) {
928                 ERR("g_unix_fd_list_get [%s]", g_err->message);
929                 g_error_free(g_err);
930                 return NOTIFICATION_ERROR_IO_ERROR;
931         }
932
933         *fd = ret_fd;
934
935         INFO("sender fd : %d", ret_fd);
936         return NOTIFICATION_ERROR_NONE;
937 }
938
939 static int __send_list_to_socket(int fd, notification_list_h get_list, uid_t uid)
940 {
941         int ret;
942         notification_h noti;
943         notification_list_h list_iter;
944         GVariant *body = NULL;
945
946         list_iter = notification_list_get_head(get_list);
947         do {
948                 noti = notification_list_get_data(list_iter);
949                 notification_set_private_sharing(noti, uid);
950                 body = notification_ipc_make_gvariant_from_noti(noti, true);
951                 if (body == NULL) {
952                         ERR("Failed to make gvariant to noti");
953                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
954                         break;
955                 }
956                 ret = notification_ipc_socket_write_string(fd,
957                                 (char *)g_variant_get_data(body),
958                                 g_variant_get_size(body));
959                 if (ret != NOTIFICATION_ERROR_NONE) {
960                         ERR("write string to socket fail");
961                         g_variant_unref(body);
962                         return ret;
963                 }
964                 list_iter = notification_list_get_next(list_iter);
965                 g_variant_unref(body);
966         } while (list_iter != NULL);
967
968         return ret;
969 }
970
971 /* load_noti_grouping_list */
972 void notification_load_grouping_list(GDBusMethodInvocation *invocation, GVariant *parameters, uid_t uid)
973 {
974         int ret;
975         notification_type_e type;
976         notification_list_h get_list = NULL;
977         GVariant *reply_body = NULL;
978         int fd = 0;
979         int count = 0;
980         int count_per_page;
981         int list_count = 0;
982         uid_t param_uid;
983
984         g_variant_get(parameters, "(iiii)", &type, &count, &count_per_page, &param_uid);
985         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
986         if (ret != NOTIFICATION_ERROR_NONE)
987                 goto err;
988
989         ret = __get_socket_from_invocation(invocation, &fd);
990         if (ret != NOTIFICATION_ERROR_NONE) {
991                 ERR("get_fd_from_invocation [%d]", ret);
992                 goto err;
993         }
994
995         ret = notification_noti_get_grouping_list(type, count, count_per_page,
996                         &get_list, &list_count, param_uid);
997         if (ret != NOTIFICATION_ERROR_NONE) {
998                 ERR("notification_noti_get_grouping_list [%d]", ret);
999                 goto err;
1000         }
1001
1002         reply_body = g_variant_new("(i)", list_count);
1003         if (reply_body == NULL) {
1004                 ERR("Failed to make reply_body");
1005                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
1006                 goto err;
1007         }
1008
1009         g_dbus_method_invocation_return_value(invocation, reply_body);
1010         if (get_list) {
1011                 ret = __send_list_to_socket(fd, get_list, param_uid);
1012                 if (ret != NOTIFICATION_ERROR_NONE)
1013                         ERR("__send_list_to_socket [%d]", ret);
1014                 notification_free_list(get_list);
1015         }
1016
1017         close(fd);
1018         return;
1019
1020 err:
1021         if (fd)
1022                 close(fd);
1023         if (get_list)
1024                 notification_free_list(get_list);
1025
1026         ERR("notification service fail, method name[load_noti_grouping_list] [%d]", ret);
1027         g_dbus_method_invocation_return_error(invocation, NOTIFICATION_ERROR,
1028                                 ret, "notification_service_error");
1029 }
1030
1031 /* get_setting_array */
1032 int notification_get_setting_array(GVariant *parameters, GVariant **reply_body, uid_t uid)
1033 {
1034         int ret;
1035         GVariant *body;
1036         GVariantBuilder *builder;
1037         int count = 0;
1038         int i;
1039         notification_setting_h setting_array = NULL;
1040         notification_setting_h temp;
1041         uid_t param_uid;
1042
1043         g_variant_get(parameters, "(i)", &param_uid);
1044         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1045         if (ret != NOTIFICATION_ERROR_NONE)
1046                 return ret;
1047
1048         ret = noti_setting_get_setting_array(&setting_array, &count, param_uid);
1049         if (ret != NOTIFICATION_ERROR_NONE)
1050                 return ret;
1051
1052         builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)"));
1053
1054         if (setting_array) {
1055                 for (i = 0; i < count; i++) {
1056                         temp = setting_array + i;
1057                         body = notification_ipc_make_gvariant_from_setting(temp);
1058                         g_variant_builder_add(builder, "(v)", body);
1059
1060                         if (temp->package_name)
1061                                 free(temp->package_name);
1062                         if (temp->app_id)
1063                                 free(temp->app_id);
1064                 }
1065                 free(setting_array);
1066         }
1067         *reply_body = g_variant_new("(ia(v))", count, builder);
1068         g_variant_builder_unref(builder);
1069
1070         if (*reply_body == NULL) {
1071                 ERR("Failed to make reply_body");
1072                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1073         }
1074
1075         INFO("count[%d]", count);
1076         return ret;
1077 }
1078
1079 static pkgmgrinfo_pkginfo_h __create_pkginfo_by_app_id(const char *app_id, uid_t uid)
1080 {
1081         int ret_pkgmgr;
1082         char *pkgname = NULL;
1083         pkgmgrinfo_appinfo_h app_handle = NULL;
1084         pkgmgrinfo_pkginfo_h pkg_handle = NULL;
1085
1086         if (app_id == NULL)
1087                 return NULL;
1088
1089         ret_pkgmgr = pkgmgrinfo_appinfo_get_usr_appinfo(app_id, uid, &app_handle);
1090         if (ret_pkgmgr != PMINFO_R_OK) {
1091                 ERR("Failed to pkgmgrinfo_appinfo_get_appinfo [%s][%d]",
1092                         app_id, ret_pkgmgr);
1093                 goto out;
1094         }
1095
1096         ret_pkgmgr = pkgmgrinfo_appinfo_get_pkgname(app_handle, &pkgname);
1097         if (ret_pkgmgr != PMINFO_R_OK) {
1098                 ERR("Failed to pkgmgrinfo_appinfo_get_pkgname [%s][%d]",
1099                         app_id, ret_pkgmgr);
1100                 goto out;
1101         }
1102
1103         ret_pkgmgr = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgname, uid, &pkg_handle);
1104         if (ret_pkgmgr != PMINFO_R_OK) {
1105                 ERR("Failed to pkgmgrinfo_appinfo_get_pkginfo [%s][%d]",
1106                         app_id, ret_pkgmgr);
1107                 goto out;
1108         }
1109
1110 out:
1111         if (app_handle)
1112                 pkgmgrinfo_appinfo_destroy_appinfo(app_handle);
1113
1114         return pkg_handle;
1115 }
1116
1117 #define NOTIFICATION_PRIVILEGE "http://tizen.org/privilege/notification"
1118 static int __check_privilege_cb(const char *privilege_name, void *is_existed)
1119 {
1120         if (!g_strcmp0(privilege_name, NOTIFICATION_PRIVILEGE)) {
1121                 *(int *)is_existed = 1;
1122                 return -1;
1123         }
1124         return 0;
1125 }
1126
1127 static int __has_notification_privilege(pkgmgrinfo_pkginfo_h handle)
1128 {
1129         int ret_pkgmgr;
1130         int is_existed = 0;
1131
1132         ret_pkgmgr = pkgmgrinfo_pkginfo_foreach_privilege(handle, __check_privilege_cb, &is_existed);
1133         if (ret_pkgmgr != PMINFO_R_OK) {
1134                 ERR("Failed to pkgmgrinfo_foreach_privilege [%d]",
1135                         ret_pkgmgr);
1136                 return NOTIFICATION_ERROR_IO_ERROR;
1137         }
1138
1139         if (is_existed == 0)
1140                 return NOTIFICATION_ERROR_NOT_EXIST_ID;
1141
1142         return NOTIFICATION_ERROR_NONE;
1143 }
1144
1145 static int __init_setting_handle_by_app_id(const char *app_id,
1146                                 notification_setting_h *setting, uid_t uid)
1147 {
1148         int ret = NOTIFICATION_ERROR_NONE;
1149         int ret_pkgmgr;
1150         char *pkgname = NULL;
1151         notification_setting_h ret_setting = NULL;
1152         pkgmgrinfo_pkginfo_h handle = NULL;
1153
1154         if (app_id == NULL || setting == NULL)
1155                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1156
1157         handle = __create_pkginfo_by_app_id(app_id, uid);
1158         if (handle == NULL) {
1159                 ERR("Failed to create pkginfo by app_id [%s]", app_id);
1160                 ret = NOTIFICATION_ERROR_IO_ERROR;
1161                 goto out;
1162         }
1163
1164         ret = __has_notification_privilege(handle);
1165         if (ret != NOTIFICATION_ERROR_NONE) {
1166                 if (ret == NOTIFICATION_ERROR_NOT_EXIST_ID)
1167                         DBG("No notification privilege [%s]", app_id);
1168                 else
1169                         ERR("Failed to check privilege [%d]", ret);
1170                 goto out;
1171         }
1172
1173         ret_pkgmgr = pkgmgrinfo_pkginfo_get_pkgname(handle, &pkgname);
1174         if (ret_pkgmgr != PMINFO_R_OK) {
1175                 ERR("Failed to get pkgname from pkginfo [%d]", ret_pkgmgr);
1176                 ret = NOTIFICATION_ERROR_IO_ERROR;
1177                 goto out;
1178         }
1179
1180         ret_setting = (struct notification_setting *)malloc(sizeof(struct notification_setting));
1181         if (ret_setting == NULL) {
1182                 ERR("Failed to alloc memory");
1183                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
1184                 goto out;
1185         }
1186
1187         ret_setting->package_name = strdup(pkgname);
1188         ret_setting->app_id = strdup(app_id);
1189         ret_setting->allow_to_notify = 1;
1190         ret_setting->do_not_disturb_except = 0;
1191         ret_setting->visibility_class = 0;
1192         ret_setting->pop_up_notification = 1;
1193         ret_setting->lock_screen_content_level = 0;
1194         ret_setting->app_disabled = 0;
1195
1196         *setting = ret_setting;
1197
1198 out:
1199         if (handle)
1200                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1201
1202         return ret;
1203 }
1204
1205 /* get_setting_by_app_id */
1206 int notification_get_setting_by_app_id(GVariant *parameters, GVariant **reply_body, uid_t uid)
1207 {
1208         int ret;
1209         GVariant *body;
1210         char *app_id = NULL;
1211         notification_setting_h setting = NULL;
1212         uid_t param_uid;
1213
1214         g_variant_get(parameters, "(&si)", &app_id, &param_uid);
1215         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1216         if (ret != NOTIFICATION_ERROR_NONE)
1217                 return ret;
1218
1219         ret = noti_setting_service_get_setting_by_app_id(app_id, &setting, param_uid);
1220         if (ret == NOTIFICATION_ERROR_NOT_EXIST_ID) {
1221                 ret = __init_setting_handle_by_app_id(app_id, &setting, param_uid);
1222                 if (ret != NOTIFICATION_ERROR_NONE)
1223                         return ret;
1224         } else if (ret != NOTIFICATION_ERROR_NONE) {
1225                 return ret;
1226         }
1227
1228         body = notification_ipc_make_gvariant_from_setting(setting);
1229         notification_setting_free_notification(setting);
1230         if (body == NULL) {
1231                 ERR("Failed to make gvariant");
1232                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1233         }
1234
1235         *reply_body = g_variant_new("(v)", body);
1236         if (*reply_body == NULL) {
1237                 ERR("Failed to make reply_body");
1238                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1239         }
1240
1241         INFO("app_id[%s] uid[%d]", app_id, param_uid);
1242         return ret;
1243 }
1244
1245 /* load_system_setting */
1246 int notification_load_system_setting(GVariant *parameters, GVariant **reply_body, uid_t uid)
1247 {
1248         int ret;
1249         GVariant *body;
1250         notification_system_setting_h setting = NULL;
1251         uid_t param_uid;
1252
1253         g_variant_get(parameters, "(i)", &param_uid);
1254         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1255         if (ret != NOTIFICATION_ERROR_NONE)
1256                 return ret;
1257
1258         ret = noti_system_setting_load_system_setting(&setting, param_uid);
1259         if (ret == NOTIFICATION_ERROR_NONE) {
1260                 body = notification_ipc_make_gvariant_from_system_setting(setting);
1261                 notification_system_setting_free_system_setting(setting);
1262
1263                 if (body == NULL) {
1264                         ERR("Failed to make gvariant");
1265                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1266                 }
1267         } else {
1268                 return ret;
1269         }
1270
1271         *reply_body = g_variant_new("(v)", body);
1272         if (*reply_body == NULL) {
1273                 ERR("Failed to make reply_body");
1274                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1275         }
1276
1277         return ret;
1278 }
1279
1280 /* load_noti_detail_list */
1281 int notification_load_detail_list(GVariant *parameters, GVariant **reply_body, uid_t uid)
1282 {
1283         int ret;
1284         notification_h noti;
1285         GVariant *body = NULL;
1286         notification_list_h get_list = NULL;
1287         notification_list_h list_iter;
1288         GVariantBuilder *builder;
1289         char *app_id = NULL;
1290         int group_id = NOTIFICATION_GROUP_ID_NONE;
1291         int priv_id = NOTIFICATION_PRIV_ID_NONE;
1292         int count = 0;
1293         uid_t param_uid;
1294
1295         g_variant_get(parameters, "(&siiii)", &app_id, &group_id, &priv_id, &count, &param_uid);
1296         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1297         if (ret != NOTIFICATION_ERROR_NONE)
1298                 return ret;
1299
1300         ret = notification_noti_get_detail_list(app_id, group_id, priv_id,
1301                         count, &get_list, param_uid);
1302         if (ret != NOTIFICATION_ERROR_NONE)
1303                 return ret;
1304
1305         builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)"));
1306
1307         if (get_list) {
1308                 list_iter = notification_list_get_head(get_list);
1309                 do {
1310                         noti = notification_list_get_data(list_iter);
1311                         notification_set_private_sharing(noti, param_uid);
1312                         body = notification_ipc_make_gvariant_from_noti(noti, true);
1313                         if (body) {
1314                                 g_variant_builder_add(builder, "(v)", body);
1315                                 list_iter = notification_list_get_next(list_iter);
1316                         }
1317                 } while (list_iter != NULL);
1318                 notification_free_list(get_list);
1319         }
1320
1321         *reply_body = g_variant_new("(a(v))", builder);
1322         g_variant_builder_unref(builder);
1323
1324         if (*reply_body == NULL) {
1325                 ERR("Failed to make reply_body");
1326                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1327         }
1328
1329         DBG("app_id[%s], group_id[%d], priv_id[%d], count[%d]",
1330                         app_id, group_id, priv_id, count);
1331         return ret;
1332 }
1333
1334 /* refresh_noti */
1335 int notification_refresh_noti(GVariant *parameters, GVariant **reply_body, uid_t uid)
1336 {
1337         int ret;
1338         uid_t param_uid;
1339
1340         g_variant_get(parameters, "(i)", &param_uid);
1341         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1342         if (ret != NOTIFICATION_ERROR_NONE)
1343                 return ret;
1344
1345         ret = send_notify(parameters, "refresh_noti_notify", &_monitoring_hash, PROVIDER_NOTI_INTERFACE_NAME, param_uid);
1346         if (ret != NOTIFICATION_ERROR_NONE) {
1347                 ERR("Failed to send notify [%d]", ret);
1348                 return ret;
1349         }
1350
1351         *reply_body = g_variant_new("()");
1352         if (*reply_body == NULL) {
1353                 ERR("Failed to make reply_body");
1354                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1355         }
1356
1357         return ret;
1358 }
1359
1360 static int __delete_sender_info(int priv_id)
1361 {
1362         int ret = NOTIFICATION_ERROR_NONE;
1363         event_sender_info_s *info;
1364         GList *delete_list = NULL;
1365         GVariant *body = NULL;
1366
1367         if (__event_list != NULL) {
1368                 __event_list = g_list_first(__event_list);
1369                 delete_list = g_list_find_custom(__event_list, GINT_TO_POINTER(priv_id),
1370                                                  (GCompareFunc)__priv_id_compare);
1371                 if (delete_list != NULL) {
1372                         info = (event_sender_info_s *)g_list_nth_data(delete_list, 0);
1373                         body = g_variant_new("(i)", priv_id);
1374                         ret = send_event_notify_by_busname(body, "delete_noti", info->busname, PROVIDER_NOTI_EVENT_INTERFACE_NAME);
1375                         g_variant_unref(body);
1376                         if (ret != NOTIFICATION_ERROR_NONE) {
1377                                 ERR("Failed to send event notify [%d]", ret);
1378                                 return ret;
1379                         }
1380                         __event_list = g_list_remove(g_list_first(__event_list), info);
1381                         g_bus_unwatch_name(info->watcher_id);
1382                         __free_event_info(info);
1383                         if (g_list_length(__event_list) == 0)
1384                                 __event_list = NULL;
1385                 }
1386         }
1387
1388         return ret;
1389 }
1390
1391 static int _delete_noti(const char *app_id, int priv_id, uid_t uid)
1392 {
1393         int ret;
1394         int num_changes = 0;
1395         GVariant *body = NULL;
1396
1397         if (app_id == NULL)
1398                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1399
1400         ret = notification_noti_delete_by_priv_id_get_changes(app_id, priv_id,
1401                                 &num_changes, uid);
1402         if (ret != NOTIFICATION_ERROR_NONE) {
1403                 ERR("Failed to delete noti, err[%d] num_changes[%d]",
1404                         ret, num_changes);
1405                 return ret;
1406         }
1407
1408         if (num_changes > 0) {
1409                 body = g_variant_new("(iii)", 1, priv_id, uid);
1410                 if (body == NULL) {
1411                         ERR("Failed to make gvariant to noti");
1412                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1413                 }
1414                 ret = send_notify(body, "delete_single_notify",
1415                         &_monitoring_hash, PROVIDER_NOTI_INTERFACE_NAME, uid);
1416                 g_variant_unref(body);
1417                 if (ret != NOTIFICATION_ERROR_NONE) {
1418                         ERR("Failed to send notify [%d]", ret);
1419                         return ret;
1420                 }
1421
1422                 notification_remove_private_sharing(app_id, priv_id, uid);
1423
1424                 ret = __delete_sender_info(priv_id);
1425                 if (ret != NOTIFICATION_ERROR_NONE)
1426                         return ret;
1427
1428                 ret = notification_launch_default_viewer(NOTIFICATION_PRIV_ID_NONE,
1429                                 NOTIFICATION_OP_DELETE,
1430                                 uid);
1431                 if (ret != NOTIFICATION_ERROR_NONE) {
1432                         ERR("Failed to launch default viewer [%d]", ret);
1433                         ret = NOTIFICATION_ERROR_NONE;
1434                 }
1435         }
1436
1437         DBG("app_id[%s] priv_id[%d] num_changes[%d]", app_id, priv_id, num_changes);
1438
1439         return ret;
1440 }
1441
1442 /* del_noti_single */
1443 int notification_del_noti_single(GVariant *parameters, GVariant **reply_body, uid_t uid)
1444 {
1445         int ret = NOTIFICATION_ERROR_NONE;
1446         int priv_id = NOTIFICATION_PRIV_ID_NONE;
1447         char *app_id = NULL;
1448         uid_t param_uid;
1449
1450         g_variant_get(parameters, "(&sii)", &app_id, &priv_id, &param_uid);
1451         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1452         if (ret != NOTIFICATION_ERROR_NONE)
1453                 return ret;
1454
1455         ret = _delete_noti(app_id, priv_id, param_uid);
1456         if (ret != NOTIFICATION_ERROR_NONE) {
1457                 ERR("Failed to delete noti, err[%d]", ret);
1458                 return ret;
1459         }
1460
1461         *reply_body = g_variant_new("(i)", priv_id);
1462         if (*reply_body == NULL) {
1463                 ERR("Failed to make reply_body");
1464                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1465         }
1466
1467         return ret;
1468 }
1469
1470 /* del_noti_multiple */
1471 int notification_del_noti_multiple(GVariant *parameters, GVariant **reply_body, uid_t uid)
1472 {
1473         int ret;
1474         char *app_id = NULL;
1475         notification_type_e type = NOTIFICATION_TYPE_NONE;
1476         int num_deleted = 0;
1477         int *list_deleted = NULL;
1478         GVariant *deleted_noti_list;
1479         GVariantBuilder *builder;
1480         int i;
1481         uid_t param_uid;
1482
1483         g_variant_get(parameters, "(&sii)", &app_id, &type, &param_uid);
1484         DBG("app_id [%s] type [%d]", app_id, type);
1485         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1486         if (ret != NOTIFICATION_ERROR_NONE)
1487                 return ret;
1488
1489         ret = notification_noti_delete_all(type, app_id, &num_deleted, &list_deleted, param_uid);
1490         if (ret != NOTIFICATION_ERROR_NONE) {
1491                 ERR("Failed to delete notifications [%d]", ret);
1492                 if (list_deleted != NULL)
1493                         free(list_deleted);
1494                 return ret;
1495         }
1496
1497         if (num_deleted > 0) {
1498                 builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
1499
1500                 for (i = 0; i < num_deleted; i++)
1501                         g_variant_builder_add(builder, "(i)", *(list_deleted + i));
1502
1503                 deleted_noti_list = g_variant_new("(a(i)ii)", builder, num_deleted, param_uid);
1504                 ret = send_notify(deleted_noti_list, "delete_multiple_notify", &_monitoring_hash, PROVIDER_NOTI_INTERFACE_NAME, param_uid);
1505                 g_variant_builder_unref(builder);
1506                 g_variant_unref(deleted_noti_list);
1507                 if (ret != NOTIFICATION_ERROR_NONE) {
1508                         ERR("Failed to send notify [%d]", ret);
1509                         return ret;
1510                 }
1511
1512                 for (i = 0; i < num_deleted; i++) {
1513                         notification_remove_private_sharing(app_id, *(list_deleted + i), param_uid);
1514                         ret = __delete_sender_info(*(list_deleted + i));
1515                         if (ret != NOTIFICATION_ERROR_NONE)
1516                                 return ret;
1517                 }
1518
1519                 free(list_deleted);
1520
1521                 ret = notification_launch_default_viewer(NOTIFICATION_PRIV_ID_NONE,
1522                         NOTIFICATION_OP_DELETE_ALL,
1523                         param_uid);
1524                 if (ret != NOTIFICATION_ERROR_NONE) {
1525                         ERR("Failed to launch default viewer [%d]", ret);
1526                         ret = NOTIFICATION_ERROR_NONE;
1527                 }
1528         }
1529
1530         *reply_body = g_variant_new("(i)", num_deleted);
1531         if (*reply_body == NULL) {
1532                 ERR("Failed to make reply_body");
1533                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1534         }
1535
1536         INFO("type[%d] app_id[%s] num_deleted[%d]", type, app_id, num_deleted);
1537         return ret;
1538 }
1539
1540 static void __free_deleted_list_info(notification_deleted_list_info_s *info,
1541                         int count)
1542 {
1543         int i;
1544
1545         for (i = 0; i < count; i++) {
1546                 if ((info + i)->app_id != NULL)
1547                         free((info + i)->app_id);
1548         }
1549
1550         free(info);
1551 }
1552
1553 int notification_del_noti_by_display_applist(GVariant *parameters,
1554                         GVariant **reply_body, uid_t uid)
1555 {
1556         int ret;
1557         int display_applist = 0;
1558         int deleted_num = 0;
1559         int i;
1560         GVariant *deleted_noti_list;
1561         GVariantBuilder *builder;
1562         uid_t param_uid;
1563         notification_deleted_list_info_s *deleted_list = NULL;
1564
1565         g_variant_get(parameters, "(ii)", &display_applist, &param_uid);
1566
1567         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1568         if (ret != NOTIFICATION_ERROR_NONE)
1569                 return ret;
1570
1571         ret = notification_noti_delete_by_display_applist(display_applist,
1572                                 &deleted_num, &deleted_list, param_uid);
1573         if (ret != NOTIFICATION_ERROR_NONE) {
1574                 ERR("Failed to delete notifications [%d]", ret);
1575                 if (deleted_list != NULL)
1576                         __free_deleted_list_info(deleted_list, deleted_num);
1577                 return ret;
1578         }
1579
1580         if (deleted_num > 0) {
1581                 builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
1582
1583                 for (i = 0; i < deleted_num; i++) {
1584                         g_variant_builder_add(builder, "(i)",
1585                                         (deleted_list +i)->priv_id);
1586                         notification_remove_private_sharing(
1587                                         (deleted_list +i)->app_id,
1588                                         (deleted_list +i)->priv_id,
1589                                         param_uid);
1590                         __delete_sender_info((deleted_list +i)->priv_id);
1591                 }
1592                 __free_deleted_list_info(deleted_list, deleted_num);
1593
1594                 deleted_noti_list = g_variant_new("(a(i)ii)", builder,
1595                                                 deleted_num, param_uid);
1596                 g_variant_builder_unref(builder);
1597
1598                 ret = send_notify(deleted_noti_list,
1599                         "delete_by_display_applist_notify", &_monitoring_hash,
1600                         PROVIDER_NOTI_INTERFACE_NAME, param_uid);
1601                 g_variant_unref(deleted_noti_list);
1602                 if (ret != NOTIFICATION_ERROR_NONE) {
1603                         ERR("Failed to send notify [%d]", ret);
1604                         return ret;
1605                 }
1606
1607                 ret = notification_launch_default_viewer(NOTIFICATION_PRIV_ID_NONE,
1608                         NOTIFICATION_OP_DELETE_ALL,
1609                         param_uid);
1610                 if (ret != NOTIFICATION_ERROR_NONE) {
1611                         ERR("Failed to launch default viewer [%d]", ret);
1612                         ret = NOTIFICATION_ERROR_NONE;
1613                 }
1614         }
1615
1616         *reply_body = g_variant_new("(i)", deleted_num);
1617         if (*reply_body == NULL) {
1618                 ERR("Failed to make reply_body");
1619                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1620         }
1621
1622         INFO("deleted num[%d]", deleted_num);
1623         return ret;
1624 }
1625
1626 /* get_noti_count */
1627 int notification_get_noti_count(GVariant *parameters, GVariant **reply_body, uid_t uid)
1628 {
1629         int ret;
1630         notification_type_e type = NOTIFICATION_TYPE_NONE;
1631         char *app_id = NULL;
1632         int group_id = NOTIFICATION_GROUP_ID_NONE;
1633         int priv_id = NOTIFICATION_PRIV_ID_NONE;
1634         int noti_count = 0;
1635         uid_t param_uid;
1636
1637         g_variant_get(parameters, "(i&siii)", &type, &app_id, &group_id, &priv_id, &param_uid);
1638         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1639         if (ret != NOTIFICATION_ERROR_NONE) {
1640                 ERR("Failed to validate uid [%d]", ret);
1641                 return NOTIFICATION_ERROR_IO_ERROR;
1642         }
1643
1644         ret = notification_noti_get_count(type, app_id, group_id, priv_id,
1645                         &noti_count, param_uid);
1646         if (ret != NOTIFICATION_ERROR_NONE) {
1647                 ERR("Failed to get count [%d]", ret);
1648                 return ret;
1649         }
1650
1651         *reply_body = g_variant_new("(i)", noti_count);
1652         if (*reply_body == NULL) {
1653                 ERR("Failed to make reply_body");
1654                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1655         }
1656
1657         INFO("type[%d] app_id[%s] group_id[%d] priv_id[%d] noti_count[%d]",
1658                 type, app_id, group_id, priv_id, noti_count);
1659         return ret;
1660 }
1661
1662 /* get_noti_count */
1663 int notification_get_noti_all_count(GVariant *parameters, GVariant **reply_body, uid_t uid)
1664 {
1665         int ret;
1666         int noti_count = 0;
1667         int type;
1668         uid_t param_uid;
1669
1670         g_variant_get(parameters, "(ii)", &type, &param_uid);
1671         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1672         if (ret != NOTIFICATION_ERROR_NONE) {
1673                 ERR("Failed to validate uid [%d]", ret);
1674                 return NOTIFICATION_ERROR_IO_ERROR;
1675         }
1676
1677         ret = notification_noti_get_all_count(type, &noti_count, param_uid);
1678         if (ret != NOTIFICATION_ERROR_NONE) {
1679                 ERR("Failed to get count [%d]", ret);
1680                 return ret;
1681         }
1682
1683         *reply_body = g_variant_new("(i)", noti_count);
1684         if (*reply_body == NULL) {
1685                 ERR("Failed to make reply_body");
1686                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1687         }
1688
1689         INFO("The numbers of all notification count is [%d]", noti_count);
1690         return ret;
1691 }
1692
1693 /* update_noti_setting */
1694 int notification_update_noti_setting(GVariant *parameters, GVariant **reply_body, uid_t uid)
1695 {
1696         int ret;
1697         char *pkgname = NULL;
1698         char *app_id = NULL;
1699         int allow_to_notify = 0;
1700         int do_not_disturb_except = 0;
1701         int visivility_class = 0;
1702         int pop_up_notification = 0;
1703         int lock_screen_content_level = 0;
1704         uid_t param_uid;
1705
1706         g_variant_get(parameters, "(&s&siiiiii)",
1707                         &pkgname,
1708                         &app_id,
1709                         &allow_to_notify,
1710                         &do_not_disturb_except,
1711                         &visivility_class,
1712                         &pop_up_notification,
1713                         &lock_screen_content_level,
1714                         &param_uid);
1715
1716         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
1717         if (ret != NOTIFICATION_ERROR_NONE)
1718                 return ret;
1719
1720         ret = notification_setting_db_update(pkgname, app_id, allow_to_notify, do_not_disturb_except, visivility_class,
1721                                              pop_up_notification, lock_screen_content_level, param_uid);
1722         if (ret != NOTIFICATION_ERROR_NONE) {
1723                 ERR("Failed to setting db update : %d", ret);
1724                 return ret;
1725         }
1726
1727         *reply_body = g_variant_new("()");
1728         if (*reply_body == NULL) {
1729                 ERR("Failed to make reply_body");
1730                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1731         }
1732
1733         INFO("package_name[%s] app_id[%s] allow_to_notify[%d] do_not_disturb_except[%d] visivility_class[%d] pop_up_notification[%d] lock_screen_content_level[%d]",
1734                         pkgname, app_id, allow_to_notify, do_not_disturb_except, visivility_class, pop_up_notification, lock_screen_content_level);
1735         return ret;
1736 }
1737
1738 static int _dnd_schedule_alarm_cb(alarm_id_t alarm_id, void *data)
1739 {
1740         int ret;
1741         int do_not_disturb;
1742         bool dnd_id_found = false;
1743         GVariant *body = NULL;
1744         GList *dnd_found_list = NULL;
1745         dnd_alarm_id_s *dnd_id_data = NULL;
1746         uid_t uid;
1747
1748         dnd_found_list = g_list_first(_dnd_alarm_id_list);
1749
1750         for (; dnd_found_list != NULL; dnd_found_list = dnd_found_list->next) {
1751                 dnd_id_data = dnd_found_list->data;
1752                 uid = dnd_id_data->uid;
1753
1754                 ret = noti_system_setting_get_do_not_disturb(&do_not_disturb, uid);
1755                 if (ret != NOTIFICATION_ERROR_NONE) {
1756                         ERR("get do not disturb failed");
1757                         return ret;
1758                 }
1759
1760                 if (alarm_id == dnd_id_data->dnd_start_id && !do_not_disturb) {
1761                         do_not_disturb = 1;
1762                         dnd_id_found = true;
1763                         break;
1764                 } else if (alarm_id == dnd_id_data->dnd_end_id && do_not_disturb) {
1765                         do_not_disturb = 0;
1766                         dnd_id_found = true;
1767                         break;
1768                 }
1769         }
1770
1771         if (dnd_id_found == false) {
1772                 ERR("notification wrong alarm [%d]", alarm_id);
1773                 return -1;
1774         }
1775
1776         notification_setting_db_update_do_not_disturb(do_not_disturb, uid);
1777
1778         body = g_variant_new("(ii)", do_not_disturb, uid);
1779
1780         ret = send_notify(body, "change_dnd_notify", &_monitoring_hash, PROVIDER_NOTI_INTERFACE_NAME, uid);
1781         g_variant_unref(body);
1782         if (ret != NOTIFICATION_ERROR_NONE) {
1783                 ERR("Failed to send notify [%d]", ret);
1784                 return ret;
1785         }
1786
1787         INFO("dnd[%d], uid[%d]", do_not_disturb, uid);
1788         return ret;
1789 }
1790
1791 static int _get_current_time(struct tm *date)
1792 {
1793         time_t now;
1794
1795         if (date == NULL) {
1796                 ERR("Invalid tm data");
1797                 return NOTIFICATION_ERROR_INVALID_PARAMETER;
1798         }
1799
1800         time(&now);
1801         localtime_r(&now, date);
1802
1803         return NOTIFICATION_ERROR_NONE;
1804 }
1805
1806 static int _noti_system_setting_set_alarm(int week_flag, int hour, int min, alarm_cb_t handler, alarm_id_t *dnd_schedule_alarm_id)
1807 {
1808         int err = NOTIFICATION_ERROR_NONE;
1809         struct tm struct_time;
1810         alarm_entry_t *alarm_info = NULL;
1811         alarm_date_t alarm_time;
1812         alarm_id_t alarm_id = -1;
1813
1814         err = alarmmgr_init("notification");
1815         if (err < 0) {
1816                 ERR("alarmmgr_init failed [%d]", err);
1817                 goto out;
1818         }
1819
1820         err = alarmmgr_set_cb(handler, NULL);
1821         if (err < 0) {
1822                 ERR("alarmmgr_set_cb failed [%d]", err);
1823                 goto out;
1824         }
1825
1826         err = _get_current_time(&struct_time);
1827         if (err != NOTIFICATION_ERROR_NONE) {
1828                 ERR("get_current_time failed [%d]", err);
1829                 goto out;
1830         }
1831
1832         alarm_info = alarmmgr_create_alarm();
1833         if (alarm_info == NULL) {
1834                 ERR("alarmmgr_create_alarm failed");
1835                 goto out;
1836         }
1837
1838         alarm_time.year = struct_time.tm_year + 1900;
1839         alarm_time.month = struct_time.tm_mon + 1;
1840         alarm_time.day = struct_time.tm_mday;
1841         alarm_time.hour = hour;
1842         alarm_time.min = min;
1843         alarm_time.sec = 0;
1844
1845         err = alarmmgr_set_time(alarm_info, alarm_time);
1846         if (err != ALARMMGR_RESULT_SUCCESS) {
1847                 ERR("alarmmgr_set_time failed [%d]", err);
1848                 goto out;
1849         }
1850
1851         if (week_flag) {
1852                 err = alarmmgr_set_repeat_mode(alarm_info, ALARM_REPEAT_MODE_WEEKLY, week_flag);
1853                 if (err != ALARMMGR_RESULT_SUCCESS) {
1854                         ERR("alarmmgr_set_repeat_mode failed [%d]", err);
1855                         goto out;
1856                 }
1857         }
1858
1859         err = alarmmgr_set_type(alarm_info, ALARM_TYPE_VOLATILE);
1860         if (err != ALARMMGR_RESULT_SUCCESS) {
1861                 ERR("alarmmgr_set_type failed [%d]", err);
1862                 goto out;
1863         }
1864
1865         err = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
1866         if (err != ALARMMGR_RESULT_SUCCESS) {
1867                 ERR("alarmmgr_add_alarm_with_localtime failed [%d]", err);
1868                 goto out;
1869         }
1870
1871         *dnd_schedule_alarm_id = alarm_id;
1872
1873 out:
1874         if (alarm_info)
1875                 alarmmgr_free_alarm(alarm_info);
1876
1877         DBG("alarm_id [%d]", alarm_id);
1878         return err;
1879 }
1880
1881 static gint _dnd_data_compare(gconstpointer a, gconstpointer b)
1882 {
1883         const dnd_alarm_id_s *data = NULL;
1884
1885         if (!a)
1886                 return -1;
1887         data = a;
1888         if (data->uid == GPOINTER_TO_UINT(b))
1889                 return 0;
1890
1891         return 1;
1892 }
1893
1894 static dnd_alarm_id_s *__malloc_dnd_alarm_id_s(uid_t uid, alarm_id_t start_alarm_id, alarm_id_t end_alarm_id)
1895 {
1896         dnd_alarm_id_s *dnd_id_data = NULL;
1897
1898         dnd_id_data = (dnd_alarm_id_s *)malloc(sizeof(dnd_alarm_id_s));
1899         if (dnd_id_data == NULL) {
1900                 ERR("Failed to alloc memory");
1901                 return NULL;
1902         }
1903
1904         dnd_id_data->uid = uid;
1905         dnd_id_data->dnd_start_id = start_alarm_id;
1906         dnd_id_data->dnd_end_id = end_alarm_id;
1907
1908         return dnd_id_data;
1909 }
1910
1911 static int _add_alarm(int dnd_schedule_day, int dnd_start_hour, int dnd_start_min, int dnd_end_hour, int dnd_end_min, uid_t uid)
1912 {
1913         int ret = NOTIFICATION_ERROR_NONE;
1914         GList *found_list = NULL;
1915         dnd_alarm_id_s *dnd_id_data = NULL;
1916         alarm_id_t dnd_schedule_start_alarm_id;
1917         alarm_id_t dnd_schedule_end_alarm_id;
1918
1919         ret = _noti_system_setting_set_alarm(dnd_schedule_day,
1920                                 dnd_start_hour, dnd_start_min,
1921                                 _dnd_schedule_alarm_cb,
1922                                 &dnd_schedule_start_alarm_id);
1923         if (ret != NOTIFICATION_ERROR_NONE) {
1924                 ERR("Failed to set start alarm [%d]", ret);
1925                 return ret;
1926         }
1927
1928         if (dnd_end_hour < dnd_start_hour ||
1929             (dnd_end_hour == dnd_start_hour && dnd_end_min <= dnd_start_min)) {
1930                 dnd_schedule_day = (dnd_schedule_day << 1);
1931                 if (dnd_schedule_day & (DND_SCHEDULE_WEEK_FLAG_SATURDAY << 1))
1932                         dnd_schedule_day = (dnd_schedule_day & DND_SCHEDULE_WEEK_FLAG_ALL)
1933                                         | DND_SCHEDULE_WEEK_FLAG_SUNDAY;
1934         }
1935
1936         ret = _noti_system_setting_set_alarm(dnd_schedule_day,
1937                                 dnd_end_hour, dnd_end_min,
1938                                 _dnd_schedule_alarm_cb,
1939                                 &dnd_schedule_end_alarm_id);
1940         if (ret != NOTIFICATION_ERROR_NONE) {
1941                 ERR("Failed to set end alarm [%d]", ret);
1942                 return ret;
1943         }
1944
1945         if (_dnd_alarm_id_list == NULL) {
1946                 dnd_id_data = __malloc_dnd_alarm_id_s(uid, dnd_schedule_start_alarm_id, dnd_schedule_end_alarm_id);
1947                 if (!dnd_id_data)
1948                         return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1949                 _dnd_alarm_id_list = g_list_append(_dnd_alarm_id_list, dnd_id_data);
1950         } else {
1951                 found_list = g_list_find_custom(g_list_first(_dnd_alarm_id_list), GUINT_TO_POINTER(uid),
1952                                                 (GCompareFunc)_dnd_data_compare);
1953                 if (found_list) {
1954                         dnd_id_data = g_list_nth_data(found_list, 0);
1955                         if (dnd_id_data->dnd_start_id) {
1956                                 alarmmgr_remove_alarm(dnd_id_data->dnd_start_id);
1957                                 dnd_id_data->dnd_start_id = dnd_schedule_start_alarm_id;
1958                         }
1959                         if (dnd_id_data->dnd_end_id) {
1960                                 alarmmgr_remove_alarm(dnd_id_data->dnd_end_id);
1961                                 dnd_id_data->dnd_end_id = dnd_schedule_end_alarm_id;
1962                         }
1963                 } else {
1964                         dnd_id_data = __malloc_dnd_alarm_id_s(uid, dnd_schedule_start_alarm_id, dnd_schedule_end_alarm_id);
1965                         if (!dnd_id_data)
1966                                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
1967                         _dnd_alarm_id_list = g_list_append(_dnd_alarm_id_list, dnd_id_data);
1968                 }
1969         }
1970
1971         return ret;
1972 }
1973
1974 static void _delete_alarm(uid_t uid)
1975 {
1976         GList *found_list = NULL;
1977         dnd_alarm_id_s *dnd_id_data = NULL;
1978
1979         if (_dnd_alarm_id_list == NULL)
1980                 return;
1981
1982         _dnd_alarm_id_list = g_list_first(_dnd_alarm_id_list);
1983         found_list = g_list_find_custom(_dnd_alarm_id_list, GUINT_TO_POINTER(uid),
1984                                         (GCompareFunc)_dnd_data_compare);
1985
1986         if (found_list == NULL)
1987                 return;
1988
1989         dnd_id_data = g_list_nth_data(found_list, 0);
1990
1991         if (dnd_id_data->dnd_start_id)
1992                 alarmmgr_remove_alarm(dnd_id_data->dnd_start_id);
1993         if (dnd_id_data->dnd_end_id)
1994                 alarmmgr_remove_alarm(dnd_id_data->dnd_end_id);
1995
1996         _dnd_alarm_id_list = g_list_remove(g_list_first(_dnd_alarm_id_list), dnd_id_data);
1997         free(dnd_id_data);
1998 }
1999
2000 /* update_noti_sys_setting */
2001 int notification_update_noti_sys_setting(GVariant *parameters, GVariant **reply_body, uid_t uid)
2002 {
2003         int ret;
2004         int pre_do_not_disturb = 0;
2005         int do_not_disturb = 0;
2006         int visivility_class = 0;
2007         int dnd_schedule_enabled = 0;
2008         int dnd_schedule_day = 0;
2009         int dnd_start_hour = 0;
2010         int dnd_start_min = 0;
2011         int dnd_end_hour = 0;
2012         int dnd_end_min = 0;
2013         int lock_screen_level = 0;
2014         uid_t param_uid;
2015         GVariant *body = NULL;
2016
2017         g_variant_get(parameters, "(iiiiiiiiii)",
2018                                 &do_not_disturb,
2019                                 &visivility_class,
2020                                 &dnd_schedule_enabled,
2021                                 &dnd_schedule_day,
2022                                 &dnd_start_hour,
2023                                 &dnd_start_min,
2024                                 &dnd_end_hour,
2025                                 &dnd_end_min,
2026                                 &lock_screen_level,
2027                                 &param_uid);
2028
2029         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
2030         if (ret != NOTIFICATION_ERROR_NONE)
2031                 return ret;
2032
2033         ret = noti_system_setting_get_do_not_disturb(&pre_do_not_disturb, param_uid);
2034         if (ret != NOTIFICATION_ERROR_NONE) {
2035                 ERR("Failed to get do not disturb");
2036                 return ret;
2037         }
2038
2039         ret = notification_setting_db_update_system_setting(do_not_disturb,
2040                                 visivility_class,
2041                                 dnd_schedule_enabled,
2042                                 dnd_schedule_day,
2043                                 dnd_start_hour,
2044                                 dnd_start_min,
2045                                 dnd_end_hour,
2046                                 dnd_end_min,
2047                                 lock_screen_level,
2048                                 param_uid);
2049         if (ret != NOTIFICATION_ERROR_NONE) {
2050                 ERR("Failed to setting db update system setting : %d", ret);
2051                 return ret;
2052         }
2053
2054         if (pre_do_not_disturb != do_not_disturb) {
2055                 body = g_variant_new("(ii)", do_not_disturb, param_uid);
2056                 ret = send_notify(body, "change_dnd_notify", &_monitoring_hash, PROVIDER_NOTI_INTERFACE_NAME, param_uid);
2057                 g_variant_unref(body);
2058         }
2059
2060         *reply_body = g_variant_new("()");
2061         if (*reply_body == NULL) {
2062                 ERR("Failed to make reply_body");
2063                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
2064         }
2065
2066         if (dnd_schedule_enabled) {
2067                 ret = _add_alarm(dnd_schedule_day, dnd_start_hour, dnd_start_min,
2068                                 dnd_end_hour, dnd_end_min, param_uid);
2069                 if (ret != NOTIFICATION_ERROR_NONE)
2070                         ERR("Failed to add alarm for dnd_schedule");
2071         } else {
2072                 _delete_alarm(param_uid);
2073         }
2074
2075         INFO("do_not_disturb [%d] visivility_class [%d] set_schedule [%d] lock_screen_level [%d]",
2076                         do_not_disturb, visivility_class, dnd_schedule_enabled, lock_screen_level);
2077         return ret;
2078 }
2079
2080 int notification_add_noti_template(GVariant *parameters, GVariant **reply_body, uid_t uid)
2081 {
2082         notification_h noti;
2083         int ret;
2084         GVariant *body = NULL;
2085         GVariant *coupled_body = NULL;
2086         char *template_name = NULL;
2087         int count = 0;
2088
2089         noti = notification_create(NOTIFICATION_TYPE_NOTI);
2090         if (noti != NULL) {
2091                 g_variant_get(parameters, "(v&s)", &coupled_body, &template_name);
2092                 g_variant_get(coupled_body, "(v)", &body);
2093
2094                 ret = notification_ipc_make_noti_from_gvariant(noti, body);
2095                 g_variant_unref(coupled_body);
2096                 g_variant_unref(body);
2097                 if (ret != NOTIFICATION_ERROR_NONE) {
2098                         ERR("Failed to make a notification [%d]", ret);
2099                         goto out;
2100                 }
2101
2102                 ret = notification_noti_check_count_for_template(noti, &count);
2103                 if (count >= NOTI_TEMPLATE_LIMIT) {
2104                         ERR("Exceed limit value that is saved tamplate  [%d]", ret);
2105                         ret = NOTIFICATION_ERROR_MAX_EXCEEDED;
2106                         goto out;
2107                 }
2108
2109                 ret = notification_noti_add_template(noti, template_name);
2110                 if (ret != NOTIFICATION_ERROR_NONE)
2111                         ERR("Failed to add a notification [%d]", ret);
2112         } else {
2113                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2114         }
2115
2116 out:
2117         if (noti)
2118                 notification_free(noti);
2119
2120         return ret;
2121 }
2122
2123 int notification_get_noti_template(GVariant *parameters, GVariant **reply_body, pid_t pid, uid_t uid)
2124 {
2125         int ret;
2126         char app_id[BUF_LEN] = {0, };
2127         char *template_name = NULL;
2128         notification_h noti;
2129
2130         noti = notification_create(NOTIFICATION_TYPE_NOTI);
2131         if (noti != NULL) {
2132                 g_variant_get(parameters, "(&s)", &template_name);
2133                 INFO("template name[%s]", template_name);
2134
2135                 ret = aul_app_get_appid_bypid_for_uid(pid, app_id, sizeof(app_id), uid);
2136                 if (ret != AUL_R_OK) {
2137                         ERR("Failed to get app_id [%d]", ret);
2138                         ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
2139                         goto out;
2140                 }
2141
2142                 ret = notification_noti_get_package_template(noti, app_id, template_name);
2143                 if (ret != NOTIFICATION_ERROR_NONE) {
2144                         ERR("Failed to get template [%d]", ret);
2145                         goto out;
2146                 }
2147
2148                 *reply_body = notification_ipc_make_gvariant_from_noti(noti, false);
2149                 if (*reply_body == NULL) {
2150                         ERR("Failed to make reply_body");
2151                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2152                 }
2153         } else {
2154                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2155         }
2156
2157 out:
2158         if (noti)
2159                 notification_free(noti);
2160
2161         return ret;
2162 }
2163
2164 int notification_get_noti_package_template(GVariant *parameters, GVariant **reply_body, uid_t uid)
2165 {
2166         int ret;
2167         char *app_id = NULL;
2168         char *template_name = NULL;
2169         notification_h noti;
2170
2171         noti = notification_create(NOTIFICATION_TYPE_NOTI);
2172         if (noti != NULL) {
2173                 g_variant_get(parameters, "(&s&s)", &app_id, &template_name);
2174                 INFO("app_id[%s] template name[%s]", app_id, template_name);
2175                 ret = notification_noti_get_package_template(noti, app_id, template_name);
2176                 if (ret != NOTIFICATION_ERROR_NONE) {
2177                         ERR("Failed to get template [%d]", ret);
2178                         goto out;
2179                 }
2180
2181                 *reply_body = notification_ipc_make_gvariant_from_noti(noti, false);
2182                 if (*reply_body == NULL) {
2183                         ERR("Failed to make reply_body");
2184                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2185                 }
2186         } else {
2187                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2188         }
2189
2190 out:
2191         if (noti)
2192                 notification_free(noti);
2193
2194         return ret;
2195 }
2196
2197 int notification_get_block_state(GVariant *parameters, GVariant **reply_body, uid_t uid)
2198 {
2199         int ret;
2200         int dnd;
2201         int dnd_except;
2202         int allow_to_notify;
2203         char *app_id;
2204         uid_t param_uid;
2205         GVariant *body = NULL;
2206
2207         g_variant_get(parameters, "(&si)", &app_id, &param_uid);
2208
2209         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
2210         if (ret != NOTIFICATION_ERROR_NONE) {
2211                 ERR("_validate_uid fail [%d]", ret);
2212                 return NOTIFICATION_ERROR_IO_ERROR;
2213         }
2214
2215         ret = notification_get_dnd_and_allow_to_notify(app_id, &dnd, &dnd_except, &allow_to_notify, param_uid);
2216         INFO("app_id[%s] dnd[%d] dnd_except[%d] allow_to_notify[%d]",
2217                 app_id, dnd, dnd_except, allow_to_notify);
2218         if (ret != NOTIFICATION_ERROR_NONE) {
2219                 ERR("Failed to get_dnd_and_allow_to_notify [%d]", ret);
2220                 return ret;
2221         }
2222
2223         body = g_variant_new("(iii)", dnd, dnd_except, allow_to_notify);
2224         *reply_body = g_variant_new("(v)", body);
2225
2226         if (*reply_body == NULL) {
2227                 ERR("Failed to make reply_body");
2228                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
2229         }
2230
2231         return ret;
2232 }
2233 int notification_load_dnd_allow_exception(GVariant *parameters, GVariant **reply_body, uid_t uid)
2234 {
2235         int ret;
2236         int count = 0;
2237         int i;
2238         uid_t param_uid;
2239         GVariant *body = NULL;
2240         GVariantBuilder *builder;
2241         dnd_allow_exception_h dnd_allow_exception = NULL;
2242         dnd_allow_exception_h temp;
2243
2244         g_variant_get(parameters, "(i)", &param_uid);
2245
2246         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
2247         if (ret != NOTIFICATION_ERROR_NONE)
2248                 return ret;
2249
2250         ret = notification_system_setting_load_dnd_allow_exception(&dnd_allow_exception, &count, param_uid);
2251         if (ret != NOTIFICATION_ERROR_NONE) {
2252                 ERR("Failed to load dnd_allow_exception [%d]", ret);
2253                 return ret;
2254         }
2255
2256         builder = g_variant_builder_new(G_VARIANT_TYPE("a(v)"));
2257
2258         if (dnd_allow_exception) {
2259                 for (i = 0; i < count; i++) {
2260                         temp = dnd_allow_exception + i;
2261                         body = notification_ipc_make_gvariant_from_dnd_allow_exception(temp);
2262                         g_variant_builder_add(builder, "(v)", body);
2263                 }
2264                 free(dnd_allow_exception);
2265         }
2266
2267         *reply_body = g_variant_new("(ia(v))", count, builder);
2268         g_variant_builder_unref(builder);
2269
2270         if (*reply_body == NULL) {
2271                 ERR("Failed to make reply_body");
2272                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
2273         }
2274
2275         return ret;
2276 }
2277
2278 int notification_update_dnd_allow_exception(GVariant *parameters, GVariant **reply_body, uid_t uid)
2279 {
2280         int ret;
2281         int type;
2282         int value;
2283         uid_t param_uid;
2284
2285         g_variant_get(parameters, "(iii)", &type, &value, &param_uid);
2286
2287         ret = _validate_and_set_param_uid_with_uid(uid, &param_uid);
2288         if (ret != NOTIFICATION_ERROR_NONE)
2289                 return ret;
2290
2291         ret = notification_system_setting_update_dnd_allow_exception(type,
2292                         value,
2293                         param_uid);
2294         if (ret != NOTIFICATION_ERROR_NONE) {
2295                 ERR("Failed to update dnd_allow_exception [%d]", ret);
2296                 return ret;
2297         }
2298
2299         *reply_body = g_variant_new("()");
2300         if (*reply_body == NULL) {
2301                 ERR("Failed to make reply_body");
2302                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
2303         }
2304
2305         return ret;
2306 }
2307
2308 static event_sender_info_s *__find_sender_info_by_priv_id(int priv_id)
2309 {
2310         event_sender_info_s *event_info;
2311         GList *find_list;
2312
2313         if (__event_list == NULL)
2314                 return NULL;
2315
2316         __event_list = g_list_first(__event_list);
2317         find_list = g_list_find_custom(__event_list, GINT_TO_POINTER(priv_id),
2318                                        (GCompareFunc)__priv_id_compare);
2319
2320         if (find_list)
2321                 event_info = g_list_nth_data(find_list, 0);
2322         else
2323                 return NULL;
2324
2325         return event_info;
2326 }
2327
2328 int notification_send_noti_event(GVariant *parameters, GVariant **reply_body)
2329 {
2330         int ret;
2331         int event_type;
2332         int priv_id;
2333         event_sender_info_s *info;
2334         GVariant *coupled_body = NULL;
2335         GVariant *body = NULL;
2336         notification_h noti;
2337
2338         noti = notification_create(NOTIFICATION_TYPE_NOTI);
2339         if (noti != NULL) {
2340                 g_variant_get(parameters, "(vi)", &coupled_body, &event_type);
2341                 g_variant_get(coupled_body, "(v)", &body);
2342
2343                 ret = notification_ipc_make_noti_from_gvariant(noti, body);
2344                 g_variant_unref(coupled_body);
2345                 g_variant_unref(body);
2346
2347                 if (ret != NOTIFICATION_ERROR_NONE) {
2348                         ERR("Failed to make a notification from gvariant");
2349                         goto out;
2350                 }
2351
2352                 ret = notification_get_id(noti, NULL, &priv_id);
2353                 if (ret != NOTIFICATION_ERROR_NONE)
2354                         goto out;
2355
2356                 info = __find_sender_info_by_priv_id(priv_id);
2357                 if (info == NULL || info->busname == NULL) {
2358                         ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
2359                         goto out;
2360                 }
2361
2362                 if (!info->watcher_id) {
2363                         if (!is_existed_busname(info->busname)) {
2364                                 __event_list = g_list_remove(g_list_first(__event_list), info);
2365                                 __free_event_info(info);
2366                                 ret = NOTIFICATION_ERROR_IO_ERROR;
2367                                 goto out;
2368                         } else {
2369                                 info->watcher_id = __insert_sender_watcher_id(info);
2370                         }
2371                 }
2372
2373                 ret = send_event_notify_by_busname(parameters, "send_event", info->busname, PROVIDER_NOTI_EVENT_INTERFACE_NAME);
2374                 if (ret != NOTIFICATION_ERROR_NONE) {
2375                         ERR("Failed to send event [%d]", ret);
2376                         goto out;
2377                 }
2378
2379                 *reply_body = g_variant_new("()");
2380                 if (*reply_body == NULL) {
2381                         ERR("Failed to make reply body");
2382                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2383                 }
2384         } else {
2385                 ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2386         }
2387
2388 out:
2389         if (noti)
2390                 notification_free(noti);
2391
2392         return ret;
2393 }
2394
2395 int notification_send_noti_event_by_priv_id(GVariant *parameters, GVariant **reply_body)
2396 {
2397         int ret;
2398         int event_type;
2399         int priv_id;
2400         bool event_flag = false;
2401         notification_h noti;
2402         GVariant *body = NULL;
2403         event_sender_info_s *info;
2404
2405         noti = notification_create(NOTIFICATION_TYPE_NOTI);
2406         if (noti != NULL) {
2407                 g_variant_get(parameters, "(ii)", &priv_id, &event_type);
2408
2409                 ret = notification_noti_get_by_priv_id(noti, priv_id);
2410                 if (ret != NOTIFICATION_ERROR_NONE) {
2411                         ERR("Failed to get notification by priv id [%d]", ret);
2412                         goto out;
2413                 }
2414
2415                 ret = notification_get_event_flag(noti, &event_flag);
2416                 if (ret != NOTIFICATION_ERROR_NONE || event_flag == false) {
2417                         ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
2418                         goto out;
2419                 }
2420
2421                 info = __find_sender_info_by_priv_id(priv_id);
2422                 if (info == NULL || info->busname == NULL) {
2423                         ret = NOTIFICATION_ERROR_INVALID_PARAMETER;
2424                         ERR("No sender info by priv_id[%d]", priv_id);
2425                         goto out;
2426                 }
2427
2428                 if (!info->watcher_id) {
2429                         if (!is_existed_busname(info->busname)) {
2430                                 __event_list = g_list_remove(g_list_first(__event_list), info);
2431                                 __free_event_info(info);
2432                                 ret = NOTIFICATION_ERROR_IO_ERROR;
2433                                 goto out;
2434                         } else {
2435                                 info->watcher_id = __insert_sender_watcher_id(info);
2436                         }
2437                 }
2438
2439                 body = notification_ipc_make_gvariant_from_noti(noti, false);
2440                 if (body == NULL) {
2441                         ERR("Can't make gvariant to noti");
2442                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2443                         goto out;
2444                 }
2445
2446                 ret = send_event_notify_by_busname(g_variant_new("(vi)", body, event_type), "send_event", info->busname, PROVIDER_NOTI_EVENT_INTERFACE_NAME);
2447                 *reply_body = g_variant_new("()");
2448                 if (*reply_body == NULL) {
2449                         ERR("Failed to make reply body");
2450                         ret = NOTIFICATION_ERROR_OUT_OF_MEMORY;
2451                 }
2452         } else {
2453                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
2454         }
2455
2456 out:
2457         if (noti)
2458                 notification_free(noti);
2459
2460         return ret;
2461 }
2462
2463 int notification_check_event_receiver(GVariant *parameters, GVariant **reply_body)
2464 {
2465         int priv_id;
2466         bool available = false;
2467         GList *find_list = NULL;
2468         event_sender_info_s *info = NULL;
2469
2470         g_variant_get(parameters, "(i)", &priv_id);
2471         INFO("priv_id[%d]", priv_id);
2472
2473         __event_list = g_list_first(__event_list);
2474         find_list = g_list_find_custom(__event_list, GINT_TO_POINTER(priv_id),
2475                                        (GCompareFunc)__priv_id_compare);
2476         if (find_list) {
2477                 info = g_list_nth_data(find_list, 0);
2478                 if (!info->watcher_id) {
2479                         if (!is_existed_busname(info->busname)) {
2480                                 __event_list = g_list_remove(g_list_first(__event_list), info);
2481                                 __free_event_info(info);
2482                         } else {
2483                                 available = true;
2484                                 info->watcher_id = __insert_sender_watcher_id(info);
2485                         }
2486                 } else {
2487                         available = true;
2488                 }
2489         }
2490
2491         *reply_body = g_variant_new("(i)", (int)available);
2492         if (*reply_body == NULL) {
2493                 ERR("Failed to make gvariant to noti");
2494                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
2495         }
2496
2497         INFO("Receiver available[%d]", available);
2498         return NOTIFICATION_ERROR_NONE;
2499 }
2500
2501 int notification_reset_event_receiver(GVariant *parameters, GVariant **reply_body, const char *sender)
2502 {
2503         int priv_id;
2504
2505         g_variant_get(parameters, "(i)", &priv_id);
2506         INFO("priv_id[%d]", priv_id);
2507
2508         __add_sender_info(priv_id, sender);
2509
2510         *reply_body = g_variant_new("()");
2511         if (*reply_body == NULL) {
2512                 ERR("Failed to make gvariant to noti");
2513                 return NOTIFICATION_ERROR_OUT_OF_MEMORY;
2514         }
2515
2516         return NOTIFICATION_ERROR_NONE;
2517 }
2518
2519 HAPI int notification_delete_noti_by_app_id(const char *app_id, uid_t uid)
2520 {
2521         GVariant *deleted_noti_list;
2522         GVariantBuilder *builder;
2523         int num_deleted = 0;
2524         int *list_deleted = NULL;
2525         int ret;
2526         int i;
2527
2528         ret = notification_noti_delete_all(NOTIFICATION_TYPE_NONE, app_id, &num_deleted, &list_deleted, uid);
2529         if (ret != NOTIFICATION_ERROR_NONE) {
2530                 ERR("Failed to delete notifications [%d]", ret);
2531                 goto out;
2532         }
2533
2534         if (num_deleted > 0) {
2535                 builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)"));
2536
2537                 for (i = 0; i < num_deleted; i++)
2538                         g_variant_builder_add(builder, "(i)", *(list_deleted + i));
2539
2540                 deleted_noti_list = g_variant_new("(a(i)ii)", builder, num_deleted, uid);
2541                 ret = send_notify(deleted_noti_list, "delete_multiple_notify", &_monitoring_hash, PROVIDER_NOTI_INTERFACE_NAME, uid);
2542                 g_variant_builder_unref(builder);
2543                 g_variant_unref(deleted_noti_list);
2544                 if (ret != NOTIFICATION_ERROR_NONE) {
2545                         ERR("Failed to send notify [%d]", ret);
2546                         goto out;
2547                 }
2548
2549                 for (i = 0; i < num_deleted; i++) {
2550                         ret = __delete_sender_info(*(list_deleted + i));
2551                         if (ret != NOTIFICATION_ERROR_NONE)
2552                                 goto out;
2553                 }
2554         }
2555 out:
2556         if (list_deleted != NULL)
2557                 free(list_deleted);
2558         return ret;
2559 }
2560
2561 static int _check_dnd_schedule(uid_t uid)
2562 {
2563         int ret;
2564         notification_system_setting_h setting = NULL;
2565         bool dnd_schedule_enabled = false;
2566         int dnd_schedule_day = 0;
2567         int dnd_start_hour = 0;
2568         int dnd_start_min = 0;
2569         int dnd_end_hour = 0;
2570         int dnd_end_min = 0;
2571
2572         ret = noti_system_setting_load_system_setting(&setting, uid);
2573         if (ret != NOTIFICATION_ERROR_NONE) {
2574                 ERR("noti_system_setting_load_system_setting fail [%d]", ret);
2575                 return ret;
2576         }
2577
2578         ret = notification_system_setting_dnd_schedule_get_enabled(setting,
2579                                 &dnd_schedule_enabled);
2580         if (ret != NOTIFICATION_ERROR_NONE) {
2581                 ERR("system_setting_dnd_schedule_get_enabled fail [%d]", ret);
2582                 goto out;
2583         }
2584
2585         if (dnd_schedule_enabled) {
2586                 ret = notification_system_setting_dnd_schedule_get_day(setting,
2587                                 &dnd_schedule_day);
2588                 if (ret != NOTIFICATION_ERROR_NONE) {
2589                         ERR("system_setting_dnd_schedule_get_day fail [%d]", ret);
2590                         goto out;
2591                 }
2592
2593                 ret = notification_system_setting_dnd_schedule_get_start_time(setting,
2594                                 &dnd_start_hour, &dnd_start_min);
2595                 if (ret != NOTIFICATION_ERROR_NONE) {
2596                         ERR("system_setting_dnd_schedule_get_start_time fail [%d]", ret);
2597                         goto out;
2598                 }
2599
2600                 ret = notification_system_setting_dnd_schedule_get_end_time(setting,
2601                                 &dnd_end_hour, &dnd_end_min);
2602                 if (ret != NOTIFICATION_ERROR_NONE) {
2603                         ERR("system_setting_dnd_schedule_get_end_time fail [%d]", ret);
2604                         goto out;
2605                 }
2606
2607                 _add_alarm(dnd_schedule_day, dnd_start_hour, dnd_start_min, dnd_end_hour, dnd_end_min, uid);
2608         }
2609
2610 out:
2611         notification_system_setting_free_system_setting(setting);
2612
2613         return ret;
2614 }
2615
2616 static gboolean __refresh_setting_table(gpointer data)
2617 {
2618         notification_setting_refresh_setting_table(
2619                 tzplatform_getuid(TZ_SYS_DEFAULT_USER));
2620         return G_SOURCE_REMOVE;
2621 }
2622
2623 /*!
2624  * MAIN THREAD
2625  * Do not try to do any other operation in these functions
2626  */
2627 HAPI int notification_service_init(void)
2628 {
2629         int ret, i;
2630         int count = 0;
2631         uid_t *uids = NULL;
2632
2633         _monitoring_hash = g_hash_table_new(g_direct_hash, g_direct_equal);
2634         ret = notification_db_init();
2635         if (ret != NOTIFICATION_ERROR_NONE) {
2636                 ERR("Failed to init DB [%d]", ret);
2637                 return ret;
2638         }
2639
2640         ret = notification_register_dbus_interface();
2641         if (ret != SERVICE_COMMON_ERROR_NONE) {
2642                 ERR("Failed to register dbus interface [%d]", ret);
2643                 return NOTIFICATION_ERROR_IO_ERROR;
2644         }
2645
2646         notification_init_default_viewer();
2647         notification_noti_init_data();
2648         notification_system_setting_init_system_setting_table(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
2649
2650         ret = notification_system_setting_get_dnd_schedule_enabled_uid(&uids, &count);
2651         if (ret == NOTIFICATION_ERROR_NONE && count > 0) {
2652                 for (i = 0; i < count; i++)
2653                         _check_dnd_schedule(uids[i]);
2654         }
2655         if (uids)
2656                 free(uids);
2657
2658         g_idle_add(__refresh_setting_table, NULL);
2659
2660         INFO("Successfully initialized");
2661         return NOTIFICATION_ERROR_NONE;
2662 }
2663
2664 HAPI int notification_service_fini(void)
2665 {
2666         pkgmgr_fini();
2667         DBG("Successfully Finalized");
2668         return NOTIFICATION_ERROR_NONE;
2669 }
2670
2671 /* End of a file */