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