Add method to support do not disturb app 91/318091/7
authorSukhyungKang <shine.kang@samsung.com>
Tue, 24 Sep 2024 10:42:24 +0000 (19:42 +0900)
committerSukhyungKang <shine.kang@samsung.com>
Mon, 30 Sep 2024 06:32:24 +0000 (15:32 +0900)
- during the do not disturb app (dnd app) is running, notification viewer is not launched.
and then if dnd app is terminated, notification viewer is launched.

Change-Id: I513b3dd6d7d0fdd8b362ab4fea3c568c194406c2
Signed-off-by: SukhyungKang <shine.kang@samsung.com>
include/notification_service.h
src/notification_service.c

index fb52119ffb9d23884f384ea71676ce53c4213c51..0683e71daf705f2238c48aca2dcfd3be7daa2bc6 100755 (executable)
@@ -57,6 +57,8 @@ int notification_check_event_receiver(GVariant *parameters, GVariant **reply_bod
 int notification_reset_event_receiver(GVariant *parameters, GVariant **reply_body, const char *sender);
 int notification_register_dbus_interface();
 int notification_delete_noti_by_app_id(const char *app_id, uid_t uid);
+int notification_register_dnd_app(GVariant *parameters, GVariant **reply_body,
+               const char *sender, pid_t pid, uid_t uid);
 
 #ifdef __cplusplus
 }
index 5f5bd3bdd8e4e31fd5f7d0c109079829b41a22bb..847fc6cbe51103ab2288aa70cdba891abffcbb54 100644 (file)
@@ -64,9 +64,28 @@ typedef struct _event_sender_info {
        guint watcher_id;
 } event_sender_info_s;
 
+static GList *__dnd_app_list;
+
+typedef struct _dnd_app_info {
+       pid_t pid;
+       char *busname;
+       guint watcher_id;
+} dnd_app_info_s;
+
+typedef struct _disturb_noti_info {
+       int priv_id;
+       notification_op_type_e status;
+} disturb_noti_info_s;
+
+static GList *__disturb_noti_list;
+
 static int _update_noti(GVariant **reply_body, notification_h noti, uid_t uid);
 static int _delete_noti(const char *app_id, int priv_id, uid_t uid);
 
+static bool _is_dnd_app_exist();
+static void __delete_dnd_app_info(pid_t pid);
+static dnd_app_info_s *__find_dnd_app_info_by_pid(pid_t pid);
+
 /*!
  * SERVICE HANDLER
  */
@@ -194,6 +213,8 @@ static void _noti_dbus_method_call_handler(GDBusConnection *conn,
                ret = notification_reset_event_receiver(parameters, &reply_body, sender);
        } else if (g_strcmp0(method_name, "del_noti_by_display_applist") == 0) {
                ret = notification_del_noti_by_display_applist(parameters, &reply_body, uid);
+       } else if (g_strcmp0(method_name, "register_dnd_app") == 0) {
+               ret = notification_register_dnd_app(parameters, &reply_body, sender, pid, uid);
        }
 
        if (ret == NOTIFICATION_ERROR_NONE) {
@@ -402,6 +423,11 @@ int notification_register_dbus_interface(void)
 
                        "        <method name='post_toast'>"
                        "        </method>"
+
+                       "        <method name='register_dnd_app'>"
+                       "          <arg type='i' name='pid' direction='in'/>"
+                       "          <arg type='i' name='uid' direction='in'/>"
+                       "        </method>"
                        "  </interface>"
                        "  </node>";
 
@@ -466,6 +492,159 @@ static int __check_limit(notification_h noti, uid_t uid)
        return ret;
 }
 
