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 if(!info.GetItemId().empty()) /* The item_id is actually an app_id. */
371 noti_list = DBManager::GetNotificationList(
372 info.GetItemId(), facade_->GetUid(info), "");
374 noti_list = DBManager::GetNotificationList(
375 facade_->GetUid(info), info.GetChannel());
377 EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
378 for (auto& i : noti_list)
379 DoDelete(event_info, i);
381 DoDelete(info, deletedItem);
385 void OnEvent(const IEventInfo& info,
386 list<shared_ptr<item::AbstractItem>> noti_list) override {
387 LOGI("Event received (%d) !!", (int)info.GetEventType());
388 int type = info.GetEventType();
389 if (type == IEventInfo::EventType::DeleteAll) {
390 OnDelete(info, nullptr);
392 } else if (type == IEventInfo::EventType::Register) {
397 for (auto& i : noti_list) {
399 case IEventInfo::EventType::Update:
402 case IEventInfo::EventType::Delete:
411 list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
412 list<shared_ptr<item::AbstractItem>> item_list;
414 DBG("Get report !!! %s", info.GetItemId().c_str());
415 item_list = DBManager::GetNotificationList(facade_->GetUid(info),
416 ((const IEventInfoInternal&)info).GetChannel().c_str());
418 facade_->shared_file_.SetPrivateSharing(item_list,
419 facade_->receiver_group_list_);
421 facade_->TranslateText(item_list);
426 int OnRequestNumber(const IEventInfo& info) override {
427 DBG("Get count !!! %s", info.GetItemId().c_str());
428 return DBManager::GetNotificationList(facade_->GetUid(info)).size();
431 int UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
434 int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
435 DBG("try update hide app_id(%s) sender(%s) uid(%s)",
436 updatedItem->GetId().c_str(),
437 updatedItem->GetSenderAppId().c_str(), string(to_string(uid)).c_str());
438 string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
439 list<string> updated_hide_list = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
441 /* Check new hide app */
442 auto noti = facade_->hide_map_.find(map_key);
443 if (noti == facade_->hide_map_.end()) {
444 if (updated_hide_list.size() > 0) {
445 for (auto& i : updated_hide_list)
446 hide_list += i + ";";
448 ret = DBManager::UpdateHideList(updatedItem, hide_list);
449 if (ret != ERROR_NONE)
452 facade_->hide_map_[map_key] = hide_list;
455 DBG("Empty hide viewer list");
456 return ERROR_NOT_EXIST_ID;
460 /* Check new hide app */
461 hide_list = noti->second;
462 for (auto& i : updated_hide_list) {
463 if (hide_list.find(i + ";") == string::npos) {
464 string new_hide_list = hide_list + i + ";";
465 ret = DBManager::UpdateHideList(updatedItem, new_hide_list);
466 if (ret != ERROR_NONE)
469 facade_->hide_map_[map_key] = new_hide_list;
474 return ERROR_NOT_EXIST_ID;
477 void OnRegister(const IEventInfo& info) {
478 std::string receiver_group = info.GetChannel();
479 std::string appid = info.GetOwner();
481 std::multimap<std::string,std::string>::iterator it;
482 for(auto receiver_group_ : facade_->receiver_group_list_) {
483 if (receiver_group_.first.compare(receiver_group) == 0 &&
484 receiver_group_.second.compare(appid) == 0)
488 facade_->receiver_group_list_.insert(make_pair(receiver_group, appid));
492 DPMReporter(std::unique_ptr<IEventSender> sender,
493 std::unique_ptr<IEventListener> listener)
494 : Reporter(move(sender), move(listener)) {
498 class DPMManager : public Manager {
500 void UpdateHideApp(shared_ptr<item::AbstractItem> updatedItem) {
502 int uid = static_pointer_cast<IItemInfoInternal>(updatedItem->GetInfo())->GetUid();
503 string map_key = updatedItem->GetId() + updatedItem->GetSenderAppId() + string(to_string(uid));
504 list<string> updated_hide_list =
505 static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->GetHideViewerList();
507 auto noti = facade_->hide_map_.find(map_key);
508 if (noti == facade_->hide_map_.end())
511 /* hide app list synchronization */
512 hide_list = noti->second;
513 istringstream stream(hide_list);
516 while (getline(stream, hide_app_id, ';')) {
517 list<string>::iterator iter = std::find(updated_hide_list.begin(),
518 updated_hide_list.end(), hide_app_id);
519 if (iter == updated_hide_list.end())
520 static_pointer_cast<item::IItemInfoInternal>(updatedItem->GetInfo())->AddHideViewer(hide_app_id);
524 void OnAdd(const IEventInfo& info,
525 list<shared_ptr<item::AbstractItem>> addedItem) override {
529 ret = ValidateUid(info, addedItem);
530 if (ret != ERROR_NONE) {
531 SendError(info, static_cast<NotificationError>(ret));
535 SetIndirectRequest(info, addedItem);
537 if (facade_->CheckAllowedToNotify(addedItem) == false)
540 facade_->SetDoNoDisturbPolicy(addedItem);
541 facade_->SetPopUpPolicy(addedItem);
543 ret = DBManager::InsertNotification(addedItem);
544 if (ret == ERROR_NONE) {
545 facade_->shared_file_.SetPrivateSharing(addedItem,
546 facade_->receiver_group_list_);
547 facade_->TranslateText(addedItem);
548 facade_->DelegateReporterEvent(info, addedItem);
549 facade_->LaunchDefaultViewer(addedItem, NOTIFICATION_OP_INSERT);
551 DBG("SendError !!!");
552 SendError(info, static_cast<NotificationError>(ret));
556 void OnUpdate(const IEventInfo& info,
557 shared_ptr<item::AbstractItem> updatedItem) override {
561 ret = ValidateUid(info, updatedItem);
562 if (ret != ERROR_NONE) {
563 SendError(info, static_cast<NotificationError>(ret));
567 UpdateHideApp(updatedItem);
568 SetIndirectRequest(info, updatedItem);
570 if (facade_->CheckAllowedToNotify(updatedItem) == false)
573 facade_->SetDoNoDisturbPolicy(updatedItem);
574 facade_->SetPopUpPolicy(updatedItem);
576 ret = DBManager::UpdateNotification(updatedItem);
577 if (ret == ERROR_NONE) {
578 facade_->shared_file_.UpdatePrivateSharing(updatedItem,
579 facade_->receiver_group_list_);
580 facade_->TranslateText(updatedItem);
581 facade_->DelegateReporterEvent(info, updatedItem);
582 facade_->LaunchDefaultViewer(updatedItem, NOTIFICATION_OP_UPDATE);
584 SendError(info, static_cast<NotificationError>(ret));
588 int DoDelete(const IEventInfo& info,
589 shared_ptr<item::AbstractItem> deletedItem) {
592 ret = DBManager::DeleteNotification(deletedItem);
593 if (ret == ERROR_NONE) {
594 facade_->DelegateReporterEvent(info, deletedItem);
595 facade_->shared_file_.RemovePrivateSharing(deletedItem,
596 facade_->receiver_group_list_);
598 SendError(info, static_cast<NotificationError>(ret));
603 void OnDelete(const IEventInfo& info,
604 shared_ptr<item::AbstractItem> deletedItem) override {
606 if (info.GetEventType() == IEventInfo::EventType::DeleteAll) {
607 list<shared_ptr<item::AbstractItem>> noti_list =
608 DBManager::GetNotificationList(info.GetOwner(), facade_->GetUid(info),
610 for (auto& i : noti_list) {
611 EventInfo event_info(EventInfo::Delete, info.GetOwner(), info.GetChannel());
612 DoDelete(event_info, i);
614 facade_->LaunchDefaultViewer(noti_list, NOTIFICATION_OP_DELETE);
616 int ret = DoDelete(info, deletedItem);
617 if (ret == ERROR_NONE)
618 facade_->LaunchDefaultViewer(deletedItem, NOTIFICATION_OP_DELETE);
622 list<shared_ptr<item::AbstractItem>> OnRequestEvent(const IEventInfo& info) override {
623 DBG("Get !!! %s", info.GetOwner().c_str());
624 list<shared_ptr<item::AbstractItem>> item_list;
625 uid_t uid = facade_->GetUid(info);
626 if (info.GetItemId().empty()) {
627 if (!info.GetChannel().empty()) {
629 item_list = DBManager::GetNotificationList(info.GetOwner(), uid, info.GetChannel());
630 facade_->TranslateText(item_list);
634 item_list = DBManager::GetNotificationList(info.GetOwner(), uid);
635 facade_->TranslateText(item_list);
640 item_list = DBManager::GetNotificationList(info.GetOwner(), info.GetItemId(), uid);
641 facade_->TranslateText(item_list);
646 void SetIndirectRequest(const IEventInfo& info,
647 list<shared_ptr<AbstractItem>> addedItem) {
648 for (auto& i : addedItem)
649 SetIndirectRequest(info, i);
652 void SetIndirectRequest(const IEventInfo& info,
653 shared_ptr<AbstractItem> addedItem) {
654 SetIndirectRequest(info, addedItem->GetAction());
656 if (addedItem->GetType() != AbstractItem::Type::Group)
659 auto item_group = static_pointer_cast<GroupItem>(addedItem);
660 auto children_list = item_group->GetChildren();
661 for (auto& i : children_list)
662 SetIndirectRequest(info, i);
665 void SetIndirectRequest(const IEventInfo& info, shared_ptr<AbstractAction>action) {
666 if (action == nullptr || action->GetType() != AbstractAction::Type::AppControl)
669 uid_t uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
670 if (uid < NORMAL_UID_BASE)
673 string owner = static_cast<const IEventInfoInternal&>(info).GetValidatedOwner();
674 app_control_h appcontrol = static_pointer_cast<AppControlAction>(action)->GetAppControl();
676 app_control_export_as_bundle(appcontrol, &b);
678 bundle_del(b, AUL_K_REQUEST_TYPE);
679 bundle_add(b, AUL_K_REQUEST_TYPE, "indirect-request");
681 bundle_del(b, AUL_K_ORG_CALLER_UID);
682 bundle_add(b, AUL_K_ORG_CALLER_UID, std::to_string(uid).c_str());
684 bundle_del(b, AUL_K_ORG_CALLER_APPID);
685 bundle_add(b, AUL_K_ORG_CALLER_APPID, owner.c_str());
687 pkgmgrinfo_appinfo_h handle;
688 int r = pkgmgrinfo_appinfo_get_usr_appinfo(owner.c_str(), uid, &handle);
689 if (r == PMINFO_R_OK) {
690 char* pkgid = nullptr;
691 pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
693 bundle_del(b, AUL_K_ORG_CALLER_PKGID);
694 bundle_add(b, AUL_K_ORG_CALLER_PKGID, pkgid);
696 pkgmgrinfo_appinfo_destroy_appinfo(handle);
699 app_control_import_from_bundle(appcontrol, b);
703 int ValidateUid(const IEventInfo& info, list<shared_ptr<AbstractItem>> addedItem) {
705 for (auto& i : addedItem) {
706 ret = ValidateUid(info, i);
707 if (ret != ERROR_NONE)
714 int ValidateUid(const IEventInfo& info, shared_ptr<AbstractItem> addedItem) {
715 uid_t validated_uid = static_cast<const IEventInfoInternal&>(info).GetValidatedUid();
716 uid_t item_uid = static_pointer_cast<IItemInfoInternal>
717 (addedItem->GetInfo())->GetUid();
719 if (validated_uid <= NORMAL_UID_BASE) {
720 static_pointer_cast<IItemInfoInternal>
721 (addedItem->GetInfo())->SetUid(tzplatform_getuid(TZ_SYS_DEFAULT_USER));
722 } else if (validated_uid != item_uid) {
723 ERR("Invalid sender uid[%d] noti_uid[%d]", validated_uid, item_uid);
724 return ERROR_INVALID_PARAMETER;
731 DPMManager(std::unique_ptr<IEventSender> sender,
732 std::unique_ptr<IEventListener> listener)
733 : Manager(move(sender), move(listener)) {
737 HAPI int notification_ex_service_init(int restart_count) {
738 facade_ = new DPMFacade(
739 unique_ptr<Reporter>(
741 unique_ptr<DBusSender>(new DBusSender(Manager::GetPath())),
742 unique_ptr<DBusEventListener>(new DBusEventListener(Reporter::GetPath())))),
745 unique_ptr<DBusSender>(new DBusSender(Reporter::GetPath())),
746 unique_ptr<DBusEventListener>(new DBusEventListener(Manager::GetPath())))),
749 notification_init_default_viewer();
754 HAPI int notification_ex_service_fini() {
759 HAPI GDBusConnection* notification_ex_service_get_gdbus_connection() {
760 return DBusConnectionManager::GetInst().GetConnection();