• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "notification_local_live_view_subscriber_manager.h"
17 
18 #include <algorithm>
19 #include <memory>
20 #include <set>
21 
22 #include "ans_const_define.h"
23 #include "ans_inner_errors.h"
24 #include "ans_log_wrapper.h"
25 #include "ans_trace_wrapper.h"
26 #include "ipc_skeleton.h"
27 #include "notification_bundle_option.h"
28 #include "notification_button_option.h"
29 #include "os_account_manager.h"
30 #include "remote_death_recipient.h"
31 #include "bundle_manager_helper.h"
32 #include "advanced_notification_service.h"
33 
34 namespace OHOS {
35 namespace Notification {
36 struct NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord {
37     sptr<IAnsSubscriberLocalLiveView> subscriber {nullptr};
38     std::string bundleName {};
39     int32_t userId {SUBSCRIBE_USER_INIT};
40 };
41 
NotificationLocalLiveViewSubscriberManager()42 NotificationLocalLiveViewSubscriberManager::NotificationLocalLiveViewSubscriberManager()
43 {
44     ANS_LOGD("called");
45     notificationButtonQueue_ = std::make_shared<ffrt::queue>("NotificationLocalLiveViewMgr");
46     recipient_ = new (std::nothrow)
47         RemoteDeathRecipient(std::bind(&NotificationLocalLiveViewSubscriberManager::OnRemoteDied,
48             this, std::placeholders::_1));
49     if (recipient_ == nullptr) {
50         ANS_LOGE("null recipient");
51     }
52 }
53 
~NotificationLocalLiveViewSubscriberManager()54 NotificationLocalLiveViewSubscriberManager::~NotificationLocalLiveViewSubscriberManager()
55 {
56     ANS_LOGD("called");
57     buttonRecordList_.clear();
58 }
59 
ResetFfrtQueue()60 void NotificationLocalLiveViewSubscriberManager::ResetFfrtQueue()
61 {
62     if (notificationButtonQueue_ != nullptr) {
63         notificationButtonQueue_.reset();
64     }
65 }
66 
AddLocalLiveViewSubscriber(const sptr<IAnsSubscriberLocalLiveView> & subscriber,const sptr<NotificationSubscribeInfo> & subscribeInfo)67 ErrCode NotificationLocalLiveViewSubscriberManager::AddLocalLiveViewSubscriber(
68     const sptr<IAnsSubscriberLocalLiveView> &subscriber, const sptr<NotificationSubscribeInfo> &subscribeInfo)
69 {
70     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
71     if (subscriber == nullptr) {
72         ANS_LOGE("null subscriber");
73         return ERR_ANS_INVALID_PARAM;
74     }
75 
76     sptr<NotificationBundleOption> bundleOption;
77     std::string bundle;
78     int32_t callingUid = IPCSkeleton::GetCallingUid();
79     std::shared_ptr<BundleManagerHelper> bundleManager = BundleManagerHelper::GetInstance();
80     if (bundleManager != nullptr) {
81         bundle = bundleManager->GetBundleNameByUid(callingUid);
82     }
83     bundleOption = new (std::nothrow) NotificationBundleOption(bundle, callingUid);
84     ErrCode result = ERR_ANS_TASK_ERR;
85     if (bundleOption == nullptr) {
86         ANS_LOGE("null bundleOption");
87         return ERR_ANS_NO_MEMORY;
88     }
89     ANS_LOGD("Get userId succeeded, callingUid = <%{public}d> bundleName = <%{public}s>", callingUid, bundle.c_str());
90     if (notificationButtonQueue_ == nullptr) {
91         ANS_LOGE("null queue");
92         return result;
93     }
94     ANS_LOGD("start");
95     ffrt::task_handle handler =
96         notificationButtonQueue_->submit_h(std::bind([this, &subscriber, &bundleOption, &result]() {
97             ANS_LOGD("called");
98             result = this->AddSubscriberInner(subscriber, bundleOption);
99     }));
100     notificationButtonQueue_->wait(handler);
101     ANS_LOGD("end");
102     return result;
103 }
104 
RemoveLocalLiveViewSubscriber(const sptr<IAnsSubscriberLocalLiveView> & subscriber,const sptr<NotificationSubscribeInfo> & subscribeInfo)105 ErrCode NotificationLocalLiveViewSubscriberManager::RemoveLocalLiveViewSubscriber(
106     const sptr<IAnsSubscriberLocalLiveView> &subscriber, const sptr<NotificationSubscribeInfo> &subscribeInfo)
107 {
108     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
109     if (subscriber == nullptr) {
110         ANS_LOGE("null subscriber");
111         return ERR_ANS_INVALID_PARAM;
112     }
113 
114     ErrCode result = ERR_ANS_TASK_ERR;
115     if (notificationButtonQueue_ == nullptr) {
116         ANS_LOGE("null queue");
117         return result;
118     }
119     ANS_LOGD("start");
120     ffrt::task_handle handler = notificationButtonQueue_->submit_h(std::bind([this, &subscriber,
121         &subscribeInfo, &result]() {
122         ANS_LOGD("called");
123         result = this->RemoveSubscriberInner(subscriber, subscribeInfo);
124     }));
125     notificationButtonQueue_->wait(handler);
126     ANS_LOGD("end");
127     return result;
128 }
129 
NotifyTriggerResponse(const sptr<Notification> & notification,const sptr<NotificationButtonOption> & buttonOption)130 void NotificationLocalLiveViewSubscriberManager::NotifyTriggerResponse(const sptr<Notification> &notification,
131     const sptr<NotificationButtonOption> &buttonOption)
132 {
133     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
134     if (notificationButtonQueue_ == nullptr) {
135         ANS_LOGE("null queue");
136         return;
137     }
138     AppExecFwk::EventHandler::Callback NotifyTriggerResponseFunc =
139         std::bind(&NotificationLocalLiveViewSubscriberManager::NotifyTriggerResponseInner,
140             this, notification, buttonOption);
141 
142     ANS_LOGD("start");
143     notificationButtonQueue_->submit(NotifyTriggerResponseFunc);
144     ANS_LOGD("end");
145 }
146 
OnRemoteDied(const wptr<IRemoteObject> & object)147 void NotificationLocalLiveViewSubscriberManager::OnRemoteDied(const wptr<IRemoteObject> &object)
148 {
149     ANS_LOGD("called");
150     if (notificationButtonQueue_ == nullptr) {
151         ANS_LOGE("null queue");
152         return;
153     }
154     ffrt::task_handle handler = notificationButtonQueue_->submit_h(std::bind([this, object]() {
155         ANS_LOGD("called");
156         std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(object);
157         if (record != nullptr) {
158             ANS_LOGI("removed. uid = %{public}d", record->userId);
159             AdvancedNotificationService::GetInstance()->RemoveSystemLiveViewNotifications(
160                 record->bundleName, record->userId);
161             buttonRecordList_.remove(record);
162         }
163     }));
164     ANS_LOGD("start");
165     notificationButtonQueue_->wait(handler);
166     ANS_LOGD("end");
167 }
168 
FindSubscriberRecord(const wptr<IRemoteObject> & object)169 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::FindSubscriberRecord(
170     const wptr<IRemoteObject> &object)
171 {
172     auto iter = buttonRecordList_.begin();
173 
174     for (; iter != buttonRecordList_.end(); iter++) {
175         if ((*iter)->subscriber->AsObject() == object) {
176             return (*iter);
177         }
178     }
179     return nullptr;
180 }
181 
FindSubscriberRecord(const sptr<IAnsSubscriberLocalLiveView> & subscriber)182 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::FindSubscriberRecord(
183     const sptr<IAnsSubscriberLocalLiveView> &subscriber)
184 {
185     auto iter = buttonRecordList_.begin();
186 
187     for (; iter != buttonRecordList_.end(); iter++) {
188         if ((*iter)->subscriber->AsObject() == subscriber->AsObject()) {
189             return (*iter);
190         }
191     }
192     return nullptr;
193 }
194 
CreateSubscriberRecord(const sptr<IAnsSubscriberLocalLiveView> & subscriber,const sptr<NotificationBundleOption> & bundleOption)195 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::CreateSubscriberRecord(
196     const sptr<IAnsSubscriberLocalLiveView> &subscriber,
197     const sptr<NotificationBundleOption> &bundleOption)
198 {
199     std::shared_ptr<LocalLiveViewSubscriberRecord> record = std::make_shared<LocalLiveViewSubscriberRecord>();
200     // set bundleName and uid
201     if (record != nullptr) {
202         record->subscriber = subscriber;
203         record->bundleName = bundleOption->GetBundleName();
204         record->userId = bundleOption->GetUid();
205         ANS_LOGD("Get userId succeeded, callingUid = <%{public}d> bundleName = <%{public}s>",
206             record->userId, record->bundleName.c_str());
207     }
208     return record;
209 }
210 
211 
AddSubscriberInner(const sptr<IAnsSubscriberLocalLiveView> & subscriber,const sptr<NotificationBundleOption> & bundleOption)212 ErrCode NotificationLocalLiveViewSubscriberManager::AddSubscriberInner(
213     const sptr<IAnsSubscriberLocalLiveView> &subscriber, const sptr<NotificationBundleOption> &bundleOption)
214 {
215     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
216     std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(subscriber);
217     if (record == nullptr) {
218         record = CreateSubscriberRecord(subscriber, bundleOption);
219         if (record == nullptr) {
220             ANS_LOGE("null record");
221             return ERR_ANS_NO_MEMORY;
222         }
223         buttonRecordList_.push_back(record);
224 
225         record->subscriber->AsObject()->AddDeathRecipient(recipient_);
226 
227         record->subscriber->OnConnected();
228         ANS_LOGI("subscriber is connected.");
229     }
230 
231     return ERR_OK;
232 }
233 
RemoveSubscriberInner(const sptr<IAnsSubscriberLocalLiveView> & subscriber,const sptr<NotificationSubscribeInfo> & subscribeInfo)234 ErrCode NotificationLocalLiveViewSubscriberManager::RemoveSubscriberInner(
235     const sptr<IAnsSubscriberLocalLiveView> &subscriber, const sptr<NotificationSubscribeInfo> &subscribeInfo)
236 {
237     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
238     std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(subscriber);
239 
240     if (record == nullptr) {
241         ANS_LOGE("null record");
242         return ERR_ANS_INVALID_PARAM;
243     }
244 
245     record->subscriber->AsObject()->RemoveDeathRecipient(recipient_);
246 
247     buttonRecordList_.remove(record);
248 
249     record->subscriber->OnDisconnected();
250     ANS_LOGI("subscriber is disconnected.");
251 
252     return ERR_OK;
253 }
254 
NotifyTriggerResponseInner(const sptr<Notification> & notification,const sptr<NotificationButtonOption> buttonOption)255 void NotificationLocalLiveViewSubscriberManager::NotifyTriggerResponseInner(
256     const sptr<Notification> &notification, const sptr<NotificationButtonOption> buttonOption)
257 {
258     ANS_LOGD("called");
259     NOTIFICATION_HITRACE(HITRACE_TAG_NOTIFICATION);
260 
261     int32_t sendUserId;
262     std::string bundleName;
263     if (notification->GetNotificationRequestPoint()->GetAgentBundle() != nullptr) {
264         sendUserId = notification->GetNotificationRequestPoint()->GetAgentBundle()->GetUid();
265         bundleName = notification->GetNotificationRequestPoint()->GetAgentBundle()->GetBundleName();
266     } else {
267         sendUserId = notification->GetUid();
268         bundleName = notification->GetBundleName();
269     }
270     ANS_LOGD("sendUserId <%{public}d>, bundlename <%{public}s>", sendUserId, bundleName.c_str());
271 
272     for (auto record : buttonRecordList_) {
273         ANS_LOGD("record->userId = <%{public}d>, bundlename <%{public}s>", record->userId, record->bundleName.c_str());
274         if (record->bundleName == bundleName && record->userId == sendUserId) {
275             record->subscriber->OnResponse(notification->GetId(), buttonOption);
276         }
277     }
278 }
279 
IsSystemUser(int32_t userId)280 bool NotificationLocalLiveViewSubscriberManager::IsSystemUser(int32_t userId)
281 {
282     return ((userId >= SUBSCRIBE_USER_SYSTEM_BEGIN) && (userId <= SUBSCRIBE_USER_SYSTEM_END));
283 }
284 
285 }  // namespace Notification
286 }  // namespace OHOS
287