+/* for dnd app */
+static gint __disturb_noti_compare(gconstpointer a, gconstpointer b)
+{
+       disturb_noti_info_s *info = NULL;
+
+       if (!a)
+               return -1;
+
+       info = (disturb_noti_info_s *)a;
+
+       if (info->priv_id == GPOINTER_TO_INT(b))
+               return 0;
+
+       return 1;
+}
+
+static void __delete_disturb_noti_info(int priv_id)
+{
+       disturb_noti_info_s *info;
+       GList *delete_list = NULL;
+
+       WARN("delete disturb noti info : %d", priv_id);
+
+       if (__disturb_noti_list != NULL) {
+               __disturb_noti_list = g_list_first(__disturb_noti_list);
+               delete_list = g_list_find_custom(__disturb_noti_list, GINT_TO_POINTER(priv_id),
+                                                (GCompareFunc)__disturb_noti_compare);
+               if (delete_list != NULL) {
+                       info = (disturb_noti_info_s *)delete_list->data;
+
+                       WARN("delete from disturb list id : %d, status : %d", info->priv_id, info->status);
+
+                       __disturb_noti_list = g_list_remove(g_list_first(__disturb_noti_list), info);
+                       free(info);
+               }
+               WARN("disturb noti info deleted, len : %d", g_list_length(__disturb_noti_list));
+       }
+}
+
+static void __add_disturb_noti_info(int priv_id, int status)
+{
+       disturb_noti_info_s *noti_info;
+
+       WARN("add disturb noti list, id : %d, status : %d", priv_id, status);
+
+       noti_info = (disturb_noti_info_s *)malloc(sizeof(disturb_noti_info_s));
+       if (noti_info == NULL) {
+               ERR("malloc failed");
+               return;
+       }
+
+       noti_info->priv_id = priv_id;
+       noti_info->status = status;
+
+       if (status == NOTIFICATION_OP_UPDATE)
+               __delete_disturb_noti_info(priv_id);
+
+       __disturb_noti_list = g_list_append(__disturb_noti_list, noti_info);
+}
+
+void _aul_app_dead_event_cb_v2(int pid, int status, void* user_data)
+{
+       int ret;
+       dnd_app_info_s *info;
+       disturb_noti_info_s *noti_info;
+       int latest_priv_id = NOTIFICATION_PRIV_ID_NONE;
+       int latest_status = NOTIFICATION_OP_NONE;
+
+       WARN("add dead, pid : %d, status : %d", pid, status);
+
+       info = __find_dnd_app_info_by_pid(pid);
+       if (info == NULL || info->busname == NULL) {
+               WARN("not dnd app");
+               return;
+       }
+
+       __delete_dnd_app_info(pid);
+
+       if (__disturb_noti_list != NULL && g_list_length(__disturb_noti_list) > 0) {
+               noti_info = (disturb_noti_info_s *)g_list_last(__disturb_noti_list)->data;
+               latest_priv_id = noti_info->priv_id;
+               latest_status = noti_info->status;
+       }
+
+       if (!_is_dnd_app_exist() && latest_priv_id > NOTIFICATION_PRIV_ID_NONE) {
+               /* uid not used*/
+               WARN("launch viewer");
+               ret = notification_launch_default_viewer(latest_priv_id, latest_status, 0);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       ERR("@Failed to launch default viewer from dead callback [%d]", ret);
+
+               g_list_free_full(__disturb_noti_list, free);
+               __disturb_noti_list = NULL;
+       } else {
+               WARN("viewer not launched");
+       }
+}
+
+int _notification_launch_viewer(notification_h noti, int priv_id,
+               notification_op_type_e status, uid_t uid)
+{
+       int ret;
+       bool pairing = false;
+       GVariant *body = NULL;
+       dnd_app_info_s *info = NULL;
+
+       WARN("launch noti viewer : [%d]", priv_id);
+
+       if (_is_dnd_app_exist()) {
+               WARN("dnd app exist, viewer does not launch");
+
+               if (status == NOTIFICATION_OP_INSERT || status == NOTIFICATION_OP_UPDATE)
+                       __add_disturb_noti_info(priv_id, status);
+
+               /* pairing */
+               if (noti == NULL) {
+                       ERR("notification not exist");
+                       return NOTIFICATION_ERROR_INVALID_PARAMETER;
+               }
+
+               ret = notification_get_pairing_type(noti, &pairing);
+               if (ret != NOTIFICATION_ERROR_NONE) {
+                       ERR("Failed to get pairing : %d", ret);
+                       return ret;
+               }
+
+               if (pairing) {
+                       WARN("dnd app exist, pairing type. exit dnd apps");
+                       /* call all disturb callback */
+                       __dnd_app_list = g_list_first(__dnd_app_list);
+                       for (GList *iter = __dnd_app_list; iter != NULL; iter = iter->next) {
+                               info = iter->data;
+                               WARN("disturb app : %s", info->busname);
+
+                               body = g_variant_new("()");
+                               ret = send_event_notify_by_busname(body, "disturb_app", info->busname,
+                                               PROVIDER_NOTI_EVENT_INTERFACE_NAME);
+                               g_variant_unref(body);
+                               if (ret != NOTIFICATION_ERROR_NONE) {
+                                       ERR("Failed to call disturb callback [%d], name [%s]", ret, info->busname);
+                                       return ret;
+                               }
+                       }
+               }
+       } else {
+               ret = notification_launch_default_viewer(priv_id, status, uid);
+               if (ret != NOTIFICATION_ERROR_NONE)
+                       ERR("Failed to launch default viewer [%d]", ret);
+       }
+
+       return ret;
+}
+
 /* add noti */
 static int _add_noti(GVariant **reply_body, notification_h noti, uid_t uid)
 {
@@ -503,14 +682,13 @@ static int _add_noti(GVariant **reply_body, notification_h noti, uid_t uid)
                return ret;
        }
 
