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_LOGI("ffrt start!");
96 ffrt::task_handle handler =
97 notificationButtonQueue_->submit_h(std::bind([this, &subscriber, &bundleOption, &result]() {
98 ANS_LOGI("ffrt enter!");
99 result = this->AddSubscriberInner(subscriber, bundleOption);
100 }));
101 notificationButtonQueue_->wait(handler);
102 ANS_LOGI("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_LOGI("ffrt start!");
121 ffrt::task_handle handler = notificationButtonQueue_->submit_h(std::bind([this, &subscriber,
122 &subscribeInfo, &result]() {
123 ANS_LOGI("ffrt enter!");
124 result = this->RemoveSubscriberInner(subscriber, subscribeInfo);
125 }));
126 notificationButtonQueue_->wait(handler);
127 ANS_LOGI("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_LOGI("ffrt start!");
144 notificationButtonQueue_->submit(NotifyTriggerResponseFunc);
145 ANS_LOGI("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_LOGI("ffrt enter!");
157 std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(object);
158 if (record != nullptr) {
159 ANS_LOGW("subscriber removed.");
160 AdvancedNotificationService::GetInstance()->RemoveSystemLiveViewNotifications(record->bundleName);
161 buttonRecordList_.remove(record);
162 }
163 }));
164 ANS_LOGI("ffrt start!");
165 notificationButtonQueue_->wait(handler);
166 ANS_LOGI("ffrt 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<AnsSubscriberLocalLiveViewInterface> & subscriber)182 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::FindSubscriberRecord(
183 const sptr<AnsSubscriberLocalLiveViewInterface> &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<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationBundleOption> & bundleOption)195 std::shared_ptr<NotificationLocalLiveViewSubscriberManager::LocalLiveViewSubscriberRecord> NotificationLocalLiveViewSubscriberManager::CreateSubscriberRecord(
196 const sptr<AnsSubscriberLocalLiveViewInterface> &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<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationBundleOption> & bundleOption)212 ErrCode NotificationLocalLiveViewSubscriberManager::AddSubscriberInner(
213 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber, const sptr<NotificationBundleOption> &bundleOption)
214 {
215 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
216 std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(subscriber);
217 if (record == nullptr) {
218 record = CreateSubscriberRecord(subscriber, bundleOption);
219 if (record == nullptr) {
220 ANS_LOGE("CreateSubscriberRecord failed.");
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<AnsSubscriberLocalLiveViewInterface> & subscriber,const sptr<NotificationSubscribeInfo> & subscribeInfo)234 ErrCode NotificationLocalLiveViewSubscriberManager::RemoveSubscriberInner(
235 const sptr<AnsSubscriberLocalLiveViewInterface> &subscriber, const sptr<NotificationSubscribeInfo> &subscribeInfo)
236 {
237 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
238 std::shared_ptr<LocalLiveViewSubscriberRecord> record = FindSubscriberRecord(subscriber);
239
240 if (record == nullptr) {
241 ANS_LOGE("subscriber not found.");
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_LOGI("ffrt enter!");
259 HITRACE_METER_NAME(HITRACE_TAG_NOTIFICATION, __PRETTY_FUNCTION__);
260
261 int32_t sendUserId = notification->GetUid();
262 std::string bundleName = "";
263 if (notification->GetNotificationRequest().IsAgentNotification()) {
264 bundleName = notification->GetCreateBundle();
265 } else {
266 bundleName = notification->GetBundleName();
267 }
268 ANS_LOGD("%{public}s notification->GetUserId <%{public}d>, bundlename <%{public}s>",
269 __FUNCTION__, notification->GetUid(), bundleName.c_str());
270
271 for (auto record : buttonRecordList_) {
272 ANS_LOGD("%{public}s record->userId = <%{public}d>, bundlename <%{public}s>",
273 __FUNCTION__, 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