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> &notification,
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> &notification, 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