• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &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_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> &notification, 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