2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <notification_type.h>
21 #include <notification_viewer.h>
23 #include <app_control_internal.h>
24 #include <pkgmgr-info.h>
26 #include <bundle_internal.h>
27 #include <tzplatform_config.h>
28 #include <notification_setting.h>
29 #include <notification_setting_internal.h>
30 #include <notification_setting_service.h>
37 #include <notification_ex_item.h>
38 #include <notification-ex/manager.h>
39 #include <notification-ex/reporter.h>
40 #include <notification-ex/dbus_sender.h>
41 #include <notification-ex/dbus_event_listener.h>
42 #include <notification-ex/dbus_connection_manager.h>
43 #include <notification-ex/db_manager.h>
44 #include <notification-ex/common.h>
45 #include <notification-ex/exception.h>
46 #include <notification-ex/item_info_internal.h>
47 #include <notification-ex/button_item.h>
48 #include <notification-ex/ex_util.h>
49 #include <notification-ex/ievent_info_internal.h>
50 #include <notification-ex/event_info_internal.h>
51 #include <notification-ex/iitem_info_internal.h>
52 #include <notification-ex/shared_file.h>
53 #include <notification-ex/group_item.h>
54 #include <notification-ex/app_control_action.h>
57 #include "notification_ex_service.h"
59 #define NORMAL_UID_BASE 5000
62 using namespace notification;
63 using namespace notification::item;
67 DPMFacade(unique_ptr<Reporter> reporter, unique_ptr<Manager> manager, int restartCount)
68 : reporter_(move(reporter)), manager_(move(manager)) {
69 DBManager::InitializeDB();
71 if (restartCount == 0)
72 DBManager::InitializeData();
74 hide_map_ = DBManager::GetHideMap();
77 void DelegateReporterEvent(const IEventInfo& info,
78 shared_ptr<item::AbstractItem> item) {
79 reporter_->SendEvent(info, item);
82 void DelegateReporterEvent(const IEventInfo& info,
83 std::list<std::shared_ptr<item::AbstractItem>> itemList) {
84 reporter_->SendEvent(info, itemList);
87 void DelegateManagerEvent(const IEventInfo& info,
88 shared_ptr<item::AbstractItem> noti) {
89 manager_->SendEvent(info, noti);
92 void LaunchDefaultViewer(list<shared_ptr<item::AbstractItem>> item,
93 notification_op_type_e status) {
99 priv_id = NOTIFICATION_PRIV_ID_NONE;
101 priv_id = static_pointer_cast<IItemInfoInternal>(
102 item.front()->GetInfo())->GetPrivateId();
104 LaunchDefaultViewer(priv_id, status,
105 static_pointer_cast<IItemInfoInternal>(
106 item.front()->GetInfo())->GetUid());
108 void LaunchDefaultViewer(shared_ptr<item::AbstractItem> item,
109 notification_op_type_e status) {
111 static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetPrivateId(),
113 static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid());
116 void LaunchDefaultViewer(int64_t privId, notification_op_type_e status,
118 int ret = notification_launch_default_viewer(
119 static_cast<int>(privId), status, uid);
120 if (ret != ERROR_NONE)
121 ERR("Failed to launch default viewer [%d]", ret);
124 uid_t GetUid(const IEventInfo& info) {
125 uid_t validated_uid =
126 static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
128 return validated_uid > NORMAL_UID_BASE ?
129 validated_uid : tzplatform_getuid(TZ_SYS_DEFAULT_USER);
132 void TranslateText(list<shared_ptr<item::AbstractItem>> item) {
137 void TranslateText(shared_ptr<item::AbstractItem> item) {
138 if (item->GetMultiLanguage() != nullptr)
139 item->GetMultiLanguage()->UpdateString();
141 if (item->GetType() != AbstractItem::Type::Group)
144 auto item_group = static_pointer_cast<GroupItem>(item);
145 auto children_list = item_group->GetChildren();
147 for (auto& i : children_list)
151 bool CheckAllowedToNotify(list<shared_ptr<item::AbstractItem>> item) {
152 auto iter = item.begin();
154 while (iter != item.end()) {
155 if (CheckAllowedToNotify(*iter) == false)
156 iter = item.erase(iter);
161 if (item.size() == 0)
167 bool CheckAllowedToNotify(shared_ptr<item::AbstractItem> item) {
168 notification_setting_h setting;
170 bool allow_to_notify, app_disabled;
171 uid_t uid = static_pointer_cast<IItemInfoInternal>(item->GetInfo())->GetUid();
173 ret = noti_setting_service_get_setting_by_app_id(item->GetSenderAppId().c_str(),
175 if (ret != NOTIFICATION_ERROR_NONE)
178 notification_setting_get_allow_to_notify(setting, &allow_to_notify);
179 notification_setting_get_app_disabled(setting, &app_disabled);
180 notification_setting_free_notification(setting);
182 if (!allow_to_notify || app_disabled) {
183 ERR("[%s] is not allowed to notify[%d,%d]", item->GetSenderAppId().c_str(),
184 allow_to_notify, app_disabled);
190 bool CheckDoNoDisturbStatus(uid_t uid, const string& owner) {
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;
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);
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);
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);
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);
224 if (do_not_disturb_exception == false)
225 do_not_disturb = true;
229 DBG("do_not_disturb [%d]", do_not_disturb);
231 notification_system_setting_free_system_setting(system_setting);
234 notification_setting_free_notification(setting);
236 return do_not_disturb;
239 void SetDoNoDisturbPolicy(list<shared_ptr<item::AbstractItem>> item) {
241 SetDoNoDisturbPolicy(i);
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)
249 item->SetSoundPath("");
250 item->SetVibrationPath("");
251 item->SetLEDInfo(nullptr);
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);
258 auto iter = receiver_list.begin();
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);
270 void SetPopUpPolicy(list<shared_ptr<item::AbstractItem>> item) {
275 void SetPopUpPolicy(shared_ptr<item::AbstractItem> item) {
276 notification_setting_h setting;
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(),
282 if (ret != NOTIFICATION_ERROR_NONE) {
283 WARN("Failed get the setting for [%s] [%x]", item->GetSenderAppId().c_str(), ret);
287 notification_setting_get_pop_up_notification(setting, &is_pop_up);
288 notification_setting_free_notification(setting);
289 if (is_pop_up == true)
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);
299 auto iter = receiver_list.begin();
301 while (iter != receiver_list.end()) {
302 if ((*iter).compare(NOTI_EX_RECEIVER_GROUP_POPUP) == 0)
303 iter = receiver_list.erase(iter);
309 unique_ptr<Reporter> reporter_;
310 unique_ptr<Manager> manager_;
311 map<string, string> hide_map_;
312 multimap<string, string> receiver_group_list_;
313 SharedFile shared_file_;
316 static DPMFacade* facade_;
318 class DPMReporter : public Reporter {
320 void OnUpdate(const IEventInfo& info,
321 shared_ptr<item::AbstractItem> updatedItem) {
325 /* check Manager::Hide() */
326 ret = UpdateHideApp(updatedItem);
327 if (ret == ERROR_NONE)
330 if (ret != ERROR_NOT_EXIST_ID) {
331 SendError(info, static_cast<NotificationError>(ret));
335 ret = DBManager::UpdateNotification(updatedItem);
336 if (ret == ERROR_NONE) {
337 facade_->TranslateText(updatedItem);
339 facade_->DelegateManagerEvent(info, updatedItem);
341 /* noti to viewers */
342 facade_->DelegateReporterEvent(info, updatedItem);
344 SendError(info, static_cast<NotificationError>(ret));
348 void DoDelete(const IEventInfo& info,
349 shared_ptr<item::AbstractItem> deletedItem) {
350 int ret = DBManager::DeleteNotification(deletedItem);
351 if (ret == ERROR_NONE) {
353 facade_->DelegateManagerEvent(info, deletedItem);
355 /* noti to viewers */
356 facade_->DelegateReporterEvent(info, deletedItem);
358 facade_->shared_file_.RemovePrivateSharing(deletedItem,
359 facade_->receiver_group_list_);
361 SendError(info, static_cast<NotificationError>(ret));
365 void OnDelete(const IEventInfo& info,
366 shared_ptr<item::AbstractItem> deletedItem) {
368 if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
369 list<shared_ptr<item::AbstractItem>> noti_list =
370 DBManager::GetNotificationList(facade_->GetUid(info), info.GetChannel());
371 for (auto& i : noti_list) {
375 DoDelete(info, deletedItem);
379 void OnEvent(const IEventInfo& info,
380 list<shared_ptr<item::AbstractItem>> noti_list) override {
381 LOGI("Event received (%d) !!", (int)info.GetEventType());
382 int type = info.GetEventType();
383 if (type == IEventInfo::EventType::DeleteAll) {
384 OnDelete(info, nullptr);
386 } else if (type == IEventInfo::EventType::Register) {
391 for (auto& i : noti_list) {
393 case IEventInfo::EventType::Update:
396 case IEventInfo::EventType::Delete:
405 list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
406 list<shared_ptr<item::AbstractItem>> item_list;
408 DBG("Get report !!! %s", info.GetItemId().c_str());
409 item_list = DBManager::GetNotificationList(facade_->GetUid(info),
410 ((const IEventInfoInternal&)info).GetChannel().c_str());
412 facade_->shared_file_.SetPrivateSharing(item_list,
413 facade_->receiver_group_list_);
415 facade_->TranslateText(item_list);
420 int OnRequestNumber(const IEventInfo& info) override {
421 DBG("Get count !!! %s", info.GetItemId().c_str());
422 return DBManager::GetNotificationList(facade_->GetUid(info)).size();
425 int UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
428 int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
429 DBG("try update hide app_id(%s) sender(%s) uid(%s)",
430 updatedItem->GetId().c_str(),
431 updatedItem->GetSenderAppId().c_str(), string(to_string(uid)).c_str());
432 string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
433 list<string> updated_hide_list = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
435 /* Check new hide app */
436 auto noti = facade_->hide_map_.find(map_key);
437 if (noti == facade_->hide_map_.end()) {
438 if (updated_hide_list.size() > 0) {
439 for (auto& i : updated_hide_list)
440 hide_list += i + ";";
442 ret = DBManager::UpdateHideList(updatedItem, hide_list);
443 if (ret != ERROR_NONE)
446 facade_->hide_map_[map_key] = hide_list;
449 DBG("Empty hide viewer list");
450 return ERROR_NOT_EXIST_ID;
454 /* Check new hide app */
455 hide_list = noti->second;
456 for (auto& i : updated_hide_list) {
457 if (hide_list.find(i + ";") == string::npos) {
458 string new_hide_list = hide_list + i + ";";
459 ret = DBManager::UpdateHideList(updatedItem, new_hide_list);
460 if (ret != ERROR_NONE)
463 facade_->hide_map_[map_key] = new_hide_list;
468 return ERROR_NOT_EXIST_ID;
471 void OnRegister(const IEventInfo& info) {
472 std::string receiver_group = info.GetChannel();
473 std::string appid = info.GetOwner();
475 std::multimap<std::string,std::string>::iterator it;
476 for(auto receiver_group_ : facade_->receiver_group_list_) {
477 if (receiver_group_.first.compare(receiver_group) == 0 &&
478 receiver_group_.second.compare(appid) == 0)
482 facade_->receiver_group_list_.insert(make_pair(receiver_group, appid));
486 DPMReporter(std::unique_ptr<IEventSender> sender,
487 std::unique_ptr<IEventListener> listener)
488 : Reporter(move(sender), move(listener)) {
492 class DPMManager : public Manager {
494 void UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
496 int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
497 string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
498 list<string> updated_hide_list =
499 static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
501 auto noti = facade_->hide_map_.find(map_key);
502 if (noti == facade_->hide_map_.end())
505 /* hide app list synchronization */
506 hide_list = noti->second;
507 istringstream stream(hide_list);
510 while (getline(stream, hide_app_id, ';')) {
511 list<string>::iterator iter = std::find(updated_hide_list.begin(),
512 updated_hide_list.end(), hide_app_id);
513 if (iter == updated_hide_list.end())
514 static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->AddHideViewer(hide_app_id);
518 void OnAdd(const IEventInfo& info,
519 list<shared_ptr<item::AbstractItem>> addedItem) override {
523 ret = ValidateUid(info, addedItem);
524 if (ret != ERROR_NONE) {
525 SendError(info, static_cast<NotificationError>(ret));
529 SetIndirectRequest(info, addedItem);
531 if (facade_->CheckAllowedToNotify(addedItem) == false)
534 facade_->SetDoNoDisturbPolicy(addedItem);
535 facade_->SetPopUpPolicy(addedItem);
537 ret = DBManager::InsertNotification(addedItem);
538 if (ret == ERROR_NONE) {
539 facade_->shared_file_.SetPrivateSharing(addedItem,
540 facade_->receiver_group_list_);
541 facade_->TranslateText(addedItem);
542 facade_->DelegateReporterEvent(info, addedItem);
543 facade_->LaunchDefaultViewer(addedItem, NOTIFICATION_OP_INSERT);
545 DBG("SendError !!!");
546 SendError(info, static_cast<NotificationError>(ret));
550 void OnUpdate(const IEventInfo& info,
551 shared_ptr<item::AbstractItem> updatedItem) override {
555 ret = ValidateUid(info, updatedItem);
556 if (ret != ERROR_NONE) {
557 SendError(info, static_cast<NotificationError>(ret));
561 UpdateHideApp(updatedItem);
562 SetIndirectRequest(info, updatedItem);
564 if (facade_->CheckAllowedToNotify(updatedItem) == false)
567 facade_->SetDoNoDisturbPolicy(updatedItem);
568 facade_->SetPopUpPolicy(updatedItem);
570 ret = DBManager::UpdateNotification(updatedItem);
571 if (ret == ERROR_NONE) {
572 facade_->shared_file_.UpdatePrivateSharing(updatedItem,
573 facade_->receiver_group_list_);
574 facade_->TranslateText(updatedItem);
575 facade_->DelegateReporterEvent(info, updatedItem);
576 facade_->LaunchDefaultViewer(updatedItem, NOTIFICATION_OP_UPDATE);
578 SendError(info, static_cast<NotificationError>(ret));
582 int DoDelete(const IEventInfo& info,
583 shared_ptr<item::AbstractItem> deletedItem) {
586 ret = DBManager::DeleteNotification(deletedItem);
587 if (ret == ERROR_NONE) {
588 facade_->DelegateReporterEvent(info, deletedItem);
589 facade_->shared_file_.RemovePrivateSharing(deletedItem,
590 facade_->receiver_group_list_);
592 SendError(info, static_cast<NotificationError>(ret));
597 void OnDelete(const IEventInfo& info,
598 shared_ptr<item::AbstractItem> deletedItem) override {
600 if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
601 list<shared_ptr<item::AbstractItem>> noti_list =
602 DBManager::GetNotificationList(info.GetOwner(), facade_->GetUid(info),
604 for (auto& i : noti_list) {
605 EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
606 DoDelete(event_info, i);
608 facade_->LaunchDefaultViewer(noti_list, NOTIFICATION_OP_DELETE);
610 int ret = DoDelete(info, deletedItem);
611 if (ret == ERROR_NONE)
612 facade_->LaunchDefaultViewer(deletedItem, NOTIFICATION_OP_DELETE);
616 list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
617 DBG("Get !!! %s", info.GetOwner().c_str());
618 list<shared_ptr<item::AbstractItem>> item_list;
619 uid_t uid = facade_->GetUid(info);
620 if (info.GetItemId().empty()) {
621 if (!info.GetChannel().empty()) {
623 item_list = DBManager::GetNotificationList(info.GetOwner(), uid, info.GetChannel());
624 facade_->TranslateText(item_list);
628 item_list = DBManager::GetNotificationList(info.GetOwner(), uid);
629 facade_->TranslateText(item_list);
634 item_list = DBManager::GetNotificationList(info.GetOwner(), info.GetItemId(), uid);
635 facade_->TranslateText(item_list);
640 void SetIndirectRequest(const IEventInfo& info,
641 list<shared_ptr<AbstractItem>> addedItem) {
642 for (auto& i : addedItem)
643 SetIndirectRequest(info, i);
646 void SetIndirectRequest(const IEventInfo& info,
647 shared_ptr<AbstractItem> addedItem) {
648 SetIndirectRequest(info, addedItem->GetAction());
650 if (addedItem->GetType() != AbstractItem::Type::Group)
653 auto item_group = static_pointer_cast<GroupItem>(addedItem);
654 auto children_list = item_group->GetChildren();
655 for (auto& i : children_list)
656 SetIndirectRequest(info, i);
659 void SetIndirectRequest(const IEventInfo& info, shared_ptr<AbstractAction>action) {
660 if (action == nullptr || action->GetType() != AbstractAction::Type::AppControl)
663 uid_t uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
664 if (uid < NORMAL_UID_BASE)
667 string owner = static_cast<const IEventInfoInternal&>(info).GetValidatedOwner();
668 app_control_h appcontrol = static_pointer_cast<AppControlAction>(action)->GetAppControl();
670 app_control_export_as_bundle(appcontrol, &b);
672 bundle_del(b, AUL_K_REQUEST_TYPE);
673 bundle_add(b, AUL_K_REQUEST_TYPE, "indirect-request");
675 bundle_del(b, AUL_K_ORG_CALLER_UID);
676 bundle_add(b, AUL_K_ORG_CALLER_UID, std::to_string(uid).c_str());
678 bundle_del(b, AUL_K_ORG_CALLER_APPID);
679 bundle_add(b, AUL_K_ORG_CALLER_APPID, owner.c_str());
681 pkgmgrinfo_appinfo_h handle;
682 int r = pkgmgrinfo_appinfo_get_usr_appinfo(owner.c_str(), uid, &handle);
683 if (r == PMINFO_R_OK) {
684 char* pkgid = nullptr;
685 pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
687 bundle_del(b, AUL_K_ORG_CALLER_PKGID);
688 bundle_add(b, AUL_K_ORG_CALLER_PKGID, pkgid);
690 pkgmgrinfo_appinfo_destroy_appinfo(handle);
693 app_control_import_from_bundle(appcontrol, b);
697 int ValidateUid(const IEventInfo& info, list<shared_ptr<AbstractItem>> addedItem) {
699 for (auto& i : addedItem) {
700 ret = ValidateUid(info, i);
701 if (ret != ERROR_NONE)
708 int ValidateUid(const IEventInfo& info, shared_ptr<AbstractItem> addedItem) {
709 uid_t validated_uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
710 uid_t item_uid = static_pointer_cast<IItemInfoInternal>
711 (addedItem->GetInfo())->GetUid();
713 if (validated_uid <= NORMAL_UID_BASE) {
714 static_pointer_cast<IItemInfoInternal>
715 (addedItem->GetInfo())->SetUid(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
716 } else if (validated_uid != item_uid) {
717 ERR("Invalid sender uid[%d] noti_uid[%d]", validated_uid, item_uid);
718 return ERROR_INVALID_PARAMETER;
725 DPMManager(std::unique_ptr<IEventSender> sender,
726 std::unique_ptr<IEventListener> listener)
727 : Manager(move(sender), move(listener)) {
731 HAPI int notification_ex_service_init(int restart_count) {
732 facade_ = new DPMFacade(
733 unique_ptr<Reporter>(
735 unique_ptr<DBusSender>(new DBusSender(Manager::GetPath())),
736 unique_ptr<DBusEventListener>(new DBusEventListener(Reporter::GetPath())))),
739 unique_ptr<DBusSender>(new DBusSender(Reporter::GetPath())),
740 unique_ptr<DBusEventListener>(new DBusEventListener(Manager::GetPath())))),
743 notification_init_default_viewer();
748 HAPI int notification_ex_service_fini() {
753 HAPI GDBusConnection* notification_ex_service_get_gdbus_connection() {
754 return DBusConnectionManager::GetInst().GetConnection();