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