• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2023 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 "advanced_notification_service.h"
17 
18 #include "cpp/task.h"
19 #include "errors.h"
20 #include "ans_inner_errors.h"
21 #include "notification_constant.h"
22 #include "notification_record.h"
23 #include "notification_request.h"
24 #include "want_params_wrapper.h"
25 #include "notification_preferences.h"
26 #include "access_token_helper.h"
27 #include "accesstoken_kit.h"
28 #include "ipc_skeleton.h"
29 #include "image_source.h"
30 #include "os_account_manager_helper.h"
31 #include "time_service_client.h"
32 #include "notification_timer_info.h"
33 #include "advanced_notification_inline.h"
34 #include <cstdint>
35 #include <memory>
36 #include "notification_analytics_util.h"
37 #include "aes_gcm_helper.h"
38 
39 namespace OHOS {
40 namespace Notification {
41 const std::string LOCK_SCREEN_PICTURE_TAG = "lock_screen_picture";
42 const std::string PROGRESS_VALUE = "progressValue";
43 constexpr int32_t BGTASK_UID = 3051;
44 constexpr int32_t TYPE_CODE_DOWNLOAD = 8;
RecoverLiveViewFromDb(int32_t userId)45 void AdvancedNotificationService::RecoverLiveViewFromDb(int32_t userId)
46 {
47     if (notificationSvrQueue_ == nullptr) {
48         ANS_LOGE("notificationSvrQueue_ is nullptr.");
49         return;
50     }
51     ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([=]() {
52         ANS_LOGI("Start recover live view from db. userId:%{public}d", userId);
53         std::vector<NotificationRequestDb> requestsdb;
54         if (GetBatchNotificationRequestsFromDb(requestsdb, userId) != ERR_OK) {
55             ANS_LOGE("Get liveView from db failed.");
56             return;
57         }
58         ANS_LOGI("The number of live views to recover: %{public}zu.", requestsdb.size());
59         std::vector<std::string> keys;
60         for (const auto &requestObj : requestsdb) {
61             if (!IsLiveViewCanRecover(requestObj.request)) {
62                 int32_t userId = requestObj.request->GetReceiverUserId();
63                 keys.emplace_back(requestObj.request->GetBaseKey(""));
64                 if (DoubleDeleteNotificationFromDb(requestObj.request->GetKey(),
65                     requestObj.request->GetSecureKey(), userId) != ERR_OK) {
66                     ANS_LOGE("Delete notification failed.");
67                 }
68                 continue;
69             }
70 
71             auto record = std::make_shared<NotificationRecord>();
72             record->isNeedFlowCtrl = false;
73             if (FillNotificationRecord(requestObj, record) != ERR_OK) {
74                 ANS_LOGE("Fill notification record failed.");
75                 continue;
76             }
77 
78             if (Filter(record, true) != ERR_OK) {
79                 ANS_LOGE("Filter record failed.");
80                 continue;
81             }
82 
83             // Turn off ringtone and vibration during recovery process
84             record->request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::SOUND_FLAG, false);
85             record->request->SetDistributedFlagBit(NotificationConstant::ReminderFlag::VIBRATION_FLAG, false);
86             ANS_LOGI("SetFlags-Recovery, notificationKey = %{public}s flags = %{public}d",
87                 record->request->GetKey().c_str(), record->request->GetFlags()->GetReminderFlags());
88             if (AssignToNotificationList(record) != ERR_OK) {
89                 ANS_LOGE("Add notification to record list failed.");
90                 continue;
91             }
92             UpdateRecentNotification(record->notification, false, 0);
93 
94             StartFinishTimer(record, requestObj.request->GetFinishDeadLine(),
95                 NotificationConstant::TRIGGER_EIGHT_HOUR_REASON_DELETE);
96             StartUpdateTimer(record, requestObj.request->GetUpdateDeadLine(),
97                 NotificationConstant::TRIGGER_FOUR_HOUR_REASON_DELETE);
98         }
99 
100         if (!keys.empty()) {
101             OnRecoverLiveView(keys);
102         }
103         // publish notifications
104         for (const auto &subscriber : NotificationSubscriberManager::GetInstance()->GetSubscriberRecords()) {
105             OnSubscriberAdd(subscriber, userId);
106         }
107         ANS_LOGI("End recover live view from db.");
108     }));
109 }
110 
UpdateNotificationTimerInfo(const std::shared_ptr<NotificationRecord> & record)111 ErrCode AdvancedNotificationService::UpdateNotificationTimerInfo(const std::shared_ptr<NotificationRecord> &record)
112 {
113     ErrCode result = ERR_OK;
114 
115     if (!record->request->IsCommonLiveView()) {
116         if ((record->request->GetAutoDeletedTime() > GetCurrentTime())) {
117             StartAutoDeletedTimer(record);
118         }
119         return ERR_OK;
120     }
121 
122     auto content = record->request->GetContent()->GetNotificationContent();
123     auto liveViewContent = std::static_pointer_cast<NotificationLiveViewContent>(content);
124     auto status = liveViewContent->GetLiveViewStatus();
125     switch (status) {
126         case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_CREATE:
127             result = SetFinishTimer(record);
128             if (result != ERR_OK) {
129                 return result;
130             }
131 
132             result = SetUpdateTimer(record);
133             return result;
134         case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_INCREMENTAL_UPDATE:
135         case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_FULL_UPDATE:
136             // delete old, then add new
137             CancelUpdateTimer(record);
138             result = SetUpdateTimer(record);
139             return result;
140 
141         case NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_END:
142             CancelUpdateTimer(record);
143             CancelFinishTimer(record);
144             StartArchiveTimer(record);
145             break;
146         default:
147             ANS_LOGE("Invalid status %{public}d.", status);
148             return ERR_ANS_INVALID_PARAM;
149     }
150     return result;
151 }
152 
ProcForDeleteLiveView(const std::shared_ptr<NotificationRecord> & record)153 void AdvancedNotificationService::ProcForDeleteLiveView(const std::shared_ptr<NotificationRecord> &record)
154 {
155     if ((record->request == nullptr) ||
156         (!(record->request->IsCommonLiveView()) && !(record->request->IsSystemLiveView()))) {
157         return;
158     }
159     int32_t userId = record->request->GetReceiverUserId();
160     if (DoubleDeleteNotificationFromDb(record->request->GetKey(),
161         record->request->GetSecureKey(), userId) != ERR_OK) {
162         ANS_LOGE("Live View cancel, delete notification failed.");
163     }
164 
165     CancelUpdateTimer(record);
166     CancelFinishTimer(record);
167     CancelArchiveTimer(record);
168 }
169 
OnSubscriberAdd(const std::shared_ptr<NotificationSubscriberManager::SubscriberRecord> & record,const int32_t userId)170 ErrCode AdvancedNotificationService::OnSubscriberAdd(
171     const std::shared_ptr<NotificationSubscriberManager::SubscriberRecord> &record, const int32_t userId)
172 {
173     if (record == nullptr) {
174         ANS_LOGE("No subscriber to notify.");
175         return ERR_ANS_INVALID_PARAM;
176     }
177 
178     sptr<NotificationSortingMap> sortingMap = GenerateSortingMap();
179     std::vector<sptr<Notification>> notifications;
180     for (auto notificationRecord : notificationList_) {
181         if (notificationRecord != nullptr &&
182             notificationRecord->notification != nullptr &&
183             notificationRecord->notification->GetNotificationRequest().IsCommonLiveView()) {
184             notifications.emplace_back(notificationRecord->notification);
185         }
186     }
187 
188     if (notifications.empty() || currentUserId.count(userId)) {
189         ANS_LOGI("No notification to consume %{public}d %{public}zu.", userId, currentUserId.count(userId));
190         return ERR_ANS_NOTIFICATION_NOT_EXISTS;
191     }
192     if (userId != INVALID_USER_ID) {
193         currentUserId.insert(userId);
194     }
195     ANS_LOGI("Consume notification count is %{public}zu %{public}d.", notifications.size(), userId);
196     NotificationSubscriberManager::GetInstance()->BatchNotifyConsumed(notifications, sortingMap, record);
197     return ERR_OK;
198 }
199 
IsLiveViewCanRecover(const sptr<NotificationRequest> request)200 bool AdvancedNotificationService::IsLiveViewCanRecover(const sptr<NotificationRequest> request)
201 {
202     if (request == nullptr) {
203         ANS_LOGE("Invalid liveview.");
204         return false;
205     }
206 
207     using StatusType = NotificationLiveViewContent::LiveViewStatus;
208     auto liveViewContent =
209         std::static_pointer_cast<NotificationLiveViewContent>(request->GetContent()->GetNotificationContent());
210     auto liveViewStatus = liveViewContent->GetLiveViewStatus();
211     if (liveViewStatus == StatusType::LIVE_VIEW_BUTT || liveViewStatus == StatusType::LIVE_VIEW_END) {
212         ANS_LOGE("Only update or create status can reconver.");
213         return false;
214     }
215 
216     auto epoch = std::chrono::system_clock::now().time_since_epoch();
217     auto curTime = std::chrono::duration_cast<std::chrono::milliseconds>(epoch).count();
218     if (curTime > request->GetUpdateDeadLine() || curTime > request->GetFinishDeadLine()) {
219         ANS_LOGE("The liveView has expired.");
220         return false;
221     }
222 
223     return true;
224 }
225 
SetNotificationRequestToDb(const NotificationRequestDb & requestDb)226 int32_t AdvancedNotificationService::SetNotificationRequestToDb(const NotificationRequestDb &requestDb)
227 {
228     auto request = requestDb.request;
229     if (!request->IsCommonLiveView()) {
230         ANS_LOGD("Slot type %{public}d, content type %{public}d.",
231             request->GetSlotType(), request->GetNotificationType());
232 
233         return ERR_OK;
234     }
235 
236     ANS_LOGI("Enter.");
237     auto content = std::static_pointer_cast<NotificationLiveViewContent>(
238         request->GetContent()->GetNotificationContent());
239     if (request->GetOwnerUid() != DEFAULT_UID) {
240         content->SetUid(request->GetOwnerUid());
241     }
242     if (content->GetLiveViewStatus() == NotificationLiveViewContent::LiveViewStatus::LIVE_VIEW_END &&
243         request->GetAutoDeletedTime() == NotificationConstant::NO_DELAY_DELETE_TIME) {
244         ANS_LOGI("Don't need set to db when liveview is in end status and no delay delete time.");
245         return ERR_OK;
246     }
247 
248     if (content->GetIsOnlyLocalUpdate()) {
249         ANS_LOGI("Not saving notification request to db for common live view with isOnlyLocalUpdate set to true.");
250         return ERR_OK;
251     }
252     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_6, EventBranchId::BRANCH_3).
253         BundleName(request->GetCreatorBundleName()).NotificationId(request->GetNotificationId());
254     nlohmann::json jsonObject;
255     if (!NotificationJsonConverter::ConvertToJson(request, jsonObject)) {
256         ANS_LOGE("Convert request to json object failed, bundle name %{public}s, id %{public}d.",
257             request->GetCreatorBundleName().c_str(), request->GetNotificationId());
258         NotificationAnalyticsUtil::ReportModifyEvent(message.Message("convert request failed"));
259         return ERR_ANS_TASK_ERR;
260     }
261     auto bundleOption = requestDb.bundleOption;
262     if (!NotificationJsonConverter::ConvertToJson(bundleOption, jsonObject)) {
263         ANS_LOGE("Convert bundle to json object failed, bundle name %{public}s, id %{public}d.",
264             bundleOption->GetBundleName().c_str(), request->GetNotificationId());
265         NotificationAnalyticsUtil::ReportModifyEvent(message.Message("convert option failed"));
266         return ERR_ANS_TASK_ERR;
267     }
268 
269     std::string encryptValue;
270     ErrCode errorCode = AesGcmHelper::Encrypt(jsonObject.dump(), encryptValue);
271     if (errorCode != ERR_OK) {
272         ANS_LOGE("SetNotificationRequestToDb encrypt error");
273         return static_cast<int>(errorCode);
274     }
275     auto result = NotificationPreferences::GetInstance()->SetKvToDb(
276         request->GetSecureKey(), encryptValue, request->GetReceiverUserId());
277     if (result != ERR_OK) {
278         ANS_LOGE("Set failed, bundle name %{public}s, id %{public}d, key %{public}s, ret %{public}d.",
279             request->GetCreatorBundleName().c_str(), request->GetNotificationId(), request->GetKey().c_str(), result);
280         NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(result).Message("set failed"));
281         return result;
282     } else {
283         DeleteNotificationRequestFromDb(request->GetKey(), request->GetReceiverUserId());
284     }
285 
286     result = SetLockScreenPictureToDb(request);
287     if (result != ERR_OK) {
288         ANS_LOGE("Failed to set lock screen picture to db");
289         NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(result).Message("SetToDb failed"));
290     }
291     return result;
292 }
293 
GetBatchNotificationRequestsFromDb(std::vector<NotificationRequestDb> & requests,int32_t userId)294 int32_t AdvancedNotificationService::GetBatchNotificationRequestsFromDb(
295     std::vector<NotificationRequestDb> &requests, int32_t userId)
296 {
297     std::unordered_map<std::string, std::string> dbRecords;
298     std::vector<int32_t> userIds;
299     int ret = ERR_OK;
300     if (userId == -1) {
301         ret = OsAccountManagerHelper::GetInstance().GetAllActiveOsAccount(userIds);
302     } else {
303         userIds.push_back(userId);
304     }
305 
306     if (ret != ERR_OK) {
307         ANS_LOGE("Get all os account failed.");
308         return ret;
309     }
310     for (const int32_t userId : userIds) {
311         int32_t result =
312             NotificationPreferences::GetInstance()->GetBatchKvsFromDb(REQUEST_STORAGE_KEY_PREFIX, dbRecords, userId);
313         int32_t secureResult =
314             NotificationPreferences::GetInstance()->GetBatchKvsFromDb(
315                 REQUEST_STORAGE_SECURE_KEY_PREFIX, dbRecords, userId);
316         if (result != ERR_OK && secureResult != ERR_OK) {
317             ANS_LOGE("Get batch notification request failed.");
318             return result;
319         }
320     }
321     for (const auto &iter : dbRecords) {
322         std::string decryptValue = iter.second;
323         if (iter.first.rfind(REQUEST_STORAGE_SECURE_KEY_PREFIX, 0) == 0) {
324             ErrCode errorCode = AesGcmHelper::Decrypt(decryptValue, iter.second);
325             if (errorCode != ERR_OK) {
326                 ANS_LOGE("GetBatchNotificationRequestsFromDb decrypt error");
327                 return static_cast<int>(errorCode);
328             }
329         }
330         if (decryptValue.empty() || !nlohmann::json::accept(decryptValue)) {
331             ANS_LOGE("Invalid json");
332             continue;
333         }
334         auto jsonObject = nlohmann::json::parse(decryptValue);
335         auto *request = NotificationJsonConverter::ConvertFromJson<NotificationRequest>(jsonObject);
336         if (request == nullptr) {
337             ANS_LOGE("Parse json string to request failed.");
338             continue;
339         }
340         auto *bundleOption = NotificationJsonConverter::ConvertFromJson<NotificationBundleOption>(jsonObject);
341         if (bundleOption == nullptr) {
342             ANS_LOGE("Parse json string to bundle option failed.");
343             (void)DoubleDeleteNotificationFromDb(request->GetKey(),
344                 request->GetSecureKey(), request->GetReceiverUserId());
345             continue;
346         }
347 
348         if (GetLockScreenPictureFromDb(request) != ERR_OK) {
349             ANS_LOGE("Get request lock screen picture failed.");
350         }
351         NotificationRequestDb requestDb = { .request = request, .bundleOption = bundleOption };
352         requests.emplace_back(requestDb);
353     }
354     return ERR_OK;
355 }
356 
357 
DoubleDeleteNotificationFromDb(const std::string & key,const std::string & secureKey,const int32_t userId)358 int32_t AdvancedNotificationService::DoubleDeleteNotificationFromDb(const std::string &key,
359     const std::string &secureKey, const int32_t userId)
360 {
361     auto result = NotificationPreferences::GetInstance()->DeleteKvFromDb(secureKey, userId);
362     if (result != ERR_OK) {
363         ANS_LOGE("Delete notification request failed, key %{public}s.", key.c_str());
364         return result;
365     }
366     result = DeleteNotificationRequestFromDb(key, userId);
367     return result;
368 }
369 
DeleteNotificationRequestFromDb(const std::string & key,const int32_t userId)370 int32_t AdvancedNotificationService::DeleteNotificationRequestFromDb(const std::string &key, const int32_t userId)
371 {
372     auto result = NotificationPreferences::GetInstance()->DeleteKvFromDb(key, userId);
373     if (result != ERR_OK) {
374         ANS_LOGE("Delete notification request failed, key %{public}s.", key.c_str());
375         return result;
376     }
377 
378     std::string lockScreenPictureKey = LOCK_SCREEN_PICTURE_TAG + key;
379     result = NotificationPreferences::GetInstance()->DeleteKvFromDb(lockScreenPictureKey, userId);
380     if (result != ERR_OK) {
381         ANS_LOGE("Delete notification lock screen picture failed, key %{public}s.", lockScreenPictureKey.c_str());
382         return result;
383     }
384     return ERR_OK;
385 }
386 
IsAllowedRemoveSlot(const sptr<NotificationBundleOption> & bundleOption,const NotificationConstant::SlotType & slotType)387 ErrCode AdvancedNotificationService::IsAllowedRemoveSlot(const sptr<NotificationBundleOption> &bundleOption,
388     const NotificationConstant::SlotType &slotType)
389 {
390     if (slotType != NotificationConstant::SlotType::LIVE_VIEW) {
391         return ERR_OK;
392     }
393 
394     sptr<NotificationSlot> slot;
395     if (NotificationPreferences::GetInstance()->GetNotificationSlot(bundleOption, slotType, slot) != ERR_OK) {
396         ANS_LOGE("Failed to get slot.");
397         return ERR_OK;
398     }
399 
400     if (!slot->GetForceControl()) {
401         ANS_LOGI("Liveview slot is not force control.");
402         return ERR_OK;
403     }
404 
405     bool isSubsystem = AccessTokenHelper::VerifyNativeToken(IPCSkeleton::GetCallingTokenID());
406     if (!isSubsystem && !AccessTokenHelper::IsSystemApp()) {
407         ANS_LOGE("Only sa or systemapp can remove liveview slot.");
408         return ERR_ANS_NON_SYSTEM_APP;
409     }
410 
411     return ERR_OK;
412 }
413 
FillLockScreenPicture(const sptr<NotificationRequest> & newRequest,const sptr<NotificationRequest> & oldRequest)414 void AdvancedNotificationService::FillLockScreenPicture(const sptr<NotificationRequest> &newRequest,
415     const sptr<NotificationRequest> &oldRequest)
416 {
417     if (oldRequest->GetContent() == nullptr ||
418         newRequest->GetContent() == nullptr) {
419         return;
420     }
421     if (oldRequest->GetContent()->GetNotificationContent() == nullptr ||
422         newRequest->GetContent()->GetNotificationContent() == nullptr) {
423         return;
424     }
425     if (newRequest->GetSlotType() != NotificationConstant::SlotType::LIVE_VIEW) {
426         return;
427     }
428 
429     auto oldContent = oldRequest->GetContent()->GetNotificationContent();
430     auto newContent = newRequest->GetContent()->GetNotificationContent();
431     if (newContent->GetLockScreenPicture() == nullptr) {
432         newContent->SetLockScreenPicture(oldContent->GetLockScreenPicture());
433     }
434 }
435 
SetLockScreenPictureToDb(const sptr<NotificationRequest> & request)436 ErrCode AdvancedNotificationService::SetLockScreenPictureToDb(const sptr<NotificationRequest> &request)
437 {
438     auto lockScreenPicture = request->GetContent()->GetNotificationContent()->GetLockScreenPicture();
439     if (!request->IsCommonLiveView() || lockScreenPicture == nullptr) {
440         return ERR_OK;
441     }
442 
443     auto size = static_cast<size_t>(lockScreenPicture->GetCapacity());
444     auto pixels = lockScreenPicture->GetPixels();
445     std::vector<uint8_t> pixelsVec(pixels, pixels + size);
446 
447     std::string key = LOCK_SCREEN_PICTURE_TAG + request->GetKey();
448     auto res = NotificationPreferences::GetInstance()->SetByteToDb(key, pixelsVec, request->GetReceiverUserId());
449     if (res != ERR_OK) {
450         ANS_LOGE("Failed to set lock screen picture to db, res is %{public}d.", res);
451         return res;
452     }
453 
454     return ERR_OK;
455 }
456 
GetLockScreenPictureFromDb(NotificationRequest * request)457 ErrCode AdvancedNotificationService::GetLockScreenPictureFromDb(NotificationRequest *request)
458 {
459     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_12, EventBranchId::BRANCH_0);
460     if (request == nullptr) {
461         ANS_LOGE("Request is nullptr");
462         NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(ERR_ANS_INVALID_PARAM));
463         return ERR_ANS_INVALID_PARAM;
464     }
465     std::string key = LOCK_SCREEN_PICTURE_TAG + request->GetKey();
466     std::vector<uint8_t> pixelsVec;
467     uint32_t res = NotificationPreferences::GetInstance()->GetByteFromDb(key, pixelsVec, request->GetReceiverUserId());
468     if (res != ERR_OK) {
469         NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(res).BranchId(BRANCH_1));
470         ANS_LOGE("Failed to get lock screen picture from db, res is %{public}d.", res);
471         return res;
472     }
473 
474     Media::SourceOptions sourceOptions;
475     auto imageSource = Media::ImageSource::CreateImageSource((const uint8_t *)pixelsVec.data(), pixelsVec.size(),
476         sourceOptions, res);
477     if (res != ERR_OK) {
478         NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(res).BranchId(BRANCH_2));
479         ANS_LOGE("Failed to create image source, res is %{public}d.", res);
480         return res;
481     }
482 
483     Media::DecodeOptions decodeOpts;
484     auto pixelMapPtr = imageSource->CreatePixelMap(decodeOpts, res);
485     if (res != ERR_OK) {
486         NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(res).BranchId(BRANCH_3));
487         ANS_LOGE("Failed to create pixel map, res is %{public}d.", res);
488         return res;
489     }
490 
491     std::shared_ptr<Media::PixelMap> picture = std::shared_ptr<Media::PixelMap>(pixelMapPtr.release());
492     request->GetContent()->GetNotificationContent()->SetLockScreenPicture(picture);
493 
494     return ERR_OK;
495 }
496 
UpdateInDelayNotificationList(const std::shared_ptr<NotificationRecord> & record)497 void AdvancedNotificationService::UpdateInDelayNotificationList(const std::shared_ptr<NotificationRecord> &record)
498 {
499     std::lock_guard<ffrt::mutex> lock(delayNotificationMutext_);
500     auto iter = delayNotificationList_.begin();
501     while (iter != delayNotificationList_.end()) {
502         if ((*iter).first->notification->GetKey() == record->notification->GetKey()) {
503             CancelTimer((*iter).second);
504             (*iter).first = record;
505             auto request = record->notification->GetNotificationRequest();
506             (*iter).second = StartDelayPublishTimer(request.GetOwnerUid(),
507                 request.GetNotificationId(), request.GetPublishDelayTime());
508             break;
509         }
510         iter++;
511     }
512 }
513 
AddToDelayNotificationList(const std::shared_ptr<NotificationRecord> & record)514 void AdvancedNotificationService::AddToDelayNotificationList(const std::shared_ptr<NotificationRecord> &record)
515 {
516     std::lock_guard<ffrt::mutex> lock(delayNotificationMutext_);
517     auto request = record->notification->GetNotificationRequest();
518     auto timerId = StartDelayPublishTimer(
519         request.GetOwnerUid(), request.GetNotificationId(), request.GetPublishDelayTime());
520     delayNotificationList_.emplace_back(std::make_pair(record, timerId));
521 }
522 
SaPublishSystemLiveViewAsBundle(const std::shared_ptr<NotificationRecord> & record)523 ErrCode AdvancedNotificationService::SaPublishSystemLiveViewAsBundle(const std::shared_ptr<NotificationRecord> &record)
524 {
525     uint32_t delayTime = record->notification->GetNotificationRequest().GetPublishDelayTime();
526     if (delayTime == 0) {
527         return StartPublishDelayedNotification(record);
528     }
529 
530     if (IsNotificationExistsInDelayList(record->notification->GetKey())) {
531         UpdateInDelayNotificationList(record);
532         return ERR_OK;
533     }
534 
535     AddToDelayNotificationList(record);
536     return ERR_OK;
537 }
538 
IsNotificationExistsInDelayList(const std::string & key)539 bool AdvancedNotificationService::IsNotificationExistsInDelayList(const std::string &key)
540 {
541     std::lock_guard<ffrt::mutex> lock(delayNotificationMutext_);
542     for (auto delayNotification : delayNotificationList_) {
543         if (delayNotification.first->notification->GetKey() == key) {
544             return true;
545         }
546     }
547 
548     return false;
549 }
550 
StartDelayPublishTimer(const int32_t ownerUid,const int32_t notificationId,const uint32_t delayTime)551 uint64_t AdvancedNotificationService::StartDelayPublishTimer(
552     const int32_t ownerUid, const int32_t notificationId, const uint32_t delayTime)
553 {
554     ANS_LOGD("Enter");
555 
556     HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_12, EventBranchId::BRANCH_4);
557     wptr<AdvancedNotificationService> wThis = this;
558     auto timeoutFunc = [wThis, ownerUid, notificationId] {
559         sptr<AdvancedNotificationService> sThis = wThis.promote();
560         if (sThis != nullptr) {
561             sThis->StartPublishDelayedNotificationTimeOut(ownerUid, notificationId);
562         }
563     };
564     std::shared_ptr<NotificationTimerInfo> notificationTimerInfo = std::make_shared<NotificationTimerInfo>();
565     notificationTimerInfo->SetCallbackInfo(timeoutFunc);
566 
567     sptr<MiscServices::TimeServiceClient> timer = MiscServices::TimeServiceClient::GetInstance();
568     if (timer == nullptr) {
569         ANS_LOGE("Failed to start timer due to get TimeServiceClient is null.");
570         NotificationAnalyticsUtil::ReportModifyEvent(message.ErrorCode(NotificationConstant::INVALID_TIMER_ID));
571         return NotificationConstant::INVALID_TIMER_ID;
572     }
573 
574     uint64_t timerId = timer->CreateTimer(notificationTimerInfo);
575     int64_t delayPublishPoint = GetCurrentTime() + delayTime * NotificationConstant::SECOND_TO_MS;
576     timer->StartTimer(timerId, delayPublishPoint);
577     return timerId;
578 }
579 
StartPublishDelayedNotificationTimeOut(const int32_t ownerUid,const int32_t notificationId)580 void AdvancedNotificationService::StartPublishDelayedNotificationTimeOut(
581     const int32_t ownerUid, const int32_t notificationId)
582 {
583     auto record = GetFromDelayedNotificationList(ownerUid, notificationId);
584     if (record == nullptr) {
585         ANS_LOGE("Failed to get delayed notification from list.");
586         return;
587     }
588 
589     int ret = StartPublishDelayedNotification(record);
590     if (ret != ERR_OK) {
591         ANS_LOGE("Failed to StartPublishDelayedNotification, ret is %{public}d", ret);
592         return;
593     }
594 }
595 
StartPublishDelayedNotification(const std::shared_ptr<NotificationRecord> & record)596 ErrCode AdvancedNotificationService::StartPublishDelayedNotification(const std::shared_ptr<NotificationRecord> &record)
597 {
598     RemoveFromDelayedNotificationList(record->notification->GetKey());
599     ErrCode result = AssignToNotificationList(record);
600     if (result != ERR_OK) {
601         ANS_LOGE("Failed to assign notification list");
602         return result;
603     }
604 
605     UpdateRecentNotification(record->notification, false, 0);
606     NotificationSubscriberManager::GetInstance()->NotifyConsumed(record->notification, GenerateSortingMap());
607     if ((record->request->GetAutoDeletedTime() > GetCurrentTime())) {
608         StartAutoDeletedTimer(record);
609     }
610 
611     record->finish_status = UploadStatus::FIRST_UPDATE_TIME_OUT;
612     StartFinishTimer(record, GetCurrentTime() + NotificationConstant::TEN_MINUTES,
613         NotificationConstant::TRIGGER_TEN_MINUTES_REASON_DELETE);
614 
615     return ERR_OK;
616 }
617 
IsUpdateSystemLiveviewByOwner(const sptr<NotificationRequest> & request)618 bool AdvancedNotificationService::IsUpdateSystemLiveviewByOwner(const sptr<NotificationRequest> &request)
619 {
620     if (!request->IsSystemLiveView()) {
621         return false;
622     }
623 
624     auto ownerUid = IPCSkeleton::GetCallingUid();
625     auto oldRecord = GetFromDelayedNotificationList(ownerUid, request->GetNotificationId());
626     if (oldRecord != nullptr) {
627         return true;
628     }
629 
630     if (notificationSvrQueue_ == nullptr) {
631         ANS_LOGE("Serial queue is invalid.");
632         return false;
633     }
634 
635     ffrt::task_handle handler = notificationSvrQueue_->submit_h([&]() {
636         oldRecord = GetFromNotificationList(ownerUid, request->GetNotificationId());
637     });
638     notificationSvrQueue_->wait(handler);
639 
640     return oldRecord != nullptr;
641 }
642 
IsSaCreateSystemLiveViewAsBundle(const std::shared_ptr<NotificationRecord> & record,int32_t ipcUid)643 bool AdvancedNotificationService::IsSaCreateSystemLiveViewAsBundle(
644     const std::shared_ptr<NotificationRecord> &record, int32_t ipcUid)
645 {
646     if (record == nullptr) {
647         ANS_LOGE("Invalid record.");
648         return false;
649     }
650 
651     auto request = record->notification->GetNotificationRequest();
652     if (!request.IsSystemLiveView()) {
653         return false;
654     }
655 
656     if (request.GetCreatorUid() == ipcUid &&
657         request.GetCreatorUid() != request.GetOwnerUid() &&
658         !IsNotificationExists(record->notification->GetKey())) {
659         return true;
660     }
661 
662     return false;
663 }
664 
UpdateRecordByOwner(const std::shared_ptr<NotificationRecord> & record,bool isSystemApp)665 void AdvancedNotificationService::UpdateRecordByOwner(
666     const std::shared_ptr<NotificationRecord> &record, bool isSystemApp)
667 {
668     auto creatorUid = record->notification->GetNotificationRequest().GetCreatorUid();
669     auto notificationId =  record->notification->GetNotificationRequest().GetNotificationId();
670     auto oldRecord = GetFromDelayedNotificationList(creatorUid, notificationId);
671     if (oldRecord == nullptr) {
672         oldRecord = GetFromNotificationList(creatorUid, notificationId);
673     }
674     if (oldRecord == nullptr) {
675         return;
676     }
677     auto downloadTemplate = record->notification->GetNotificationRequest().GetTemplate();
678     auto content = record->notification->GetNotificationRequest().GetContent();
679     auto wantAgent = record->notification->GetNotificationRequest().GetWantAgent();
680     record->request = new (std::nothrow) NotificationRequest(*(oldRecord->request));
681     if (record->request == nullptr) {
682         ANS_LOGE("request is nullptr.");
683         return;
684     }
685     if (wantAgent != nullptr) {
686         record->request->SetWantAgent(wantAgent);
687     }
688     uint64_t timerId = 0;
689     if (isSystemApp) {
690         record->request->SetContent(content);
691     } else {
692         record->request->SetTemplate(downloadTemplate);
693         auto data = downloadTemplate->GetTemplateData();
694         AAFwk::WantParamWrapper wrapper(*data);
695         ANS_LOGD("Update the template data: %{public}s.", wrapper.ToString().c_str());
696         CancelTimer(oldRecord->notification->GetFinishTimer());
697         uint64_t process = 0;
698         if (data->HasParam(PROGRESS_VALUE)) {
699             process = data->GetIntParam(PROGRESS_VALUE, 0);
700         }
701         StartFinishTimerForUpdate(record, process);
702         timerId = record->notification->GetFinishTimer();
703         ANS_LOGI("TimerForUpdate,oldTimeId:%{public}d,newTimeId:%{public}d",
704             (int)(oldRecord->notification->GetFinishTimer()), (int)timerId);
705     }
706     record->notification = new (std::nothrow) Notification(record->request);
707     if (record->notification == nullptr) {
708         ANS_LOGE("Failed to create notification.");
709         return;
710     }
711     record->bundleOption = oldRecord->bundleOption;
712     record->notification->SetFinishTimer(timerId);
713 }
714 
StartFinishTimerForUpdate(const std::shared_ptr<NotificationRecord> & record,uint64_t process)715 void AdvancedNotificationService::StartFinishTimerForUpdate(
716     const std::shared_ptr<NotificationRecord> &record, uint64_t process)
717 {
718     if (process == NotificationConstant::FINISH_PER) {
719         record->finish_status = UploadStatus::FINISH;
720         StartFinishTimer(record, GetCurrentTime() + NotificationConstant::THIRTY_MINUTES,
721             NotificationConstant::TRIGGER_FIFTEEN_MINUTES_REASON_DELETE);
722     } else {
723         record->finish_status = UploadStatus::CONTINUOUS_UPDATE_TIME_OUT;
724         StartFinishTimer(record, GetCurrentTime() + NotificationConstant::FIFTEEN_MINUTES,
725             NotificationConstant::TRIGGER_THIRTY_MINUTES_REASON_DELETE);
726     }
727 }
728 
HandleUpdateLiveViewNotificationTimer(const int32_t uid,const bool isPaused)729 void AdvancedNotificationService::HandleUpdateLiveViewNotificationTimer(const int32_t uid, const bool isPaused)
730 {
731     for (const auto &record : notificationList_) {
732         const auto &request = record->request;
733         if (!request || request->GetOwnerUid() != uid) {
734             continue;
735         }
736         if (!request->GetContent() || !request->GetContent()->GetNotificationContent()) {
737             continue;
738         }
739         bool isContinuousLiveView = request->IsSystemLiveView() && request->GetCreatorUid() == BGTASK_UID;
740         if (!isContinuousLiveView) {
741             continue;
742         }
743         const auto &liveViewContent = std::static_pointer_cast<NotificationLocalLiveViewContent>(
744             request->GetContent()->GetNotificationContent());
745         if (liveViewContent->GetType() == TYPE_CODE_DOWNLOAD) {
746             if (isPaused) {
747                 ANS_LOGI("liveview notification timer is being cancelled, uid: %{public}d", uid);
748                 CancelTimer(record->notification->GetFinishTimer());
749             } else {
750                 ANS_LOGI("liveview notification timer is being reset, uid: %{public}d", uid);
751                 StartFinishTimer(record, GetCurrentTime() + NotificationConstant::FIFTEEN_MINUTES,
752                     NotificationConstant::TRIGGER_THIRTY_MINUTES_REASON_DELETE);
753             }
754         }
755     }
756 }
757 }
758 }
759