-       ret = notification_launch_default_viewer(priv_id,
-                       NOTIFICATION_OP_INSERT, uid);
+       ret = _notification_launch_viewer(noti, priv_id,
+                               NOTIFICATION_OP_INSERT, uid);
        if (ret != NOTIFICATION_ERROR_NONE) {
-               ERR("Failed to launch default viewer [%d]", ret);
+               ERR("Failed to launch viewer [%d]", ret);
                ret = NOTIFICATION_ERROR_NONE;
        }
 
-
        *reply_body = g_variant_new("(i)", priv_id);
        if (*reply_body == NULL) {
                ERR("Failed to make reply");
@@ -782,10 +960,10 @@ static int _update_noti(GVariant **reply_body, notification_h noti, uid_t uid)
                return ret;
        }
 
-       ret = notification_launch_default_viewer(priv_id,
-                       NOTIFICATION_OP_UPDATE, uid);
+       ret = _notification_launch_viewer(noti, priv_id,
+                               NOTIFICATION_OP_UPDATE, uid);
        if (ret != NOTIFICATION_ERROR_NONE) {
-               ERR("Failed to launch default viewer [%d]", ret);
+               ERR("Failed to launch viewer [%d]", ret);
                ret = NOTIFICATION_ERROR_NONE;
        }
 
@@ -1424,11 +1602,14 @@ static int _delete_noti(const char *app_id, int priv_id, uid_t uid)
                if (ret != NOTIFICATION_ERROR_NONE)
                        return ret;
 
-               ret = notification_launch_default_viewer(NOTIFICATION_PRIV_ID_NONE,
+               /* delete disturb noti info from list */
+               __delete_disturb_noti_info(priv_id);
+
+               ret = _notification_launch_viewer(NULL, NOTIFICATION_PRIV_ID_NONE,
                                NOTIFICATION_OP_DELETE,
                                uid);
                if (ret != NOTIFICATION_ERROR_NONE) {
-                       ERR("Failed to launch default viewer [%d]", ret);
+                       ERR("Failed to launch viewer [%d]", ret);
                        ret = NOTIFICATION_ERROR_NONE;
                }
        }
@@ -1516,15 +1697,18 @@ int notification_del_noti_multiple(GVariant *parameters, GVariant **reply_body,
                                free(list_deleted);
                                return ret;
                        }
+
+                       /* delete disturb noti info from list */
+                       __delete_disturb_noti_info(*(list_deleted + i));
                }
 
                free(list_deleted);
 
-               ret = notification_launch_default_viewer(NOTIFICATION_PRIV_ID_NONE,
+               ret = _notification_launch_viewer(NULL, NOTIFICATION_PRIV_ID_NONE,
                        NOTIFICATION_OP_DELETE_ALL,
                        param_uid);
                if (ret != NOTIFICATION_ERROR_NONE) {
-                       ERR("Failed to launch default viewer [%d]", ret);
+                       ERR("Failed to launch viewer [%d]", ret);
                        ret = NOTIFICATION_ERROR_NONE;
                }
        }
@@ -1590,6 +1774,9 @@ int notification_del_noti_by_display_applist(GVariant *parameters,
                                        (deleted_list +i)->priv_id,
                                        param_uid);
                        __delete_sender_info((deleted_list +i)->priv_id);
