diff --git a/frameworks/ans/src/notification_request.cpp b/frameworks/ans/src/notification_request.cpp index c1906adda8a9efbc8a3dcaa4a3337f7a4fac53ee..06653690f5c59e3ddf5734ada1200470fd334984 100644 --- a/frameworks/ans/src/notification_request.cpp +++ b/frameworks/ans/src/notification_request.cpp @@ -777,6 +777,7 @@ std::string NotificationRequest::Dump() ", floatingIcon = " + (floatingIcon_ ? "true" : "false") + ", onlyLocal = " + (onlyLocal_ ? "true" : "false") + ", permitted = " + (permitted_ ? "true" : "false") + ", isAgent = " + (isAgent_ ? "true" : "false") + + ", updateOnly = " + (updateOnly_ ? "true" : "false") + ", removalWantAgent = " + (removalWantAgent_ ? "not null" : "null") + ", maxScreenWantAgent = " + (maxScreenWantAgent_ ? "not null" : "null") + ", additionalParams = " + (additionalParams_ ? "not null" : "null") + @@ -830,6 +831,7 @@ bool NotificationRequest::ToJson(nlohmann::json &jsonObject) const jsonObject["isUnremovable"] = unremovable_; jsonObject["isAgent"] = isAgent_; jsonObject["isFloatingIcon"] = floatingIcon_; + jsonObject["updateOnly"] = updateOnly_; jsonObject["creatorBundleName"] = creatorBundleName_; jsonObject["creatorUid"] = creatorUid_; @@ -1336,6 +1338,11 @@ bool NotificationRequest::Marshalling(Parcel &parcel) const return false; } + if (!parcel.WriteBool(updateOnly_)) { + ANS_LOGE("Failed to write updateOnly_"); + return false; + } + if (!parcel.WriteUint64(messageUsers_.size())) { ANS_LOGE("Failed to write the size of messageUsers"); return false; @@ -1707,6 +1714,7 @@ bool NotificationRequest::ReadFromParcel(Parcel &parcel) isCoverActionButtons_ = parcel.ReadBool(); isUpdateByOwnerAllowed_ = parcel.ReadBool(); + updateOnly_ = parcel.ReadBool(); vsize = parcel.ReadUint64(); vsize = (vsize < NotificationRequest::MAX_MESSAGE_USERS) ? vsize : NotificationRequest::MAX_MESSAGE_USERS; @@ -1914,6 +1922,7 @@ void NotificationRequest::CopyBase(const NotificationRequest &other) this->isRemoveAllowed_ = other.isRemoveAllowed_; this->isCoverActionButtons_ = other.isCoverActionButtons_; this->isUpdateByOwnerAllowed_ = other.isUpdateByOwnerAllowed_; + this->updateOnly_ = other.updateOnly_; this->slotType_ = other.slotType_; this->settingsText_ = other.settingsText_; @@ -2239,6 +2248,10 @@ void NotificationRequest::ConvertJsonToBool(NotificationRequest *target, const n target->floatingIcon_ = jsonObject.at("isFloatingIcon").get(); } + if (jsonObject.find("updateOnly") != jsonEnd && jsonObject.at("updateOnly").is_boolean()) { + target->updateOnly_ = jsonObject.at("updateOnly").get(); + } + ConvertJsonToBoolExt(target, jsonObject); } @@ -2803,6 +2816,16 @@ bool NotificationRequest::IsUpdateByOwnerAllowed() const return isUpdateByOwnerAllowed_; } +void NotificationRequest::SetUpdateOnly(bool updateOnly) +{ + updateOnly_ = updateOnly; +} + +bool NotificationRequest::IsUpdateOnly() const +{ + return updateOnly_; +} + const std::string NotificationRequest::GetLittleIconType() const { return littleIconType_; diff --git a/frameworks/core/common/include/ans_const_define.h b/frameworks/core/common/include/ans_const_define.h index 24135987dee5b8c31bba6081c284acc5321e52db..f58eea322242e3ac9772ecd337315b1ca57af860 100644 --- a/frameworks/core/common/include/ans_const_define.h +++ b/frameworks/core/common/include/ans_const_define.h @@ -27,8 +27,11 @@ namespace Notification { // Max active notification number constexpr size_t MAX_ACTIVE_NUM = 1000; constexpr uint32_t MAX_ACTIVE_NUM_PERAPP = 100; -constexpr uint32_t MAX_ACTIVE_NUM_PERSECOND = 10; -constexpr uint32_t MAX_UPDATE_NUM_PERSECOND = 20; +constexpr uint32_t MAX_CREATE_NUM_PERSECOND = 15; +constexpr uint32_t MAX_UPDATE_NUM_PERSECOND = 30; +constexpr uint32_t MAX_CREATE_NUM_PERSECOND_PERAPP = 10; +constexpr uint32_t MAX_UPDATE_NUM_PERSECOND_PERAPP = 20; +constexpr std::chrono::seconds SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME = std::chrono::seconds(1); constexpr size_t MAX_SLOT_NUM = 5; constexpr uint32_t MAX_ICON_SIZE = 192 * 1024; constexpr uint32_t MAX_PICTURE_SIZE = 2 * 1024 * 1024; diff --git a/frameworks/js/napi/include/common.h b/frameworks/js/napi/include/common.h index adf7d992c133e0c75d87758473e2e771fecacf2f..e00d30baecb5110d17bb3be9b4b20721eceaa1e6 100644 --- a/frameworks/js/napi/include/common.h +++ b/frameworks/js/napi/include/common.h @@ -902,6 +902,16 @@ public: static napi_value GetNotificationShowDeliveryTime( const napi_env &env, const napi_value &value, NotificationRequest &request); + /** + * @brief Gets the updateOnly flag of NotificationRequest object from specified js object + * + * @param env Indicates the environment that the API is invoked under + * @param value Indicates a js object to be converted + * @param request Indicates a NotificationRequest object from specified js object + * @return Returns the null object if success, returns the null value otherwise + */ + static napi_value GetNotificationIsUpdateOnly( + const napi_env &env, const napi_value &value, NotificationRequest &request); static napi_value GetNotificationIsRemoveAllowed( const napi_env &env, const napi_value &value, NotificationRequest &request); diff --git a/frameworks/js/napi/src/common_convert_request.cpp b/frameworks/js/napi/src/common_convert_request.cpp index 292aa33df1218508e1a7e95128a1447cf26ce855..d35a97e11ec02f2764bce0a9bc227e5b3f3824b0 100644 --- a/frameworks/js/napi/src/common_convert_request.cpp +++ b/frameworks/js/napi/src/common_convert_request.cpp @@ -177,6 +177,10 @@ napi_value Common::SetNotificationRequestByBool( napi_get_boolean(env, request->IsShowDeliveryTime(), &value); napi_set_named_property(env, result, "showDeliveryTime", value); + // UpdateOnly?: boolean + napi_get_boolean(env, request->IsUpdateOnly(), &value); + napi_set_named_property(env, result, "updateOnly", value); + return NapiGetBoolean(env, true); } @@ -656,6 +660,11 @@ napi_value Common::GetNotificationRequestByBool( return nullptr; } + // UpdateOnly?: boolean + if (GetNotificationIsUpdateOnly(env, value, request) == nullptr) { + return nullptr; + } + GetNotificationIsRemoveAllowed(env, value, request); return NapiGetNull(env); @@ -1566,6 +1575,29 @@ napi_value Common::GetNotificationShowDeliveryTime( return NapiGetNull(env); } +napi_value Common::GetNotificationIsUpdateOnly( + const napi_env &env, const napi_value &value, NotificationRequest &request) +{ + napi_valuetype valuetype = napi_undefined; + napi_value result = nullptr; + bool hasProperty = false; + bool isUpdateOnly = false; + + NAPI_CALL(env, napi_has_named_property(env, value, "updateOnly", &hasProperty)); + if (hasProperty) { + napi_get_named_property(env, value, "updateOnly", &result); + NAPI_CALL(env, napi_typeof(env, result, &valuetype)); + if (valuetype != napi_boolean) { + ANS_LOGE("Wrong argument type. Bool expected."); + return nullptr; + } + napi_get_value_bool(env, result, &isUpdateOnly); + request.SetUpdateOnly(isUpdateOnly); + } + + return NapiGetNull(env); +} + napi_value Common::GetNotificationIsRemoveAllowed( const napi_env &env, const napi_value &value, NotificationRequest &request) { diff --git a/interfaces/inner_api/notification_request.h b/interfaces/inner_api/notification_request.h index ba2fd914fc431ba890fabd71500802bc6b31b66b..4ec110804535e4d23d62417163ba35bed4ffcb59 100644 --- a/interfaces/inner_api/notification_request.h +++ b/interfaces/inner_api/notification_request.h @@ -1403,6 +1403,20 @@ public: */ bool IsUpdateByOwnerAllowed() const; + /** + * @brief Set notification updateOnly value. + * + * @param updateOnly Indicates the updateOnly value of this notification. + */ + void SetUpdateOnly(bool updateOnly); + + /** + * @brief Obtains the value of updateOnly. + * + * @return Returns the updateOnly value of the notification. + */ + bool IsUpdateOnly() const; + private: /** * Indicates the color mask, used for calculation with the ARGB value set by setColor(int32_t). @@ -1522,6 +1536,7 @@ private: bool isRemoveAllowed_ {true}; bool isCoverActionButtons_ {false}; bool isUpdateByOwnerAllowed_ {false}; + bool updateOnly_ {false}; std::shared_ptr wantAgent_ {}; std::shared_ptr removalWantAgent_ {}; diff --git a/services/ans/include/advanced_notification_service.h b/services/ans/include/advanced_notification_service.h index 3a478e746382ca6bd33f9c6192471905d1eccaf1..3b3d1a25f37b4c6613d09deb3eaa877d73e03659 100644 --- a/services/ans/include/advanced_notification_service.h +++ b/services/ans/include/advanced_notification_service.h @@ -1219,8 +1219,8 @@ private: void SortNotificationList(); static bool NotificationCompare( const std::shared_ptr &first, const std::shared_ptr &second); - ErrCode FlowControl(const std::shared_ptr &record); - ErrCode PublishFlowControl(const std::shared_ptr &record); + ErrCode FlowControl(const std::shared_ptr &record, const int32_t callingUid); + ErrCode PublishInNotificationList(const std::shared_ptr &record); ErrCode RemoveNotificationBySlot(const sptr &bundleOption, const sptr &slot, const int reason); @@ -1404,8 +1404,19 @@ private: ErrCode CheckNeedSilent(const std::string &phoneNumber, int32_t callerType, int32_t userId); uint32_t GetDefaultSlotFlags(const sptr &request); bool IsSystemUser(int32_t userId); - ErrCode UpdateFlowCtrl(const std::shared_ptr &record); - ErrCode PublishFlowControlInner(const std::shared_ptr &record); + ErrCode UpdateFlowCtrl(const std::shared_ptr &record, const int32_t callingUid); + ErrCode UpdateGlobalFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now); + ErrCode UpdateSingleAppFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now, const int32_t callingUid); + void UpdateSingleAppFlowCtrlRemoveExpire(std::chrono::system_clock::time_point now); + ErrCode PublishFlowCtrl(const std::shared_ptr &record, const int32_t callingUid); + ErrCode PublishGlobalFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now); + ErrCode PublishSingleAppFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now, const int32_t callingUid); + void PublishSingleAppFlowCtrlRemoveExpire(std::chrono::system_clock::time_point now); + void GetFlowCtrlConfigFromCCM(); ErrCode SetEnabledForBundleSlotInner(const sptr &bundleOption, const sptr &bundle, const NotificationConstant::SlotType &slotType, bool enabled, bool isForceControl); @@ -1424,13 +1435,20 @@ private: std::shared_ptr handler_ = nullptr; std::list> notificationList_; static std::mutex flowControlMutex_; - std::list flowControlTimestampList_; std::list flowControlUpdateTimestampList_; std::list flowControlPublishTimestampList_; static std::mutex systemFlowControlMutex_; - std::list systemFlowControlTimestampList_; std::list systemFlowControlUpdateTimestampList_; std::list systemFlowControlPublishTimestampList_; + static std::mutex singleAppFlowControlMutex_; + std::map>> singleAppFlowControlUpdateTimestampMap_; + std::map>> singleAppFlowControlPublishTimestampMap_; + uint32_t maxCreateNumPerSecond = MAX_CREATE_NUM_PERSECOND; + uint32_t maxUpdateNumPerSecond = MAX_UPDATE_NUM_PERSECOND; + uint32_t maxCreateNumPerSecondPerApp = MAX_CREATE_NUM_PERSECOND_PERAPP; + uint32_t maxUpdateNumPerSecondPerApp = MAX_UPDATE_NUM_PERSECOND_PERAPP; std::shared_ptr recentInfo_ = nullptr; std::shared_ptr distributedKvStoreDeathRecipient_ = nullptr; std::shared_ptr systemEventObserver_ = nullptr; diff --git a/services/ans/include/notification_config_parse.h b/services/ans/include/notification_config_parse.h index 1948a9134e1bed7801bf78a01c70892c278f027d..486672a3b7ee5668f3195046f98539d6325d8892 100644 --- a/services/ans/include/notification_config_parse.h +++ b/services/ans/include/notification_config_parse.h @@ -49,6 +49,10 @@ public: constexpr static const char* CFG_KEY_NAME = "name"; constexpr static const char* CFG_KEY_REMINDER_FLAGS = "reminderFlags"; constexpr static const char* APP_PRIVILEGES = "appPrivileges"; + constexpr static const char* CFG_KEY_MAX_CREATE_NUM_PERSECOND = "MaxCreateNumPerSecond"; + constexpr static const char* CFG_KEY_MAX_UPDATE_NUM_PERSECOND = "MaxUpdateNumPerSecond"; + constexpr static const char* CFG_KEY_MAX_CREATE_NUM_PERSECOND_PERAPP = "MaxCreateNumPerSecondPerApp"; + constexpr static const char* CFG_KEY_MAX_UPDATE_NUM_PERSECOND_PERAPP = "MaxUpdateNumPerSecondPerApp"; #ifdef CONFIG_POLICY_ENABLE constexpr static const char* NOTIFICAITON_CONFIG_FILE = "etc/notification/notification_config.json"; # else diff --git a/services/ans/src/advanced_notification_live_view_service.cpp b/services/ans/src/advanced_notification_live_view_service.cpp index 0adab15907a557e215c296a225499e6eb0a86e24..29deece6ea3072306e8083a265127cabb3e25ce6 100644 --- a/services/ans/src/advanced_notification_live_view_service.cpp +++ b/services/ans/src/advanced_notification_live_view_service.cpp @@ -76,11 +76,6 @@ void AdvancedNotificationService::RecoverLiveViewFromDb(int32_t userId) continue; } - if (FlowControl(record) != ERR_OK) { - ANS_LOGE("Flow control failed."); - continue; - } - // Turn off ringtone and vibration during recovery process auto notificationFlags = record->request->GetFlags(); notificationFlags->SetSoundEnabled(NotificationConstant::FlagStatus::CLOSE); diff --git a/services/ans/src/advanced_notification_publish_service.cpp b/services/ans/src/advanced_notification_publish_service.cpp index 6898074b35ab1d3b1878fa2a19fb9dae00575797..854ddfe398da25d8cd90319d036bd11daaa46515 100644 --- a/services/ans/src/advanced_notification_publish_service.cpp +++ b/services/ans/src/advanced_notification_publish_service.cpp @@ -2110,7 +2110,7 @@ ErrCode AdvancedNotificationService::PublishNotificationBySa(const sptrGetUnifiedGroupInfo(request); #endif - auto ipcUid = IPCSkeleton::GetCallingUid(); + const int32_t ipcUid = IPCSkeleton::GetCallingUid(); ffrt::task_handle handler = notificationSvrQueue_->submit_h([&]() { if (!bundleOption->GetBundleName().empty()) { ErrCode ret = AssignValidNotificationSlot(record, bundleOption); @@ -2129,7 +2129,10 @@ ErrCode AdvancedNotificationService::PublishNotificationBySa(const sptr slotFlagsDefaultMap_; std::map> AdvancedNotificationService::pushCallBacks_; @@ -321,6 +323,7 @@ AdvancedNotificationService::AdvancedNotificationService() systemEventObserver_ = std::make_shared(iSystemEvent); dataManager_.RegisterKvStoreServiceDeathRecipient(distributedKvStoreDeathRecipient_); + GetFlowCtrlConfigFromCCM(); #ifdef DISTRIBUTED_NOTIFICATION_SUPPORTED InitDistributeCallBack(); #endif @@ -355,8 +358,15 @@ ErrCode AdvancedNotificationService::AssignToNotificationList(const std::shared_ { ErrCode result = ERR_OK; if (!IsNotificationExists(record->notification->GetKey())) { + if (record->request->IsUpdateOnly()) { + ANS_LOGE("Notification not exists when update"); + HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_3, EventBranchId::BRANCH_3) + .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("Nft not exist"); + NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + return ERR_ANS_NOTIFICATION_NOT_EXISTS; + } record->request->SetCreateTime(GetCurrentTime()); - result = PublishFlowControl(record); + result = PublishInNotificationList(record); } else { if (record->request->IsAlertOneTime()) { CloseAlert(record); @@ -643,7 +653,7 @@ ErrCode AdvancedNotificationService::PublishPreparedNotification(const sptrGetUnifiedGroupInfo(request); #endif - int32_t uid = IPCSkeleton::GetCallingUid(); + const int32_t uid = IPCSkeleton::GetCallingUid(); ffrt::task_handle handler = notificationSvrQueue_->submit_h(std::bind([&]() { ANS_LOGD("ffrt enter!"); if (record->request->GetSlotType() == NotificationConstant::SlotType::LIVE_VIEW && @@ -656,7 +666,10 @@ ErrCode AdvancedNotificationService::PublishPreparedNotification(const sptr &record) +ErrCode AdvancedNotificationService::UpdateFlowCtrl(const std::shared_ptr &record, + const int32_t callingUid) { if (record->isNeedFlowCtrl == false) { return ERR_OK; } std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - ANS_LOGD("UpdateInNotificationList size %{public}zu,%{public}zu", + ErrCode result = ERR_OK; + result = UpdateSingleAppFlowCtrl(record, now, callingUid); + if (result != ERR_OK) { + return result; + } + result = UpdateGlobalFlowCtrl(record, now); + if (result != ERR_OK) { + return result; + } + if (record->isThirdparty == true) { + std::lock_guard lock(flowControlMutex_); + flowControlUpdateTimestampList_.push_back(now); + } else { + std::lock_guard lock(systemFlowControlMutex_); + systemFlowControlUpdateTimestampList_.push_back(now); + } + + { + std::lock_guard lock(singleAppFlowControlMutex_); + auto singleAppFlowControlIter = singleAppFlowControlUpdateTimestampMap_.find(callingUid); + if (singleAppFlowControlIter == singleAppFlowControlUpdateTimestampMap_.end()) { + singleAppFlowControlUpdateTimestampMap_[callingUid] = + std::make_shared>(); + singleAppFlowControlIter = singleAppFlowControlUpdateTimestampMap_.find(callingUid); + } + singleAppFlowControlIter->second->push_back(now); + } + + UpdateSingleAppFlowCtrlRemoveExpire(now); + return result; +} + +ErrCode AdvancedNotificationService::UpdateGlobalFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now) +{ + ANS_LOGD("UpdateGlobalFlowCtrl size %{public}zu,%{public}zu", flowControlUpdateTimestampList_.size(), systemFlowControlUpdateTimestampList_.size()); if (record->isThirdparty == true) { // 三方流控 std::lock_guard lock(flowControlMutex_); NotificationAnalyticsUtil::RemoveExpired(flowControlUpdateTimestampList_, now); - if (flowControlUpdateTimestampList_.size() >= MAX_UPDATE_NUM_PERSECOND) { + if (flowControlUpdateTimestampList_.size() >= maxUpdateNumPerSecond) { + ANS_LOGE("Third-part UpdateGlobalFlowCtrl failed"); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_2, EventBranchId::BRANCH_4) - .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("UpdateInNotificationList failed"); + .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("UpdateGlobalFlowCtrl failed"); if (record != nullptr) { NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); } return ERR_ANS_OVER_MAX_UPDATE_PERSECOND; } - flowControlUpdateTimestampList_.push_back(now); } else { // 系统流控 std::lock_guard lock(systemFlowControlMutex_); NotificationAnalyticsUtil::RemoveExpired(systemFlowControlUpdateTimestampList_, now); - if (systemFlowControlUpdateTimestampList_.size() >= MAX_UPDATE_NUM_PERSECOND) { + if (systemFlowControlUpdateTimestampList_.size() >= maxUpdateNumPerSecond) { + ANS_LOGE("System UpdateGlobalFlowCtrl failed"); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_2, EventBranchId::BRANCH_4) - .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("UpdateInNotificationList failed"); + .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("UpdateGlobalFlowCtrl failed"); if (record != nullptr) { NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); } return ERR_ANS_OVER_MAX_UPDATE_PERSECOND; } - systemFlowControlUpdateTimestampList_.push_back(now); } return ERR_OK; } -ErrCode AdvancedNotificationService::UpdateInNotificationList(const std::shared_ptr &record) +ErrCode AdvancedNotificationService::UpdateSingleAppFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now, const int32_t callingUid) { - ErrCode result = UpdateFlowCtrl(record); - if (result != ERR_OK) { - return result; + std::lock_guard lock(singleAppFlowControlMutex_); + auto singleAppFlowControlIter = singleAppFlowControlUpdateTimestampMap_.find(callingUid); + if (singleAppFlowControlIter == singleAppFlowControlUpdateTimestampMap_.end()) { + return ERR_OK; + } + NotificationAnalyticsUtil::RemoveExpired(*(singleAppFlowControlIter->second), now); + if (singleAppFlowControlIter->second->size() >= maxUpdateNumPerSecondPerApp) { + ANS_LOGE("SingleAppUpdateFlowControl failed"); + HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_2, EventBranchId::BRANCH_6) + .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("SingleAppUpdateFlowControl failed"); + if (record != nullptr) { + NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + } + return ERR_ANS_OVER_MAX_UPDATE_PERSECOND; + } + return ERR_OK; +} + +void AdvancedNotificationService::UpdateSingleAppFlowCtrlRemoveExpire(std::chrono::system_clock::time_point now) +{ + std::lock_guard lock(singleAppFlowControlMutex_); + for (auto iter = singleAppFlowControlUpdateTimestampMap_.begin(); + iter != singleAppFlowControlUpdateTimestampMap_.end();) { + auto latest = iter->second->back(); + if (std::chrono::abs(now - latest) > SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME) { + iter = singleAppFlowControlUpdateTimestampMap_.erase(iter); + } else { + ++iter; + } } +} + +ErrCode AdvancedNotificationService::UpdateInNotificationList(const std::shared_ptr &record) +{ auto iter = notificationList_.begin(); while (iter != notificationList_.end()) { if ((*iter)->notification->GetKey() == record->notification->GetKey()) { @@ -1485,36 +1565,31 @@ static bool SortNotificationsByLevelAndTime( return (first->request->GetCreateTime() < second->request->GetCreateTime()); } -ErrCode AdvancedNotificationService::FlowControl(const std::shared_ptr &record) +ErrCode AdvancedNotificationService::FlowControl(const std::shared_ptr &record, + const int32_t callingUid) { if (record->isNeedFlowCtrl == false) { return ERR_OK; } - HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_4, EventBranchId::BRANCH_2); - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - ANS_LOGD("FlowControl size %{public}zu,%{public}zu", - flowControlTimestampList_.size(), systemFlowControlTimestampList_.size()); - if (record->isThirdparty == true) { - std::lock_guard lock(flowControlMutex_); - NotificationAnalyticsUtil::RemoveExpired(flowControlTimestampList_, now); - if (flowControlTimestampList_.size() >= MAX_ACTIVE_NUM_PERSECOND + MAX_UPDATE_NUM_PERSECOND) { - message.ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + + ErrCode result = ERR_OK; + if (!IsNotificationExists(record->notification->GetKey())) { + if (record->request->IsUpdateOnly()) { + ANS_LOGE("Notification not exists when update"); + HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_3, EventBranchId::BRANCH_3) + .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("Nft not exist"); NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); - return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; + return ERR_ANS_NOTIFICATION_NOT_EXISTS; } - flowControlTimestampList_.push_back(now); + result = PublishFlowCtrl(record, callingUid); } else { - std::lock_guard lock(systemFlowControlMutex_); - NotificationAnalyticsUtil::RemoveExpired(systemFlowControlTimestampList_, now); - if (systemFlowControlTimestampList_.size() >= MAX_ACTIVE_NUM_PERSECOND + MAX_UPDATE_NUM_PERSECOND) { - message.ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); - NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); - return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; + if (record->request->IsAlertOneTime()) { + CloseAlert(record); } - systemFlowControlTimestampList_.push_back(now); + result = UpdateFlowCtrl(record, callingUid); } - return ERR_OK; + return result; } bool AdvancedNotificationService::IsSystemUser(int32_t userId) @@ -1522,50 +1597,116 @@ bool AdvancedNotificationService::IsSystemUser(int32_t userId) return ((userId >= SUBSCRIBE_USER_SYSTEM_BEGIN) && (userId <= SUBSCRIBE_USER_SYSTEM_END)); } -ErrCode AdvancedNotificationService::PublishFlowControlInner(const std::shared_ptr &record) +ErrCode AdvancedNotificationService::PublishFlowCtrl(const std::shared_ptr &record, + const int32_t callingUid) { if (record->isNeedFlowCtrl == false) { return ERR_OK; } std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - ANS_LOGD("PublishFlowControl size %{public}zu,%{public}zu", + ErrCode result = ERR_OK; + result = PublishSingleAppFlowCtrl(record, now, callingUid); + if (result != ERR_OK) { + return result; + } + result = PublishGlobalFlowCtrl(record, now); + if (result != ERR_OK) { + return result; + } + if (record->isThirdparty == true) { + std::lock_guard lock(flowControlMutex_); + flowControlPublishTimestampList_.push_back(now); + } else { + std::lock_guard lock(systemFlowControlMutex_); + systemFlowControlPublishTimestampList_.push_back(now); + } + + { + std::lock_guard lock(singleAppFlowControlMutex_); + auto singleAppFlowControlIter = singleAppFlowControlPublishTimestampMap_.find(callingUid); + if (singleAppFlowControlIter == singleAppFlowControlPublishTimestampMap_.end()) { + singleAppFlowControlPublishTimestampMap_[callingUid] = + std::make_shared>(); + singleAppFlowControlIter = singleAppFlowControlPublishTimestampMap_.find(callingUid); + } + singleAppFlowControlIter->second->push_back(now); + } + PublishSingleAppFlowCtrlRemoveExpire(now); + return ERR_OK; +} + +ErrCode AdvancedNotificationService::PublishGlobalFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now) +{ + ANS_LOGD("PublishGlobalFlowCtrl size %{public}zu,%{public}zu", flowControlPublishTimestampList_.size(), systemFlowControlPublishTimestampList_.size()); if (record->isThirdparty == true) { // 三方流控 std::lock_guard lock(flowControlMutex_); NotificationAnalyticsUtil::RemoveExpired(flowControlPublishTimestampList_, now); - if (flowControlPublishTimestampList_.size() >= MAX_ACTIVE_NUM_PERSECOND) { + if (flowControlPublishTimestampList_.size() >= maxCreateNumPerSecond) { + ANS_LOGE("Third-part PublishGlobalFlowCtrl failed"); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_2, EventBranchId::BRANCH_3) - .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("PublishFlowControl failed"); + .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("PublishGlobalFlowCtrl failed"); if (record != nullptr) { NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); } return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; } - flowControlPublishTimestampList_.push_back(now); } else { // 系统流控 std::lock_guard lock(systemFlowControlMutex_); NotificationAnalyticsUtil::RemoveExpired(systemFlowControlPublishTimestampList_, now); - if (systemFlowControlPublishTimestampList_.size() >= MAX_ACTIVE_NUM_PERSECOND) { + if (systemFlowControlPublishTimestampList_.size() >= maxCreateNumPerSecond) { + ANS_LOGE("System PublishGlobalFlowCtrl failed"); HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_2, EventBranchId::BRANCH_3) - .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("PublishFlowControl failed"); + .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("PublishGlobalFlowCtrl failed"); if (record != nullptr) { NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); } return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; } - systemFlowControlPublishTimestampList_.push_back(now); } return ERR_OK; } -ErrCode AdvancedNotificationService::PublishFlowControl(const std::shared_ptr &record) +ErrCode AdvancedNotificationService::PublishSingleAppFlowCtrl(const std::shared_ptr &record, + std::chrono::system_clock::time_point now, const int32_t callingUid) { - ErrCode result = PublishFlowControlInner(record); - if (result != ERR_OK) { - return result; + std::lock_guard lock(singleAppFlowControlMutex_); + auto singleAppFlowControlIter = singleAppFlowControlPublishTimestampMap_.find(callingUid); + if (singleAppFlowControlIter == singleAppFlowControlPublishTimestampMap_.end()) { + return ERR_OK; } + NotificationAnalyticsUtil::RemoveExpired(*(singleAppFlowControlIter->second), now); + if (singleAppFlowControlIter->second->size() >= maxCreateNumPerSecondPerApp) { + ANS_LOGE("SingleAppPublishFlowControl failed"); + HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_2, EventBranchId::BRANCH_6) + .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("SingleAppPublishFlowControl failed"); + if (record != nullptr) { + NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + } + return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; + } + return ERR_OK; +} + +void AdvancedNotificationService::PublishSingleAppFlowCtrlRemoveExpire(std::chrono::system_clock::time_point now) +{ + std::lock_guard lock(singleAppFlowControlMutex_); + for (auto iter = singleAppFlowControlPublishTimestampMap_.begin(); + iter != singleAppFlowControlPublishTimestampMap_.end();) { + auto latest = iter->second->back(); + if (std::chrono::abs(now - latest) > SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME) { + iter = singleAppFlowControlPublishTimestampMap_.erase(iter); + } else { + ++iter; + } + } +} + +ErrCode AdvancedNotificationService::PublishInNotificationList(const std::shared_ptr &record) +{ std::list> bundleList; for (auto item : notificationList_) { if (record->notification->GetBundleName() == item->notification->GetBundleName()) { @@ -2330,5 +2471,42 @@ void AdvancedNotificationService::RemoveNotificationList(const std::shared_ptrGetConfigJson(JsonPoint, root)) { + ANS_LOGE("Failed to get JsonPoint CCM config file"); + return; + } + if (!root.contains(NotificationConfigParse::CFG_KEY_NOTIFICATION_SERVICE)) { + ANS_LOGW("GetFlowCtrlConfigFromCCM not found jsonKey"); + return; + } + nlohmann::json affects = root[NotificationConfigParse::CFG_KEY_NOTIFICATION_SERVICE]; + if (affects.is_null() || affects.empty()) { + ANS_LOGE("GetFlowCtrlConfigFromCCM failed as invalid ccmFlowCtrlConfig json"); + return; + } + if (affects.contains(NotificationConfigParse::CFG_KEY_MAX_CREATE_NUM_PERSECOND)) { + maxCreateNumPerSecond = affects[NotificationConfigParse::CFG_KEY_MAX_CREATE_NUM_PERSECOND]; + } + + if (affects.contains(NotificationConfigParse::CFG_KEY_MAX_UPDATE_NUM_PERSECOND)) { + maxUpdateNumPerSecond = affects[NotificationConfigParse::CFG_KEY_MAX_UPDATE_NUM_PERSECOND]; + } + + if (affects.contains(NotificationConfigParse::CFG_KEY_MAX_CREATE_NUM_PERSECOND_PERAPP)) { + maxCreateNumPerSecondPerApp = affects[NotificationConfigParse::CFG_KEY_MAX_CREATE_NUM_PERSECOND_PERAPP]; + } + + if (affects.contains(NotificationConfigParse::CFG_KEY_MAX_UPDATE_NUM_PERSECOND_PERAPP)) { + maxUpdateNumPerSecondPerApp = affects[NotificationConfigParse::CFG_KEY_MAX_UPDATE_NUM_PERSECOND_PERAPP]; + } + + ANS_LOGI("GetFlowCtrlConfigFromCCM success"); +} } // namespace Notification } // namespace OHOS diff --git a/services/ans/src/advanced_notification_utils.cpp b/services/ans/src/advanced_notification_utils.cpp index f25fd804e869461b98184411b0d100f331e72e71..bcd8f9ccfae2b4ec904ee0d158b6629d98cd39ac 100644 --- a/services/ans/src/advanced_notification_utils.cpp +++ b/services/ans/src/advanced_notification_utils.cpp @@ -945,7 +945,8 @@ void AdvancedNotificationService::OnDistributedPublish( ANS_LOGE("notificationSvrQueue_ is nullptr."); return; } - notificationSvrQueue_->submit(std::bind([this, deviceId, bundleName, request, activeUserId]() { + const int32_t callingUid = IPCSkeleton::GetCallingUid(); + notificationSvrQueue_->submit(std::bind([this, deviceId, bundleName, request, activeUserId, callingUid]() { ANS_LOGD("ffrt enter!"); if (!CheckDistributedNotificationType(request)) { ANS_LOGD("CheckDistributedNotificationType is false."); @@ -995,7 +996,11 @@ void AdvancedNotificationService::OnDistributedPublish( return; } - result = PublishFlowControl(record); + result = FlowControl(record, callingUid); + if (result != ERR_OK) { + return; + } + result = PublishInNotificationList(record); if (result != ERR_OK) { return; } diff --git a/services/ans/test/unittest/advanced_notification_service_test.cpp b/services/ans/test/unittest/advanced_notification_service_test.cpp index e51e6876924ee52bb44c4b7aadbc1aeca34fbe70..eba34c5b10a61a868754ae8bb492dde3a6715743 100644 --- a/services/ans/test/unittest/advanced_notification_service_test.cpp +++ b/services/ans/test/unittest/advanced_notification_service_test.cpp @@ -3362,6 +3362,57 @@ HWTEST_F(AdvancedNotificationServiceTest, AssignToNotificationList_00001, Functi ASSERT_EQ(advancedNotificationService_->notificationList_.size(), 1); } +/** + * @tc.name: AssignToNotificationList_00002 + * @tc.desc: Test AssignToNotificationList when NotificationRequest's updateOnly is true but notification ID not exists + * @tc.type: FUNC + */ +HWTEST_F(AdvancedNotificationServiceTest, AssignToNotificationList_00002, Function | SmallTest | Level1) +{ + advancedNotificationService_->notificationList_.clear(); + auto slotType = NotificationConstant::SlotType::LIVE_VIEW; + sptr request = new (std::nothrow) NotificationRequest(); + request->SetUpdateOnly(true); + auto bundle = new NotificationBundleOption(TEST_DEFUALT_BUNDLE, SYSTEM_APP_UID); + auto liveViewContent = std::make_shared(); + std::shared_ptr content = std::make_shared(liveViewContent); + request->SetContent(content); + request->SetSlotType(slotType); + request->SetNotificationId(1); + auto record = advancedNotificationService_->MakeNotificationRecord(request, bundle); + auto ret = advancedNotificationService_->AssignToNotificationList(record); + + ASSERT_EQ(ret, (int)ERR_ANS_NOTIFICATION_NOT_EXISTS); + ASSERT_EQ(advancedNotificationService_->notificationList_.size(), 0); + advancedNotificationService_->notificationList_.clear(); +} + +/** + * @tc.name: AssignToNotificationList_00003 + * @tc.desc: Test AssignToNotificationList when NotificationRequest's updateOnly is true and notification ID exists + * @tc.type: FUNC + */ +HWTEST_F(AdvancedNotificationServiceTest, AssignToNotificationList_00003, Function | SmallTest | Level1) +{ + advancedNotificationService_->notificationList_.clear(); + auto slotType = NotificationConstant::SlotType::LIVE_VIEW; + sptr request = new (std::nothrow) NotificationRequest(); + request->SetUpdateOnly(true); + auto bundle = new NotificationBundleOption(TEST_DEFUALT_BUNDLE, SYSTEM_APP_UID); + auto liveViewContent = std::make_shared(); + std::shared_ptr content = std::make_shared(liveViewContent); + request->SetContent(content); + request->SetSlotType(slotType); + request->SetNotificationId(1); + auto record = advancedNotificationService_->MakeNotificationRecord(request, bundle); + advancedNotificationService_->notificationList_.push_back(record); + auto ret = advancedNotificationService_->AssignToNotificationList(record); + + ASSERT_EQ(ret, (int)ERR_OK); + ASSERT_EQ(advancedNotificationService_->notificationList_.size(), 1); + advancedNotificationService_->notificationList_.clear(); +} + /** * @tc.name: StartArchiveTimer_00001 * @tc.desc: Test StartArchiveTimer @@ -3761,5 +3812,401 @@ HWTEST_F(AdvancedNotificationServiceTest, GetExcludeDates_00001, Function | Smal ASSERT_EQ(advancedNotificationService_->GetExcludeDates(reminderId, times), (int)ERR_NO_INIT); MockIsVerfyPermisson(false); } + +/** + * @tc.number : PublishInNotificationList_00001 + * @tc.name : Test PublishInNotificationList + * @tc.desc : Test PublishInNotificationList function when the record->slot is nullptr + * @tc.require : issueI5S4VP + */ +HWTEST_F(AdvancedNotificationServiceTest, PublishInNotificationList_00001, Function | SmallTest | Level1) +{ + for (int i = 0; i < 100; i++) { + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + advancedNotificationService_->notificationList_.push_back(record); + } + ASSERT_EQ(advancedNotificationService_->notificationList_.size(), 100); + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + advancedNotificationService_->PublishInNotificationList(record); + ASSERT_EQ(advancedNotificationService_->notificationList_.size(), 100); +} + +/** + * @tc.number : PublishGlobalFlowCtrl_00001 + * @tc.name : Test PublishGlobalFlowCtrl + * @tc.desc : Test PublishGlobalFlowCtrl + */ +HWTEST_F(AdvancedNotificationServiceTest, PublishGlobalFlowCtrl_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->flowControlPublishTimestampList_.clear(); + advancedNotificationService_->systemFlowControlPublishTimestampList_.clear(); + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isThirdparty = false; + record->isNeedFlowCtrl = true; + ErrCode result = ERR_OK; + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + for (int i = 0; i < advancedNotificationService_->maxCreateNumPerSecond; i++) { + result = advancedNotificationService_->PublishGlobalFlowCtrl(record, now); + advancedNotificationService_->systemFlowControlPublishTimestampList_.push_back(now); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->PublishGlobalFlowCtrl(record, now); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + + record->isThirdparty = true; + for (int i = 0; i < advancedNotificationService_->maxCreateNumPerSecond; i++) { + result = advancedNotificationService_->PublishGlobalFlowCtrl(record, now); + advancedNotificationService_->flowControlPublishTimestampList_.push_back(now); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->PublishGlobalFlowCtrl(record, now); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + + advancedNotificationService_->flowControlPublishTimestampList_.clear(); + advancedNotificationService_->systemFlowControlPublishTimestampList_.clear(); +} + +/** + * @tc.number : PublishSingleAppFlowCtrl_00001 + * @tc.name : Test PublishSingleAppFlowCtrl + * @tc.desc : Test PublishSingleAppFlowCtrl + */ +HWTEST_F(AdvancedNotificationServiceTest, PublishSingleAppFlowCtrl_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isNeedFlowCtrl = true; + ErrCode result = ERR_OK; + const int32_t callingUid = DEFAULT_UID; + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_[callingUid] = + std::make_shared>(); + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + for (int i = 0; i < advancedNotificationService_->maxCreateNumPerSecondPerApp; i++) { + result = advancedNotificationService_->PublishSingleAppFlowCtrl(record, now, callingUid); + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_[callingUid]->push_back(now); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->PublishSingleAppFlowCtrl(record, now, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); +} + +/** + * @tc.number : PublishSingleAppFlowCtrlRemoveExpire_00001 + * @tc.name : Test PublishSingleAppFlowCtrlRemoveExpire + * @tc.desc : Test PublishSingleAppFlowCtrlRemoveExpire + */ +HWTEST_F(AdvancedNotificationServiceTest, PublishSingleAppFlowCtrlRemoveExpire_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); + + int32_t callingUid = DEFAULT_UID; + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_[callingUid] = + std::make_shared>(); + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_[callingUid]->push_back(now); + callingUid = NON_SYSTEM_APP_UID; + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_[callingUid] = + std::make_shared>(); + now = now + SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME; + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_[callingUid]->push_back(now); + now = now + SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME; + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.size(), 2); + advancedNotificationService_->PublishSingleAppFlowCtrlRemoveExpire(now); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.size(), 1); + now = now + SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME; + advancedNotificationService_->PublishSingleAppFlowCtrlRemoveExpire(now); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.size(), 0); + + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); +} + +/** + * @tc.number : PublishFlowCtrl_00001 + * @tc.name : Test PublishFlowCtrl + * @tc.desc : Test PublishFlowCtrl + */ +HWTEST_F(AdvancedNotificationServiceTest, PublishFlowCtrl_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->flowControlPublishTimestampList_.clear(); + advancedNotificationService_->systemFlowControlPublishTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isThirdparty = false; + record->isNeedFlowCtrl = true; + ErrCode result = ERR_OK; + int32_t callingUid = DEFAULT_UID; + + // single app flow control test + for (int i = 0; i < advancedNotificationService_->maxCreateNumPerSecondPerApp; i++) { + result = advancedNotificationService_->PublishFlowCtrl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->PublishFlowCtrl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.size(), 1); + + // global flow control test + int gap = advancedNotificationService_->maxCreateNumPerSecond - + advancedNotificationService_->maxCreateNumPerSecondPerApp; + callingUid = NON_SYSTEM_APP_UID; + for (int i = 0; i < gap; i++) { + result = advancedNotificationService_->PublishFlowCtrl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->PublishFlowCtrl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.size(), 2); + + advancedNotificationService_->flowControlPublishTimestampList_.clear(); + advancedNotificationService_->systemFlowControlPublishTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); +} + +/** + * @tc.number : UpdateGlobalFlowCtrl_00001 + * @tc.name : Test UpdateGlobalFlowCtrl + * @tc.desc : Test UpdateGlobalFlowCtrl + */ +HWTEST_F(AdvancedNotificationServiceTest, UpdateGlobalFlowCtrl_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->flowControlUpdateTimestampList_.clear(); + advancedNotificationService_->systemFlowControlUpdateTimestampList_.clear(); + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isThirdparty = false; + record->isNeedFlowCtrl = true; + ErrCode result = ERR_OK; + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + for (int i = 0; i < advancedNotificationService_->maxUpdateNumPerSecond; i++) { + result = advancedNotificationService_->UpdateGlobalFlowCtrl(record, now); + advancedNotificationService_->systemFlowControlUpdateTimestampList_.push_back(now); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->UpdateGlobalFlowCtrl(record, now); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + + record->isThirdparty = true; + for (int i = 0; i < advancedNotificationService_->maxUpdateNumPerSecond; i++) { + result = advancedNotificationService_->UpdateGlobalFlowCtrl(record, now); + advancedNotificationService_->flowControlUpdateTimestampList_.push_back(now); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->UpdateGlobalFlowCtrl(record, now); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + + advancedNotificationService_->flowControlUpdateTimestampList_.clear(); + advancedNotificationService_->systemFlowControlUpdateTimestampList_.clear(); +} + +/** + * @tc.number : UpdateSingleAppFlowCtrl_00001 + * @tc.name : Test UpdateSingleAppFlowCtrl + * @tc.desc : Test UpdateSingleAppFlowCtrl + */ +HWTEST_F(AdvancedNotificationServiceTest, UpdateSingleAppFlowCtrl_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isNeedFlowCtrl = true; + ErrCode result = ERR_OK; + const int32_t callingUid = DEFAULT_UID; + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_[callingUid] = + std::make_shared>(); + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + for (int i = 0; i < advancedNotificationService_->maxUpdateNumPerSecondPerApp; i++) { + result = advancedNotificationService_->UpdateSingleAppFlowCtrl(record, now, callingUid); + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_[callingUid]->push_back(now); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->UpdateSingleAppFlowCtrl(record, now, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); +} + +/** + * @tc.number : UpdateSingleAppFlowCtrlRemoveExpire_00001 + * @tc.name : Test UpdateSingleAppFlowCtrlRemoveExpire + * @tc.desc : Test UpdateSingleAppFlowCtrlRemoveExpire + */ +HWTEST_F(AdvancedNotificationServiceTest, UpdateSingleAppFlowCtrlRemoveExpire_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); + + int32_t callingUid = DEFAULT_UID; + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_[callingUid] = + std::make_shared>(); + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_[callingUid]->push_back(now); + callingUid = NON_SYSTEM_APP_UID; + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_[callingUid] = + std::make_shared>(); + now = now + SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME; + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_[callingUid]->push_back(now); + now = now + SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME; + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.size(), 2); + advancedNotificationService_->UpdateSingleAppFlowCtrlRemoveExpire(now); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.size(), 1); + now = now + SINGLE_APP_FLOW_CONTRL_EXPIRE_TIME; + advancedNotificationService_->UpdateSingleAppFlowCtrlRemoveExpire(now); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.size(), 0); + + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); +} + +/** + * @tc.number : UpdateFlowCtrl_00001 + * @tc.name : Test UpdateFlowCtrl + * @tc.desc : Test UpdateFlowCtrl + */ +HWTEST_F(AdvancedNotificationServiceTest, UpdateFlowCtrl_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->flowControlUpdateTimestampList_.clear(); + advancedNotificationService_->systemFlowControlUpdateTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isThirdparty = false; + record->isNeedFlowCtrl = true; + ErrCode result = ERR_OK; + int32_t callingUid = DEFAULT_UID; + + // single app flow control test + for (int i = 0; i < advancedNotificationService_->maxUpdateNumPerSecondPerApp; i++) { + result = advancedNotificationService_->UpdateFlowCtrl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->UpdateFlowCtrl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.size(), 1); + + // global flow control test + int gap = advancedNotificationService_->maxUpdateNumPerSecond - + advancedNotificationService_->maxUpdateNumPerSecondPerApp; + callingUid = NON_SYSTEM_APP_UID; + for (int i = 0; i < gap; i++) { + result = advancedNotificationService_->UpdateFlowCtrl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->UpdateFlowCtrl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.size(), 2); + + advancedNotificationService_->flowControlUpdateTimestampList_.clear(); + advancedNotificationService_->systemFlowControlUpdateTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); +} + +/** + * @tc.number : FlowControl_00001 + * @tc.name : Test FlowControl + * @tc.desc : Test FlowControl + */ +HWTEST_F(AdvancedNotificationServiceTest, FlowControl_00001, Function | SmallTest | Level1) +{ + advancedNotificationService_->flowControlPublishTimestampList_.clear(); + advancedNotificationService_->systemFlowControlPublishTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); + advancedNotificationService_->flowControlUpdateTimestampList_.clear(); + advancedNotificationService_->systemFlowControlUpdateTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); + advancedNotificationService_->notificationList_.clear(); + + sptr request = new (std::nothrow) NotificationRequest(); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isThirdparty = false; + record->isNeedFlowCtrl = true; + ErrCode result = ERR_OK; + int32_t callingUid = DEFAULT_UID; + + // create flow control + // single app flow control test + for (int i = 0; i < advancedNotificationService_->maxCreateNumPerSecondPerApp; i++) { + result = advancedNotificationService_->FlowControl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->FlowControl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.size(), 1); + + // global flow control test + int gap = advancedNotificationService_->maxCreateNumPerSecond - + advancedNotificationService_->maxCreateNumPerSecondPerApp; + callingUid = NON_SYSTEM_APP_UID; + for (int i = 0; i < gap; i++) { + result = advancedNotificationService_->FlowControl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->FlowControl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.size(), 2); + + advancedNotificationService_->notificationList_.push_back(record); + // update flow control + // single app flow control test + callingUid = DEFAULT_UID; + for (int i = 0; i < advancedNotificationService_->maxUpdateNumPerSecondPerApp; i++) { + result = advancedNotificationService_->FlowControl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->FlowControl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.size(), 1); + + // global flow control test + gap = advancedNotificationService_->maxUpdateNumPerSecond - + advancedNotificationService_->maxUpdateNumPerSecondPerApp; + callingUid = NON_SYSTEM_APP_UID; + for (int i = 0; i < gap; i++) { + result = advancedNotificationService_->FlowControl(record, callingUid); + } + ASSERT_EQ(result, (int)ERR_OK); + result = advancedNotificationService_->FlowControl(record, callingUid); + ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + ASSERT_EQ(advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.size(), 2); + + advancedNotificationService_->flowControlPublishTimestampList_.clear(); + advancedNotificationService_->systemFlowControlPublishTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlPublishTimestampMap_.clear(); + advancedNotificationService_->flowControlUpdateTimestampList_.clear(); + advancedNotificationService_->systemFlowControlUpdateTimestampList_.clear(); + advancedNotificationService_->singleAppFlowControlUpdateTimestampMap_.clear(); + advancedNotificationService_->notificationList_.clear(); +} } // namespace Notification } // namespace OHOS diff --git a/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_service_publish_test.cpp b/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_service_publish_test.cpp index a25c5be8371941f0f315eda8866b80536f0f0d6c..5e164addcb93dc042928d839a63bd5e7b5bc4866 100644 --- a/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_service_publish_test.cpp +++ b/services/ans/test/unittest/advanced_notification_service_test/advanced_notification_service_publish_test.cpp @@ -217,41 +217,6 @@ HWTEST_F(AdvancedNotificationServiceTest, AdvancedNotificationServiceTest_00100, SleepForFC(); } -/** - * @tc.number : ANS_Publish_Update_Flow_00100 - * @tc.name : ANSPublish00100 - * @tc.desc : Publish a normal text type notification 30 times,trigger flow. - */ -HWTEST_F(AdvancedNotificationServiceTest, AdvancedNotificationServiceUpdateFlowTest_00100, Function | SmallTest | Level1) -{ - TestAddSlot(NotificationConstant::SlotType::OTHER); - MockGetTokenTypeFlag(Security::AccessToken::ATokenTypeEnum::TOKEN_HAP); - MockIsSystemApp(true); - sptr req = new NotificationRequest(1); - EXPECT_NE(req, nullptr); - req->SetSlotType(NotificationConstant::SlotType::OTHER); - req->SetLabel("req's label update flow"); - req->SetCreatorUid(1); - std::string label = "publish's label"; - std::shared_ptr normalContent = std::make_shared(); - EXPECT_NE(normalContent, nullptr); - normalContent->SetText("normalContent's text"); - normalContent->SetTitle("normalContent's title"); - std::shared_ptr content = std::make_shared(normalContent); - EXPECT_NE(content, nullptr); - req->SetContent(content); - int count = 30; - for (uint64_t i = 1; i <= 30; ++i) { - if (i <= 21) { - ASSERT_EQ(advancedNotificationService_->Publish(label, req), (int)ERR_OK); - } else { - ASSERT_EQ(advancedNotificationService_->Publish(label, req), (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); - } - } - SleepForFC(); -} - - /** * @tc.number : ANS_Publish_00200 * @tc.name : ANSPublish00200 diff --git a/test/fuzztest/advancednotificationservice_fuzzer/advancednotificationservice_fuzzer.cpp b/test/fuzztest/advancednotificationservice_fuzzer/advancednotificationservice_fuzzer.cpp index 181babfe79fc59f9a568e7af495327ce2b2c2969..b1629b7e81aca88aae126cf66e024f6a02770a41 100644 --- a/test/fuzztest/advancednotificationservice_fuzzer/advancednotificationservice_fuzzer.cpp +++ b/test/fuzztest/advancednotificationservice_fuzzer/advancednotificationservice_fuzzer.cpp @@ -291,7 +291,7 @@ namespace OHOS { service->ChangeNotificationByControlFlags(record, fuzzData.GenerateRandomBool()); service->CheckPublishPreparedNotification(record, fuzzData.GenerateRandomBool()); service->UpdateInNotificationList(record); - service->PublishFlowControl(record); + service->PublishInNotificationList(record); service->IsNeedPushCheck(request); return true; }