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