+
+                       /* delete disturb noti info from list */
+                       __delete_disturb_noti_info((deleted_list +i)->priv_id);
                }
                __free_deleted_list_info(deleted_list, deleted_num);
 
@@ -1606,11 +1793,11 @@ int notification_del_noti_by_display_applist(GVariant *parameters,
                        return ret;
                }
 
-               ret = notification_launch_default_viewer(NOTIFICATION_PRIV_ID_NONE,
+               ret = _notification_launch_viewer(NULL, NOTIFICATION_PRIV_ID_NONE,
                        NOTIFICATION_OP_DELETE_ALL,
                        param_uid);
                if (ret != NOTIFICATION_ERROR_NONE) {
-                       ERR("Failed to launch default viewer [%d]", ret);
+                       ERR("Failed to launch viewer [%d]", ret);
                        ret = NOTIFICATION_ERROR_NONE;
                }
        }
@@ -2563,6 +2750,9 @@ HAPI int notification_delete_noti_by_app_id(const char *app_id, uid_t uid)
                        ret = __delete_sender_info(*(list_deleted + i));
                        if (ret != NOTIFICATION_ERROR_NONE)
                                goto out;
+
+                       /* delete disturb noti info from list */
+                       __delete_disturb_noti_info(*(list_deleted + i));
                }
        }
 out:
@@ -2683,4 +2873,194 @@ HAPI int notification_service_fini(void)
        return NOTIFICATION_ERROR_NONE;
 }
 
