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> ¬ification,
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> ¬ification, 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