Add flush timer
[platform/core/appfw/data-provider-master.git] / src / notification_ex_service.cc
1 /*
2  * Copyright (c) 2019 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
17 #include <dlog.h>
18 #include <malloc.h>
19 #include <sqlite3.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <notification_type.h>
23 #include <notification_viewer.h>
24 #include <aul.h>
25 #include <app_control_internal.h>
26 #include <pkgmgr-info.h>
27 #include <bundle.h>
28 #include <bundle_internal.h>
29 #include <tzplatform_config.h>
30 #include <notification_setting.h>
31 #include <notification_setting_internal.h>
32 #include <notification_setting_service.h>
33
34 #include <iostream>
35 #include <sstream>
36 #include <algorithm>
37 #include <map>
38
39 #include <notification_ex_item.h>
40 #include <notification-ex/manager.h>
41 #include <notification-ex/reporter.h>
42 #include <notification-ex/dbus_sender.h>
43 #include <notification-ex/dbus_event_listener.h>
44 #include <notification-ex/dbus_connection_manager.h>
45 #include <notification-ex/db_manager.h>
46 #include <notification-ex/common.h>
47 #include <notification-ex/exception.h>
48 #include <notification-ex/item_info_internal.h>
49 #include <notification-ex/button_item.h>
50 #include <notification-ex/ex_util.h>
51 #include <notification-ex/ievent_info_internal.h>
52 #include <notification-ex/event_info_internal.h>
53 #include <notification-ex/iitem_info_internal.h>
54 #include <notification-ex/shared_file.h>
55 #include <notification-ex/group_item.h>
56 #include <notification-ex/app_control_action.h>
57
58 #include "debug.h"
59 #include "notification_ex_service.h"
60
61 #define NORMAL_UID_BASE 5000
62 #define MAX_TIMEOUT 30 * 1000 /* 30 sec */
63
64 using namespace std;
65 using namespace notification;
66 using namespace notification::item;
67
68 class DPMFacade {
69  public:
70   DPMFacade(unique_ptr<Reporter> reporter, unique_ptr<Manager> manager, int restartCount)
71       : reporter_(move(reporter)), manager_(move(manager)) {
72     DBManager::InitializeDB();
73
74     if (restartCount == 0)
75       DBManager::InitializeData();
76
77     hide_map_ = DBManager::GetHideMap();
78   }
79
80   void DelegateReporterEvent(const IEventInfo& info,
81         list<shared_ptr<item::AbstractItem>> itemList) {
82     reporter_->SendEvent(info, itemList);
83   }
84
85   void DelegateManagerEvent(const IEventInfo& info,
86         list<shared_ptr<item::AbstractItem>> itemList) {
87     manager_->SendEvent(info, itemList);
88   }
89
90   void LaunchDefaultViewer(list<shared_ptr<item::AbstractItem>> item,
91                                    notification_op_type_e status) {
92     int64_t priv_id;
93     if (item.size() == 0)
94       return;
95
96     if (item.size() > 1)
97       priv_id = NOTIFICATION_PRIV_ID_NONE;
98     else
99       priv_id = static_pointer_cast<IItemInfoInternal>(
100                     item.front()->GetInfo())->GetPrivateId();
101
102     LaunchDefaultViewer(priv_id, status,
103                         static_pointer_cast<IItemInfoInternal>(
104                             item.front()->GetInfo())->GetUid());
105   }
106
107   void LaunchDefaultViewer(shared_ptr<item::AbstractItem> item,
108               notification_op_type_e status) {
109     LaunchDefaultViewer(
110         static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetPrivateId(),
111         status,
112         static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid());
113   }
114
115   void LaunchDefaultViewer(int64_t privId, notification_op_type_e status,
116                                    uid_t uid) {
117     int ret = notification_launch_default_viewer(
118                    static_cast<int>(privId), status, uid);
119     if (ret != ERROR_NONE)
120       ERR("Failed to launch default viewer [%d]", ret);
121   }
122
123   uid_t GetUid(const IEventInfo& info) {
124     uid_t validated_uid =
125             static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
126
127     return validated_uid > NORMAL_UID_BASE ?
128                     validated_uid : tzplatform_getuid(TZ_SYS_DEFAULT_USER);
129   }
130
131   void TranslateText(list<shared_ptr<item::AbstractItem>> item) {
132     for (auto& i : item)
133       TranslateText(i);
134   }
135
136   void TranslateText(shared_ptr<item::AbstractItem> item) {
137     if (item->GetMultiLanguage() != nullptr)
138       item->GetMultiLanguage()->UpdateString();
139
140     if (item->GetType() != AbstractItem::Type::Group)
141       return;
142
143     auto item_group = static_pointer_cast<GroupItem>(item);
144     auto children_list = item_group->GetChildren();
145
146     for (auto& i : children_list)
147       TranslateText(i);
148   }
149
150   bool CheckAllowedToNotify(list<shared_ptr<item::AbstractItem>> item) {
151     auto iter = item.begin();
152
153     while (iter != item.end()) {
154       if (CheckAllowedToNotify(*iter) == false)
155         iter = item.erase(iter);
156       else
157         iter++;
158     }
159
160     if (item.size() == 0)
161       return false;
162     else
163       return true;
164   }
165
166   bool CheckAllowedToNotify(shared_ptr<item::AbstractItem> item) {
167     notification_setting_h setting;
168     int ret;
169     bool allow_to_notify, app_disabled;
170     uid_t uid = static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid();
171
172     ret = noti_setting_service_get_setting_by_app_id(item->GetSenderAppId().c_str(),
173              &setting, uid);
174     if (ret != NOTIFICATION_ERROR_NONE)
175       return true;
176
177     notification_setting_get_allow_to_notify(setting, &allow_to_notify);
178     notification_setting_get_app_disabled(setting, &app_disabled);
179     notification_setting_free_notification(setting);
180
181     if (!allow_to_notify || app_disabled) {
182       ERR("[%s] is not allowed to notify[%d,%d]", item->GetSenderAppId().c_str(),
183             allow_to_notify, app_disabled);
184       return false;
185     }
186
187     return true;
188   }
189
190   bool CheckDoNoDisturbStatus(uid_t uid, const string& owner) {
191     int ret;
192     bool do_not_disturb = false;
193     bool do_not_disturb_exception;
194     notification_setting_h setting = nullptr;
195     notification_system_setting_h system_setting = nullptr;
196
197     ret = noti_system_setting_load_system_setting(&system_setting, uid);
198     if (ret != NOTIFICATION_ERROR_NONE) {
199       WARN("Failed to load system setting [%d]", ret);
200       goto out;
201     }
202
203     ret = notification_system_setting_get_do_not_disturb(system_setting, &do_not_disturb);
204     if (ret != NOTIFICATION_ERROR_NONE) {
205       WARN("Failed to get do_not_disturb [%d]", ret);
206       goto out;
207     }
208
209     if (do_not_disturb) {
210       do_not_disturb = false;
211       /* Check exception option of the caller app_id */
212       ret = noti_setting_service_get_setting_by_app_id(owner.c_str(), &setting, uid);
213       if (ret != NOTIFICATION_ERROR_NONE) {
214         WARN("Failed to get setting by app_id [%d]", ret);
215         goto out;
216       }
217
218       ret = notification_setting_get_do_not_disturb_except(setting, &do_not_disturb_exception);
219       if (ret != NOTIFICATION_ERROR_NONE) {
220         WARN("Failed to get do_not_disturb_exception [%d]", ret);
221         goto out;
222       }
223
224       if (do_not_disturb_exception == false)
225         do_not_disturb = true;
226     }
227
228 out:
229     DBG("do_not_disturb [%d]", do_not_disturb);
230     if (system_setting)
231       notification_system_setting_free_system_setting(system_setting);
232
233     if (setting)
234       notification_setting_free_notification(setting);
235
236     return do_not_disturb;
237   }
238
239   void SetDoNoDisturbPolicy(list<shared_ptr<item::AbstractItem>> item) {
240     for (auto& i : item)
241       SetDoNoDisturbPolicy(i);
242   }
243
244   void SetDoNoDisturbPolicy(shared_ptr<item::AbstractItem> item) {
245     uid_t uid = static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid();
246     if (CheckDoNoDisturbStatus(uid, item->GetSenderAppId()) == false)
247       return;
248
249     item->SetSoundPath("");
250     item->SetVibrationPath("");
251     item->SetLEDInfo(nullptr);
252
253     std::list<std::string> receiver_list = item->GetReceiverList();
254     if (receiver_list.size() == 0) {
255       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_PANEL);
256       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_INDICATOR);
257     } else {
258        auto iter = receiver_list.begin();
259
260       while (iter != receiver_list.end()) {
261         if ((*iter).compare(NOTI_EX_RECEIVER_GROUP_PANEL) != 0
262               && (*iter).compare(NOTI_EX_RECEIVER_GROUP_INDICATOR) != 0)
263           iter = receiver_list.erase(iter);
264         else
265           iter++;
266       }
267     }
268   }
269
270   void SetPopUpPolicy(list<shared_ptr<item::AbstractItem>> item) {
271     for (auto& i : item)
272       SetPopUpPolicy(i);
273   }
274
275   void SetPopUpPolicy(shared_ptr<item::AbstractItem> item) {
276     notification_setting_h setting;
277     int ret;
278     bool is_pop_up;
279     uid_t uid = static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid();
280     ret = noti_setting_service_get_setting_by_app_id(item->GetSenderAppId().c_str(),
281                    &setting, uid);
282     if (ret != NOTIFICATION_ERROR_NONE) {
283       WARN("Failed get the setting for [%s] [%x]", item->GetSenderAppId().c_str(), ret);
284       return;
285     }
286
287     notification_setting_get_pop_up_notification(setting, &is_pop_up);
288     notification_setting_free_notification(setting);
289     if (is_pop_up == true)
290       return;
291
292     std::list<std::string> receiver_list = item->GetReceiverList();
293     if (receiver_list.size() == 0) {
294       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_PANEL);
295       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_TICKER);
296       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_LOCKSCREEN);
297       item->AddReceiver(NOTI_EX_RECEIVER_GROUP_INDICATOR);
298     } else {
299        auto iter = receiver_list.begin();
300
301       while (iter != receiver_list.end()) {
302         if ((*iter).compare(NOTI_EX_RECEIVER_GROUP_POPUP) == 0)
303           iter = receiver_list.erase(iter);
304         else
305           iter++;
306       }
307     }
308   }
309
310   void SetMemoryTrimTimer(void) {
311     static guint timer = 0;
312     if (timer > 0)
313       g_source_remove(timer);
314
315     timer = g_timeout_add(MAX_TIMEOUT, TimeoutHandler, &timer);
316   }
317
318   static gboolean TimeoutHandler(gpointer data) {
319     guint* timer = static_cast<guint*>(data);
320     sqlite3_release_memory(-1);
321     malloc_trim(0);
322     *timer = 0;
323
324     return false;
325   }
326
327   unique_ptr<Reporter> reporter_;
328   unique_ptr<Manager> manager_;
329   map<string, string> hide_map_;
330   multimap<string, string> receiver_group_list_;
331   SharedFile shared_file_;
332 };
333
334 static DPMFacade* facade_;
335
336 class DPMReporter : public Reporter {
337  protected:
338   void OnUpdate(const IEventInfo& info,
339       list<shared_ptr<item::AbstractItem>> updatedList) {
340     DBG("Update !!!");
341     int ret;
342
343     /* check Manager::Hide() */
344     ret = UpdateHideApp(updatedList);
345     if (ret == ERROR_NONE)
346       return;
347
348     if (ret != ERROR_NOT_EXIST_ID) {
349       SendError(info, static_cast<NotificationError>(ret));
350       return;
351     }
352
353     ret = DBManager::UpdateNotification(updatedList);
354     if (ret == ERROR_NONE) {
355       facade_->TranslateText(updatedList);
356       /* noti owner */
357       facade_->DelegateManagerEvent(info, updatedList);
358
359       /* noti to viewers */
360       facade_->DelegateReporterEvent(info, updatedList);
361     } else {
362       SendError(info, static_cast<NotificationError>(ret));
363     }
364   }
365
366   void DoDelete(const IEventInfo& info,
367       list<shared_ptr<item::AbstractItem>> deletedList) {
368     int ret = DBManager::DeleteNotification(deletedList);
369     if (ret == ERROR_NONE) {
370       /* noti owner */
371       facade_->DelegateManagerEvent(info, deletedList);
372
373       /* noti to viewers */
374       facade_->DelegateReporterEvent(info, deletedList);
375
376       facade_->shared_file_.RemovePrivateSharing(deletedList,
377             facade_->receiver_group_list_);
378     } else {
379       SendError(info, static_cast<NotificationError>(ret));
380     }
381   }
382
383   void OnDelete(const IEventInfo& info,
384       list<shared_ptr<item::AbstractItem>> deletedList) {
385     DBG("Delete !!!");
386     if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
387       list<shared_ptr<item::AbstractItem>> noti_list;
388       if(!info.GetItemId().empty()) /* The item_id is actually an app_id. */
389         noti_list = DBManager::GetNotificationList(
390                 info.GetItemId(), facade_->GetUid(info), "");
391       else
392         noti_list = DBManager::GetNotificationList(
393                 facade_->GetUid(info), info.GetChannel());
394
395       EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
396       DoDelete(event_info, noti_list);
397     } else {
398       DoDelete(info, deletedList);
399     }
400   }
401
402   void OnEvent(const IEventInfo& info,
403       list<shared_ptr<item::AbstractItem>> noti_list) override {
404     LOGI("Event received (%d) !!", (int)info.GetEventType());
405     int type = info.GetEventType();
406
407     switch (type) {
408       case IEventInfo::EventType::Update:
409         OnUpdate(info, noti_list);
410         break;
411       case IEventInfo::EventType::Delete:
412         OnDelete(info, noti_list);
413         break;
414       case IEventInfo::EventType::DeleteAll:
415         OnDelete(info, noti_list);
416         break;
417       case IEventInfo::EventType::Register:
418         OnRegister(info);
419         break;
420       default :
421         break;
422     }
423
424     facade_->SetMemoryTrimTimer();
425   }
426
427   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
428     list<shared_ptr<item::AbstractItem>> item_list;
429
430     DBG("Get report !!! %s", info.GetItemId().c_str());
431     item_list = DBManager::GetNotificationList(facade_->GetUid(info),
432                 ((const IEventInfoInternal&)info).GetChannel().c_str());
433
434     facade_->shared_file_.SetPrivateSharing(item_list,
435                 facade_->receiver_group_list_);
436
437     facade_->TranslateText(item_list);
438     facade_->SetMemoryTrimTimer();
439
440     return item_list;
441   }
442
443   int OnRequestNumber(const IEventInfo& info) override {
444     DBG("Get count !!! %s", info.GetItemId().c_str());
445     facade_->SetMemoryTrimTimer();
446
447     return DBManager::GetNotificationList(facade_->GetUid(info)).size();
448   }
449
450   int UpdateHideApp(list<shared_ptr<item::AbstractItem>> updatedList) {
451     int ret;
452     for (auto& i : updatedList) {
453       string hide_list;
454       int uid = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetUid();
455       DBG("try update hide app_id(%s) sender(%s) uid(%s)",
456         i->GetId().c_str(),
457         i->GetSenderAppId().c_str(), string(to_string(uid)).c_str());
458       string map_key = i->GetId() + i->GetSenderAppId() + string(to_string(uid));
459       list<string> updated_hide_list = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetHideViewerList();
460
461       /* Check new hide app */
462       auto noti = facade_->hide_map_.find(map_key);
463       if (noti == facade_->hide_map_.end()) {
464         if (updated_hide_list.size() > 0) {
465           for (auto& j : updated_hide_list)
466             hide_list += j + ";";
467
468           ret = DBManager::UpdateHideList(i, hide_list);
469           if (ret != ERROR_NONE)
470             return ret;
471
472           facade_->hide_map_[map_key] = hide_list;
473           return ERROR_NONE;
474         } else {
475           DBG("Empty hide viewer list");
476           return ERROR_NOT_EXIST_ID;
477         }
478       }
479
480       /* Check new hide app */
481       hide_list = noti->second;
482       for (auto& j : updated_hide_list) {
483         if (hide_list.find(j + ";") == string::npos) {
484           string new_hide_list = hide_list + j + ";";
485           ret = DBManager::UpdateHideList(i, new_hide_list);
486           if (ret != ERROR_NONE)
487             return ret;
488
489           facade_->hide_map_[map_key] = new_hide_list;
490           return ERROR_NONE;
491         }
492       }
493     }
494     return ERROR_NOT_EXIST_ID;
495   }
496
497   void OnRegister(const IEventInfo& info) {
498     std::string receiver_group = info.GetChannel();
499     std::string appid = info.GetOwner();
500
501     std::multimap<std::string,std::string>::iterator it;
502     for(auto receiver_group_ : facade_->receiver_group_list_) {
503       if (receiver_group_.first.compare(receiver_group) == 0 &&
504           receiver_group_.second.compare(appid) == 0)
505         return;
506     }
507
508     facade_->receiver_group_list_.insert(make_pair(receiver_group, appid));
509   }
510
511  public:
512   DPMReporter(std::unique_ptr<IEventSender> sender,
513       std::unique_ptr<IEventListener> listener)
514     : Reporter(move(sender), move(listener)) {
515   }
516 };
517
518 class DPMManager : public Manager {
519  protected:
520   void OnAdd(const IEventInfo& info,
521       list<shared_ptr<item::AbstractItem>> addedList) override {
522     DBG("Add !!!");
523     int ret;
524
525     ret = ValidateUid(info, addedList);
526     if (ret != ERROR_NONE) {
527       SendError(info, static_cast<NotificationError>(ret));
528       return;
529     }
530
531     SetIndirectRequest(info, addedList);
532
533     if (facade_->CheckAllowedToNotify(addedList) == false)
534       return;
535
536     facade_->SetDoNoDisturbPolicy(addedList);
537     facade_->SetPopUpPolicy(addedList);
538
539     ret = DBManager::InsertNotification(addedList);
540     if (ret == ERROR_NONE) {
541       facade_->shared_file_.SetPrivateSharing(addedList,
542             facade_->receiver_group_list_);
543       facade_->TranslateText(addedList);
544       facade_->DelegateReporterEvent(info, addedList);
545       facade_->LaunchDefaultViewer(addedList, NOTIFICATION_OP_INSERT);
546     } else {
547         DBG("SendError !!!");
548         SendError(info, static_cast<NotificationError>(ret));
549     }
550     facade_->SetMemoryTrimTimer();
551   }
552
553   void OnUpdate(const IEventInfo& info,
554       list<shared_ptr<item::AbstractItem>> updatedList) override {
555     DBG("Update !!!");
556     int ret;
557
558     ret = ValidateUid(info, updatedList);
559     if (ret != ERROR_NONE) {
560       SendError(info, static_cast<NotificationError>(ret));
561       return;
562     }
563
564     UpdateHideApp(updatedList);
565     SetIndirectRequest(info, updatedList);
566
567     if (facade_->CheckAllowedToNotify(updatedList) == false)
568       return;
569
570     facade_->SetDoNoDisturbPolicy(updatedList);
571     facade_->SetPopUpPolicy(updatedList);
572
573     ret = DBManager::UpdateNotification(updatedList);
574     if (ret == ERROR_NONE) {
575       facade_->shared_file_.UpdatePrivateSharing(updatedList,
576             facade_->receiver_group_list_);
577       facade_->TranslateText(updatedList);
578       facade_->DelegateReporterEvent(info, updatedList);
579       facade_->LaunchDefaultViewer(updatedList, NOTIFICATION_OP_UPDATE);
580     } else {
581       SendError(info, static_cast<NotificationError>(ret));
582     }
583     facade_->SetMemoryTrimTimer();
584   }
585
586   int DoDelete(const IEventInfo& info,
587       list<shared_ptr<item::AbstractItem>> deletedList) {
588     int ret;
589
590     ret = DBManager::DeleteNotification(deletedList);
591     if (ret == ERROR_NONE) {
592       facade_->DelegateReporterEvent(info, deletedList);
593       facade_->shared_file_.RemovePrivateSharing(deletedList,
594             facade_->receiver_group_list_);
595     } else {
596       SendError(info, static_cast<NotificationError>(ret));
597     }
598     return ret;
599   }
600
601   void OnDelete(const IEventInfo& info,
602       list<shared_ptr<item::AbstractItem>> deletedList) override {
603     DBG("Delete !!!");
604     if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
605       list<shared_ptr<item::AbstractItem>> noti_list =
606           DBManager::GetNotificationList(info.GetOwner(), facade_->GetUid(info),
607           info.GetChannel());
608       EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
609
610       DoDelete(event_info, noti_list);
611       facade_->LaunchDefaultViewer(noti_list, NOTIFICATION_OP_DELETE);
612     } else {
613       int64_t priv_id = static_pointer_cast<IItemInfoInternal>
614                            (deletedList.front()->GetInfo())->GetPrivateId();
615       list<shared_ptr<item::AbstractItem>> noti_list;
616       if (priv_id == 0) {
617         noti_list = DBManager::GetNotificationList(info.GetOwner(),
618             deletedList.front()->GetId(), facade_->GetUid(info));
619       } else {
620         noti_list = deletedList;
621       }
622       int ret = DoDelete(info, noti_list);
623       if (ret == ERROR_NONE)
624         facade_->LaunchDefaultViewer(deletedList, NOTIFICATION_OP_DELETE);
625     }
626     facade_->SetMemoryTrimTimer();
627   }
628
629   list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
630     DBG("Get !!! %s", info.GetOwner().c_str());
631     list<shared_ptr<item::AbstractItem>> item_list;
632     uid_t uid = facade_->GetUid(info);
633     facade_->SetMemoryTrimTimer();
634
635     if (info.GetItemId().empty()) {
636       if (!info.GetChannel().empty()) {
637         /* get by channel */
638         item_list = DBManager::GetNotificationList(info.GetOwner(), uid, info.GetChannel());
639         facade_->TranslateText(item_list);
640         return item_list;
641       } else {
642         /* get all*/
643         item_list = DBManager::GetNotificationList(info.GetOwner(), uid);
644         facade_->TranslateText(item_list);
645         return item_list;
646       }
647     } else {
648       /*  FindByRootID */
649       item_list = DBManager::GetNotificationList(info.GetOwner(), info.GetItemId(), uid);
650       facade_->TranslateText(item_list);
651       return item_list;
652     }
653   }
654
655   int OnRequestNumber(const IEventInfo& info) override {
656     int count = 0;
657     DBG("Get count !!! %s, %s", info.GetOwner().c_str(), info.GetChannel().c_str());
658     DBManager::GetCount(info.GetOwner(), info.GetChannel(), facade_->GetUid(info), &count);
659     facade_->SetMemoryTrimTimer();
660
661     return count;
662   }
663
664   void UpdateHideApp(list<shared_ptr<item::AbstractItem>> updatedList) {
665     for (auto& i : updatedList) {
666       string hide_list;
667       int uid = static_pointer_cast<IItemInfoInternal>(i->GetInfo())->GetUid();
668       string map_key = i->GetId() + i->GetSenderAppId() + string(to_string(uid));
669       list<string> updated_hide_list =
670           static_pointer_cast<item::IItemInfoInternal>(i->GetInfo())->GetHideViewerList();
671
672       auto noti = facade_->hide_map_.find(map_key);
673       if (noti == facade_->hide_map_.end())
674         return;
675
676       /* hide app list synchronization */
677       hide_list = noti->second;
678       istringstream stream(hide_list);
679       string hide_app_id;
680
681       while (getline(stream, hide_app_id, ';')) {
682         list<string>::iterator iter = std::find(updated_hide_list.begin(),
683                       updated_hide_list.end(), hide_app_id);
684         if (iter == updated_hide_list.end())
685           static_pointer_cast<item::IItemInfoInternal>(i->GetInfo())->AddHideViewer(hide_app_id);
686       }
687     }
688   }
689
690   void SetIndirectRequest(const IEventInfo& info,
691           list<shared_ptr<AbstractItem>> addedList) {
692     for (auto& i : addedList)
693       SetIndirectRequest(info, i);
694   }
695
696   void SetIndirectRequest(const IEventInfo& info,
697           shared_ptr<AbstractItem> addedItem) {
698     SetIndirectRequest(info, addedItem->GetAction());
699
700     if (addedItem->GetType() != AbstractItem::Type::Group)
701       return;
702
703     auto item_group = static_pointer_cast<GroupItem>(addedItem);
704     auto children_list = item_group->GetChildren();
705     for (auto& i : children_list)
706       SetIndirectRequest(info, i);
707   }
708
709   void SetIndirectRequest(const IEventInfo& info, shared_ptr<AbstractAction>action) {
710     if (action == nullptr || action->GetType() != AbstractAction::Type::AppControl)
711       return;
712
713     uid_t uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
714     if (uid < NORMAL_UID_BASE)
715       return;
716
717     string owner = static_cast<const IEventInfoInternal&>(info).GetValidatedOwner();
718     app_control_h appcontrol = static_pointer_cast<AppControlAction>(action)->GetAppControl();
719     bundle* b = nullptr;
720     app_control_export_as_bundle(appcontrol, &b);
721
722     bundle_del(b, AUL_K_REQUEST_TYPE);
723     bundle_add(b, AUL_K_REQUEST_TYPE, "indirect-request");
724
725     bundle_del(b, AUL_K_ORG_CALLER_UID);
726     bundle_add(b, AUL_K_ORG_CALLER_UID, std::to_string(uid).c_str());
727
728     bundle_del(b, AUL_K_ORG_CALLER_APPID);
729     bundle_add(b, AUL_K_ORG_CALLER_APPID, owner.c_str());
730
731     pkgmgrinfo_appinfo_h handle;
732     int r = pkgmgrinfo_appinfo_get_usr_appinfo(owner.c_str(), uid, &handle);
733     if (r == PMINFO_R_OK) {
734       char* pkgid = nullptr;
735       pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
736       if (pkgid) {
737         bundle_del(b, AUL_K_ORG_CALLER_PKGID);
738         bundle_add(b, AUL_K_ORG_CALLER_PKGID, pkgid);
739       }
740       pkgmgrinfo_appinfo_destroy_appinfo(handle);
741     }
742
743     app_control_import_from_bundle(appcontrol, b);
744     bundle_free(b);
745   }
746
747   int ValidateUid(const IEventInfo& info, list<shared_ptr<AbstractItem>> addedList) {
748     int ret;
749     for (auto& i : addedList) {
750       ret = ValidateUid(info, i);
751       if (ret != ERROR_NONE)
752         return ret;
753     }
754
755     return ERROR_NONE;
756   }
757
758   int ValidateUid(const IEventInfo& info, shared_ptr<AbstractItem> addedItem) {
759     uid_t validated_uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
760     uid_t item_uid = static_pointer_cast<IItemInfoInternal>
761                                   (addedItem->GetInfo())->GetUid();
762
763     if (validated_uid <= NORMAL_UID_BASE) {
764       static_pointer_cast<IItemInfoInternal>
765           (addedItem->GetInfo())->SetUid(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
766     } else if (validated_uid != item_uid) {
767       ERR("Invalid sender uid[%d] noti_uid[%d]", validated_uid, item_uid);
768       return ERROR_INVALID_PARAMETER;
769     }
770
771     return ERROR_NONE;
772   }
773
774  public:
775   DPMManager(std::unique_ptr<IEventSender> sender,
776       std::unique_ptr<IEventListener> listener)
777     : Manager(move(sender), move(listener)) {
778   }
779 };
780
781 HAPI int notification_ex_service_init(int restart_count) {
782   facade_ = new DPMFacade(
783     unique_ptr<Reporter>(
784       new DPMReporter(
785         unique_ptr<DBusSender>(new DBusSender(Manager::GetPath())),
786         unique_ptr<DBusEventListener>(new DBusEventListener(Reporter::GetPath())))),
787     unique_ptr<Manager>(
788       new DPMManager(
789         unique_ptr<DBusSender>(new DBusSender(Reporter::GetPath())),
790         unique_ptr<DBusEventListener>(new DBusEventListener(Manager::GetPath())))),
791         restart_count);
792
793   notification_init_default_viewer();
794   facade_->SetMemoryTrimTimer();
795
796   return ERROR_NONE;
797 }
798
799 HAPI int notification_ex_service_fini() {
800   delete facade_;
801   return ERROR_NONE;
802 }
803
804 HAPI GDBusConnection* notification_ex_service_get_gdbus_connection() {
805   return DBusConnectionManager::GetInst().GetConnection();
806 }