1 /*
2 * Copyright (c) 2021-2022 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_watchdog.h"
26 #include "hitrace_meter_adapter.h"
27 #include "ipc_skeleton.h"
28 #include "notification_bundle_option.h"
29 #include "notification_button_option.h"
30 #include "os_account_manager.h"
31 #include "remote_death_recipient.h"
32 #include "bundle_manager_helper.h"
33 #include "advanced_notification_service.h"
34
35 namespace OHOS {
36 namespace Notification {
37 struct NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord {
38 sptr<AnsSubscriberLocalLiveViewInterface> subscriber {nullptr};
39 std::string bundleName {};
40 int32_t userId {SUBSCRIBE_USER_INIT};
41 };
42
NotificationLocalLiveViewSubscriberManager()43 NotificationLocalLiveViewSubscriberManager::NotificationLocalLiveViewSubscriberManager()
44 {
45 ANS_LOGI("constructor");
46 notificationButtonQueue_ = std::make_shared<ffrt::queue>("NotificationLocalLiveViewMgr");
47 recipient_ = new (std::nothrow)
48 RemoteDeathRecipient(std::bind(&NotificationLocalLiveViewSubscriberManager::OnRemoteDied,
49 this, std::placeholders::_1));
50 if (recipient_ == nullptr) {
51 ANS_LOGE("Failed to create RemoteDeathRecipient instance");
52 }
53 }
54
~NotificationLocalLiveViewSubscriberManager()55 NotificationLocalLiveViewSubscriberManager::~NotificationLocalLiveViewSubscriberManager()
56 {
57 ANS_LOGI("deconstructor");
58 buttonRecordList_.clear();
59 }
60
ResetFfrtQueue()61 void NotificationLocalLiveViewSubscriberManager::ResetFfrtQueue()
62 {
63 if (notificationButtonQueue_ != nullptr) {
64 notificationButtonQueue_.reset();
65 }
66 }
67
AddLocalLiveViewSubscriber(const sptr<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationSubscribeInfo> & subscribeInfo)68 ErrCode NotificationLocalLiveViewSubscriberManager::AddLocalLiveViewSubscriber(
69 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber, const sptr<NotificationSubscribeInfo> &subscribeInfo)
70 {
71 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
72 if (subscriber == nullptr) {
73 ANS_LOGE("subscriber is null.");
74 return ERR_ANS_INVALID_PARAM;
75 }
76
77 sptr<NotificationBundleOption> bundleOption;
78 std::string bundle;
79 int32_t callingUid = IPCSkeleton::GetCallingUid();
80 std::shared_ptr<BundleManagerHelper> bundleManager = BundleManagerHelper::GetInstance();
81 if (bundleManager != nullptr) {
82 bundle = bundleManager->GetBundleNameByUid(callingUid);
83 }
84 bundleOption = new (std::nothrow) NotificationBundleOption(bundle, callingUid);
85 ErrCode result = ERR_ANS_TASK_ERR;
86 if (bundleOption == nullptr) {
87 ANS_LOGE("Failed to create NotificationBundleOption instance");
88 return ERR_ANS_NO_MEMORY;
89 }
90 ANS_LOGD("Get userId succeeded, callingUid = <%{public}d> bundleName = <%{public}s>", callingUid, bundle.c_str());
91 if (notificationButtonQueue_ == nullptr) {
92 ANS_LOGE("queue is nullptr");
93 return result;
94 }
95 ANS_LOGD("ffrt start!");
96 ffrt::task_handle handler =
97 notificationButtonQueue_->submit_h(std::bind([this, &subscriber, &bundleOption, &result]() {
98 ANS_LOGD("ffrt enter!");
99 result = this->AddSubscriberInner(subscriber, bundleOption);
100 }));
101 notificationButtonQueue_->wait(handler);
102 ANS_LOGD("ffrt end!");
103 return result;
104 }
105
RemoveLocalLiveViewSubscriber(const sptr<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationSubscribeInfo> & subscribeInfo)106 ErrCode NotificationLocalLiveViewSubscriberManager::RemoveLocalLiveViewSubscriber(
107 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber, const sptr<NotificationSubscribeInfo> &subscribeInfo)
108 {
109 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
110 if (subscriber == nullptr) {
111 ANS_LOGE("subscriber is null.");
112 return ERR_ANS_INVALID_PARAM;
113 }
114
115 ErrCode result = ERR_ANS_TASK_ERR;
116 if (notificationButtonQueue_ == nullptr) {
117 ANS_LOGE("queue is nullptr");
118 return result;
119 }
120 ANS_LOGD("ffrt start!");
121 ffrt::task_handle handler = notificationButtonQueue_->submit_h(std::bind([this, &subscriber,
122 &subscribeInfo, &result]() {
123 ANS_LOGD("ffrt enter!");
124 result = this->RemoveSubscriberInner(subscriber, subscribeInfo);
125 }));
126 notificationButtonQueue_->wait(handler);
127 ANS_LOGD("ffrt end!");
128 return result;
129 }
130
NotifyTriggerResponse(const sptr<Notification> & notification,const sptr<NotificationButtonOption> & buttonOption)131 void NotificationLocalLiveViewSubscriberManager::NotifyTriggerResponse(const sptr<Notification> ¬ification,
132 const sptr<NotificationButtonOption> &buttonOption)
133 {
134 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
135 if (notificationButtonQueue_ == nullptr) {
136 ANS_LOGE("queue is nullptr");
137 return;
138 }
139 AppExecFwk::EventHandler::Callback NotifyTriggerResponseFunc =
140 std::bind(&NotificationLocalLiveViewSubscriberManager::NotifyTriggerResponseInner,
141 this, notification, buttonOption);
142
143 ANS_LOGD("ffrt start!");
144 notificationButtonQueue_->submit(NotifyTriggerResponseFunc);
145 ANS_LOGD("ffrt end!");
146 }
147
OnRemoteDied(const wptr<IRemoteObject> & object)148 void NotificationLocalLiveViewSubscriberManager::OnRemoteDied(const wptr<IRemoteObject> &object)
149 {
150 ANS_LOGI("OnRemoteDied");
151 if (notificationButtonQueue_ == nullptr) {
152 ANS_LOGE("queue is nullptr");
153 return;
154 }
155 ffrt::task_handle handler = notificationButtonQueue_->submit_h(std::bind([this, object]() {
156 ANS_LOGD("ffrt enter!");
157 std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(object);
158 if (record != nullptr) {
159 ANS_LOGI("subscriber removed . userId = %{public}d", record->userId);
160 AdvancedNotificationService::GetInstance()->RemoveSystemLiveViewNotifications(
161 record->bundleName, record->userId);
162 buttonRecordList_.remove(record);
163 }
164 }));
165 ANS_LOGD("ffrt start!");
166 notificationButtonQueue_->wait(handler);
167 ANS_LOGD("ffrt end!");
168 }
169
FindSubscriberRecord(const wptr<IRemoteObject> & object)170 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::FindSubscriberRecord(
171 const wptr<IRemoteObject> &object)
172 {
173 auto iter = buttonRecordList_.begin();
174
175 for (; iter != buttonRecordList_.end(); iter++) {
176 if ((*iter)->subscriber->AsObject() == object) {
177 return (*iter);
178 }
179 }
180 return nullptr;
181 }
182
FindSubscriberRecord(const sptr<AnsSubscriberLocalLiveViewInterface> & subscriber)183 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::FindSubscriberRecord(
184 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber)
185 {
186 auto iter = buttonRecordList_.begin();
187
188 for (; iter != buttonRecordList_.end(); iter++) {
189 if ((*iter)->subscriber->AsObject() == subscriber->AsObject()) {
190 return (*iter);
191 }
192 }
193 return nullptr;
194 }
195
CreateSubscriberRecord(const sptr<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationBundleOption> & bundleOption)196 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::CreateSubscriberRecord(
197 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber,
198 const sptr<NotificationBundleOption> &bundleOption)
199 {
200 std::shared_ptr<LocalLiveViewSubscriberRecord> record = std::make_shared<LocalLiveViewSubscriberRecord>();
201 // set bundleName and uid
202 if (record != nullptr) {
203 record->subscriber = subscriber;
204 record->bundleName = bundleOption->GetBundleName();
205 record->userId = bundleOption->GetUid();
206 ANS_LOGD("Get userId succeeded, callingUid = <%{public}d> bundleName = <%{public}s>",
207 record->userId, record->bundleName.c_str());
208 }
209 return record;
210 }
211
212
AddSubscriberInner(const sptr<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationBundleOption> & bundleOption)213 ErrCode NotificationLocalLiveViewSubscriberManager::AddSubscriberInner(
214 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber, const sptr<NotificationBundleOption> &bundleOption)
215 {
216 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
217 std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(subscriber);
218 if (record == nullptr) {
219 record = CreateSubscriberRecord(subscriber, bundleOption);
220 if (record == nullptr) {
221 ANS_LOGE("CreateSubscriberRecord failed.");
222 return ERR_ANS_NO_MEMORY;
223 }
224 buttonRecordList_.push_back(record);
225
226 record->subscriber->AsObject()->AddDeathRecipient(recipient_);
227
228 record->subscriber->OnConnected();
229 ANS_LOGI("subscriber is connected.");
230 }
231
232 return ERR_OK;
233 }
234
RemoveSubscriberInner(const sptr<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationSubscribeInfo> & subscribeInfo)235 ErrCode NotificationLocalLiveViewSubscriberManager::RemoveSubscriberInner(
236 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber, const sptr<NotificationSubscribeInfo> &subscribeInfo)
237 {
238 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
239 std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(subscriber);
240
241 if (record == nullptr) {
242 ANS_LOGE("subscriber not found.");
243 return ERR_ANS_INVALID_PARAM;
244 }
245
246 record->subscriber->AsObject()->RemoveDeathRecipient(recipient_);
247
248 buttonRecordList_.remove(record);
249
250 record->subscriber->OnDisconnected();
251 ANS_LOGI("subscriber is disconnected.");
252
253 return ERR_OK;
254 }
255
NotifyTriggerResponseInner(const sptr<Notification> & notification,const sptr<NotificationButtonOption> buttonOption)256 void NotificationLocalLiveViewSubscriberManager::NotifyTriggerResponseInner(
257 const sptr<Notification> ¬ification, const sptr<NotificationButtonOption> buttonOption)
258 {
259 ANS_LOGD("ffrt enter!");
260 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
261
262 int32_t sendUserId;
263 std::string bundleName;
264 if (notification->GetNotificationRequestPoint()->GetAgentBundle() != nullptr) {
265 sendUserId = notification->GetNotificationRequestPoint()->GetAgentBundle()->GetUid();
266 bundleName = notification->GetNotificationRequestPoint()->GetAgentBundle()->GetBundleName();
267 } else {
268 sendUserId = notification->GetUid();
269 bundleName = notification->GetBundleName();
270 }
271 ANS_LOGD("%{public}s sendUserId <%{public}d>, bundlename <%{public}s>",
272 __FUNCTION__, sendUserId, bundleName.c_str());
273
274 for (auto record : buttonRecordList_) {
275 ANS_LOGD("%{public}s record->userId = <%{public}d>, bundlename <%{public}s>",
276 __FUNCTION__, record->userId, record->bundleName.c_str());
277 if (record->bundleName == bundleName && record->userId == sendUserId) {
278 record->subscriber->OnResponse(notification->GetId(), buttonOption);
279 }
280 }
281 }
282
IsSystemUser(int32_t userId)283 bool NotificationLocalLiveViewSubscriberManager::IsSystemUser(int32_t userId)
284 {
285 return ((userId >= SUBSCRIBE_USER_SYSTEM_BEGIN) && (userId <= SUBSCRIBE_USER_SYSTEM_END));
286 }
287
288 } // namespace Notification
289 } // namespace OHOS
290