+/* added for do not disturb app */
+static bool _is_dnd_app_exist(void)
+{
+       if (__dnd_app_list != NULL && g_list_length(__dnd_app_list) > 0)
+               return true;
+
+       return false;
+}
+
+static void __free_dnd_app_info(gpointer data)
+{
+       dnd_app_info_s *info = (dnd_app_info_s *)data;
+
+       if (info) {
+               if (info->busname)
+                       free(info->busname);
+               free(info);
+       }
+}
+
+static gint __pid_compare(gconstpointer a, gconstpointer b)
+{
+       dnd_app_info_s *info = NULL;
+
+       if (!a)
+               return -1;
+
+       info = (dnd_app_info_s *)a;
+
+       if (info->pid == GPOINTER_TO_INT(b))
+               return 0;
+
+       return 1;
+}
+
+static void __dnd_app_sender_name_appeared_cb(GDBusConnection *connection,
+                                     const gchar *name,
+                                     const gchar *name_owner,
+                                     gpointer user_data)
+{
+       WARN("name[%s], name_owner[%s]", name, name_owner);
+}
+
+static void __dnd_app_sender_name_vanished_cb(GDBusConnection *connection,
+                                     const gchar *name,
+                                     gpointer user_data)
+{
+       dnd_app_info_s *info;
+
+       if (!user_data)
+               return;
+
+       info = (dnd_app_info_s *)user_data;
+
+       WARN("name[%s], pid[%d], watcher_id[%d]",
+                       name, (int)info->pid, info->watcher_id);
+}
+
+static guint __insert_dnd_app_sender_watcher_id(dnd_app_info_s *sender_info)
+{
+       guint watcher_id = 0;
+
+       watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM,
+                                     sender_info->busname,
+                                     G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                     __dnd_app_sender_name_appeared_cb,
+                                     __dnd_app_sender_name_vanished_cb,
+                                     sender_info,
+                                     NULL);
+       if (!watcher_id) {
+               ERR("Failed to watch sender name");
+               return 0;
+       }
+
+       WARN("Watch on busname[%s] watcher_id[%d]", sender_info->busname, watcher_id);
+       return watcher_id;
+}
+
+static dnd_app_info_s *__find_dnd_app_info_by_pid(pid_t pid)
+{
+       dnd_app_info_s *dnd_app_info;
+       GList *find_list;
+
+       if (__dnd_app_list == NULL) {
+               ERR("find disturb list null");
+               return NULL;
+       }
+
+       __dnd_app_list = g_list_first(__dnd_app_list);
+       find_list = g_list_find_custom(__dnd_app_list, GINT_TO_POINTER(pid),
+                                      (GCompareFunc)__pid_compare);
+
+       if (find_list)
+               dnd_app_info = g_list_nth_data(find_list, 0);
+       else
+               return NULL;
+
+       return dnd_app_info;
+}
+
+static void __delete_dnd_app_info(pid_t pid)
+{
+       dnd_app_info_s *info;
+       GList *delete_list = NULL;
+
+       WARN("delete dnd app info : [%d]", pid);
+
+       if (__dnd_app_list != NULL) {
+               __dnd_app_list = g_list_first(__dnd_app_list);
+               delete_list = g_list_find_custom(__dnd_app_list, GINT_TO_POINTER(pid),
+                                                (GCompareFunc)__pid_compare);
+               if (delete_list != NULL) {
+                       info = (dnd_app_info_s *)g_list_nth_data(delete_list, 0);
+
+                       WARN("delete dnd app from list : [%d], name : %s", info->pid, info->busname);
+
+                       __dnd_app_list = g_list_remove(g_list_first(__dnd_app_list), info);
+                       g_bus_unwatch_name(info->watcher_id);
+                       __free_dnd_app_info(info);
+                       if (g_list_length(__dnd_app_list) == 0)
+                               __dnd_app_list = NULL;
+               }
+       }
+}
+
+int notification_register_dnd_app(GVariant *parameters, GVariant **reply_body,
+               const char *sender, pid_t pid, uid_t uid)
+{
+       GList *find_list = NULL;
+       dnd_app_info_s *sender_info;
+       dnd_app_info_s *tmp_info = NULL;
+       uid_t param_uid;
+       pid_t param_pid;
+
+       /* is parameter necessary ?? */
+       /* is it necessary to check valid uid, pid ?? */
+       g_variant_get(parameters, "(ii)", &param_uid, &param_pid);
+
+       WARN("register dnd app, uid : %d, param uid : %d, pid : %d, param pid : %d",
+                       uid, param_uid, pid, param_pid);
+
+       if (sender == NULL)
+               return NOTIFICATION_ERROR_INVALID_PARAMETER;
+
+       sender_info = (dnd_app_info_s *)malloc(sizeof(dnd_app_info_s));
+       if (sender_info == NULL) {
+               ERR("malloc failed");
+               return NOTIFICATION_ERROR_OUT_OF_MEMORY;
+       }
+
+       sender_info->pid = pid;
+       sender_info->busname = strdup(sender);
+
+       if (__dnd_app_list == NULL) {
+               sender_info->watcher_id = __insert_dnd_app_sender_watcher_id(sender_info);
+               __dnd_app_list = g_list_append(__dnd_app_list, sender_info);
+       } else {
+               __dnd_app_list = g_list_first(__dnd_app_list);
+               find_list = g_list_find_custom(__dnd_app_list, GINT_TO_POINTER(pid),
+                                              (GCompareFunc)__pid_compare);
+               if (find_list == NULL) {
+                       sender_info->watcher_id = __insert_dnd_app_sender_watcher_id(sender_info);
+                       __dnd_app_list = g_list_append(__dnd_app_list, sender_info);
+               } else {
+                       tmp_info = (dnd_app_info_s *)g_list_nth_data(find_list, 0);
+                       if (tmp_info->busname) {
+                               if (strcmp(tmp_info->busname, sender)) {
+                                       free(tmp_info->busname);
+                                       tmp_info->busname = strdup(sender);
+                                       g_bus_unwatch_name(tmp_info->watcher_id);
+                                       tmp_info->watcher_id = __insert_dnd_app_sender_watcher_id(sender_info);
+                               }
+                       } else {
+                               tmp_info->busname = strdup(sender);
+                               if (!tmp_info->watcher_id)
+                                       g_bus_unwatch_name(tmp_info->watcher_id);
+                               tmp_info->watcher_id = __insert_dnd_app_sender_watcher_id(tmp_info);
+                       }
+                       __free_dnd_app_info(sender_info);
+               }
+       }
+       aul_listen_app_dead_signal_v2(_aul_app_dead_event_cb_v2, NULL);
+
+       *reply_body = g_variant_new("()");
+       if (*reply_body == NULL)
+               ERR("Failed to make reply_body");
+
+       return NOTIFICATION_ERROR_NONE;
+}
+
 /* End of a file */