From 010d884334075111d9164dc79ca5aa6b3dcdfb77 Mon Sep 17 00:00:00 2001 From: "yangjun (CI)" Date: Sun, 18 May 2025 14:54:40 +0800 Subject: [PATCH] =?UTF-8?q?ANS=E6=B5=81=E6=8E=A7=E8=A7=84=E6=A0=BC?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=EF=BC=8C=E5=8C=BA=E5=88=86=E5=AE=9E=E5=86=B5?= =?UTF-8?q?=E6=B5=81=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangjun Signed-off-by: yangjun (CI) --- .../core/common/include/ans_const_define.h | 2 +- ...vanced_notification_flow_control_service.h | 147 +++-- ...nced_notification_flow_control_service.cpp | 490 ++++++++++------- .../advanced_notification_publish_service.cpp | 4 +- .../ans/src/advanced_notification_service.cpp | 2 +- .../ans/src/advanced_notification_utils.cpp | 4 +- ...notification_flow_control_service_test.cpp | 504 ++++++++++++++---- 7 files changed, 807 insertions(+), 346 deletions(-) diff --git a/frameworks/core/common/include/ans_const_define.h b/frameworks/core/common/include/ans_const_define.h index 6b80bf344..c8dcc2afd 100644 --- a/frameworks/core/common/include/ans_const_define.h +++ b/frameworks/core/common/include/ans_const_define.h @@ -31,7 +31,7 @@ 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 std::chrono::seconds CALLER_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/services/ans/include/advanced_notification_flow_control_service.h b/services/ans/include/advanced_notification_flow_control_service.h index cb182f817..646ddf81f 100644 --- a/services/ans/include/advanced_notification_flow_control_service.h +++ b/services/ans/include/advanced_notification_flow_control_service.h @@ -25,6 +25,7 @@ #include "singleton.h" #include "ans_const_define.h" #include "notification_record.h" +#include "notification_analytics_util.h" namespace OHOS { namespace Notification { @@ -35,45 +36,127 @@ struct FlowControlThreshold { uint32_t maxUpdateNumPerSecondPerApp = MAX_UPDATE_NUM_PERSECOND_PERAPP; }; -class FlowControlService : public DelayedSingleton { +struct FlowControlErrMsg { + std::string msg; + EventSceneId sceneId; + EventBranchId EventBranchId; + ErrCode errCode; +}; + +enum FlowControlSceneType { + GLOBAL_SYSTEM_NORMAL_CREATE, + GLOBAL_SYSTEM_NORMAL_UPDATE, + GLOBAL_SYSTEM_LIVEVIEW_CREATE, + GLOBAL_SYSTEM_LIVEVIEW_UPDATE, + GLOBAL_THIRD_PART_NORMAL_CREATE, + GLOBAL_THIRD_PART_NORMAL_UPDATE, + GLOBAL_THIRD_PART_LIVEVIEW_CREATE, + GLOBAL_THIRD_PART_LIVEVIEW_UPDATE, + CALLER_SYSTEM_NORMAL_CREATE, + CALLER_SYSTEM_NORMAL_UPDATE, + CALLER_SYSTEM_LIVEVIEW_CREATE, + CALLER_SYSTEM_LIVEVIEW_UPDATE, + CALLER_THIRD_PART_NORMAL_CREATE, + CALLER_THIRD_PART_NORMAL_UPDATE, + CALLER_THIRD_PART_LIVEVIEW_CREATE, + CALLER_THIRD_PART_LIVEVIEW_UPDATE, +}; + +class GlobalFlowController { public: - FlowControlService(); - ErrCode FlowControl(const std::shared_ptr &record, - const int32_t callingUid, bool isNotificationExists); + using TimePoint = std::chrono::system_clock::time_point; + GlobalFlowController(const uint32_t threshold, const FlowControlErrMsg& errMsg) + : threshold_(threshold), errMsg_(errMsg) {} + + /** + * @brief Flow control for all apps. + * + * @param record Notification record. User should ensure that record is not nullptr. + * @param now Current time. + * @return Returns ERR_OK when the call frequency doesn't reach the threshold. + */ + ErrCode FlowControl(const std::shared_ptr record, const TimePoint &now); + + /** + * @brief Add a timestamp to flow control list. + * + * @param now Current time. + */ + void RecordTimestamp(const TimePoint &now); + +private: + uint32_t threshold_; + FlowControlErrMsg errMsg_; + std::mutex globalFlowControllerMutex_; + std::list globalFlowControllerList_; +}; +class CallerFlowController { +public: + using TimePoint = std::chrono::system_clock::time_point; + CallerFlowController(const uint32_t threshold, const FlowControlErrMsg& errMsg) + : threshold_(threshold), errMsg_(errMsg) {} + + /** + * @brief Flow control for specified app which owns the notification. + * + * @param record Notification record. User should ensure that record is not nullptr. + * @param callingUid Uid of caller. + * @param now Current time. + * @return Returns ERR_OK when the call frequency doesn't reach the threshold. + */ + ErrCode FlowControl( + const std::shared_ptr record, const int32_t callingUid, const TimePoint &now); + + /** + * @brief Add a timestamp to flow control list. + * + * @param record Notification record to acquire owner uid of notification. User should ensure that record is not nullptr. + * @param callingUid Uid of caller. + * @param now Current time. + */ + void RecordTimestamp( + const std::shared_ptr record, const int32_t callingUid, const TimePoint &now); + + /** + * @brief Remove expired appliacation record. + * + * @param now Current time. + */ + void RemoveExpired(const TimePoint &now); private: - 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 PublishRecordTimestamp(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); - - 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 UpdateRecordTimestamp(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); + uint32_t threshold_; + FlowControlErrMsg errMsg_; + std::mutex callerFlowControllerMutex_; + std::map>> callerFlowControllerMapper_; +}; + +class FlowControlService { +public: + DISALLOW_COPY_AND_MOVE(FlowControlService); + static FlowControlService& GetInstance(); + + /** + * @brief Flow control total entrance. + * + * @param record Notification record. User should ensure that record is not nullptr. + * @param callingUid Uid of caller. + * @param isNotificationExists true when update notification and false when create notification. + */ + ErrCode FlowControl( + const std::shared_ptr record, const int32_t callingUid, bool isNotificationExists); private: - static std::mutex flowControlMutex_; - std::list flowControlUpdateTimestampList_; - std::list flowControlPublishTimestampList_; - static std::mutex systemFlowControlMutex_; - std::list systemFlowControlUpdateTimestampList_; - std::list systemFlowControlPublishTimestampList_; - static std::mutex singleAppFlowControlMutex_; - std::map>> singleAppFlowControlUpdateTimestampMap_; - std::map>> singleAppFlowControlPublishTimestampMap_; + FlowControlService(); + void InitGlobalFlowControl(); + void InitCallerFlowControl(); + std::pair GetSceneTypePair( + const std::shared_ptr record, bool isNotificationExists); +private: FlowControlThreshold threshold_; + std::map> globalFlowControllerMapper_; + std::map> callerFlowControllerMapper_; }; } // namespace Notification } // namespace OHOS diff --git a/services/ans/src/advanced_notification_flow_control_service.cpp b/services/ans/src/advanced_notification_flow_control_service.cpp index 78ffa1be3..ad54e01fb 100644 --- a/services/ans/src/advanced_notification_flow_control_service.cpp +++ b/services/ans/src/advanced_notification_flow_control_service.cpp @@ -15,262 +15,364 @@ #include "advanced_notification_flow_control_service.h" +#include +#include + #include "ans_inner_errors.h" #include "notification_config_parse.h" -#include "notification_analytics_util.h" namespace OHOS { namespace Notification { -std::mutex FlowControlService::flowControlMutex_; -std::mutex FlowControlService::systemFlowControlMutex_; -std::mutex FlowControlService::singleAppFlowControlMutex_; +using TimePoint = std::chrono::system_clock::time_point; +constexpr int32_t TIME_GAP_FOR_SECOND = 1; -FlowControlService::FlowControlService() +void RemoveExpiredTimestamp(std::list &list, const TimePoint &now) { - DelayedSingleton::GetInstance()->GetFlowCtrlConfigFromCCM(threshold_); + auto iter = list.begin(); + while (iter != list.end()) { + if (abs(now - *iter) > std::chrono::seconds(TIME_GAP_FOR_SECOND)) { + iter = list.erase(iter); + } else { + break; + } + } } -ErrCode FlowControlService::FlowControl(const std::shared_ptr &record, - const int32_t callingUid, bool isNotificationExists) +ErrCode GlobalFlowController::FlowControl(const std::shared_ptr record, const TimePoint &now) { - if (record->isNeedFlowCtrl == false) { - return ERR_OK; - } - - ErrCode result = ERR_OK; - if (!isNotificationExists) { - if (record->request->IsUpdateOnly()) { - ANS_LOGE("Notification not exists when update"); - return ERR_ANS_NOTIFICATION_NOT_EXISTS; - } - result = PublishFlowCtrl(record, callingUid); - } else { - result = UpdateFlowCtrl(record, callingUid); + std::lock_guard lock(globalFlowControllerMutex_); + RemoveExpiredTimestamp(globalFlowControllerList_, now); + if (globalFlowControllerList_.size() >= threshold_) { + ANS_LOGE("%{public}s", errMsg_.msg.c_str()); + HaMetaMessage message = HaMetaMessage(errMsg_.sceneId, errMsg_.EventBranchId) + .ErrorCode(errMsg_.errCode).Message(errMsg_.msg); + NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + return errMsg_.errCode; } + return ERR_OK; +} - return result; +void GlobalFlowController::RecordTimestamp(const TimePoint &now) +{ + std::lock_guard lock(globalFlowControllerMutex_); + globalFlowControllerList_.push_back(now); } -ErrCode FlowControlService::PublishFlowCtrl(const std::shared_ptr &record, - const int32_t callingUid) +ErrCode CallerFlowController::FlowControl( + const std::shared_ptr record, const int32_t callingUid, const TimePoint &now) { - if (record->isNeedFlowCtrl == false) { + std::lock_guard lock(callerFlowControllerMutex_); + auto callerFlowControlIter = callerFlowControllerMapper_.find(callingUid); + if (callerFlowControlIter == callerFlowControllerMapper_.end()) { return ERR_OK; } - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - 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; + RemoveExpiredTimestamp(*(callerFlowControlIter->second), now); + if (callerFlowControlIter->second->size() >= threshold_) { + ANS_LOGE("%{public}s", errMsg_.msg.c_str()); + HaMetaMessage message = HaMetaMessage(errMsg_.sceneId, errMsg_.EventBranchId) + .ErrorCode(errMsg_.errCode).Message(errMsg_.msg); + NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + return errMsg_.errCode; } - PublishRecordTimestamp(record, now, callingUid); - PublishSingleAppFlowCtrlRemoveExpire(now); return ERR_OK; } -ErrCode FlowControlService::PublishGlobalFlowCtrl(const std::shared_ptr &record, - std::chrono::system_clock::time_point now) +void CallerFlowController::RecordTimestamp( + const std::shared_ptr record, const int32_t callingUid, const TimePoint &now) { - ANS_LOGD("PublishGlobalFlowCtrl size %{public}zu,%{public}zu", - flowControlPublishTimestampList_.size(), systemFlowControlPublishTimestampList_.size()); - if (record->isThirdparty == true) { - // Third-part flow control - std::lock_guard lock(flowControlMutex_); - NotificationAnalyticsUtil::RemoveExpired(flowControlPublishTimestampList_, now); - if (flowControlPublishTimestampList_.size() >= threshold_.maxCreateNumPerSecond) { - ANS_LOGE("Third-part PublishGlobalFlowCtrl failed"); - HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_3, EventBranchId::BRANCH_2) - .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("Third-part PublishGlobalFlowCtrl failed"); - if (record != nullptr) { - NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); - } - return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; - } - } else { - // System flow control - std::lock_guard lock(systemFlowControlMutex_); - NotificationAnalyticsUtil::RemoveExpired(systemFlowControlPublishTimestampList_, now); - if (systemFlowControlPublishTimestampList_.size() >= threshold_.maxCreateNumPerSecond) { - ANS_LOGE("System PublishGlobalFlowCtrl failed"); - HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_3, EventBranchId::BRANCH_3) - .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("System PublishGlobalFlowCtrl failed"); - if (record != nullptr) { - NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); - } - return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; - } + std::lock_guard lock(callerFlowControllerMutex_); + auto callerFlowControlIter = callerFlowControllerMapper_.find(callingUid); + if (callerFlowControlIter == callerFlowControllerMapper_.end()) { + callerFlowControllerMapper_[callingUid] = std::make_shared>(); + callerFlowControlIter = callerFlowControllerMapper_.find(callingUid); } - return ERR_OK; + callerFlowControlIter->second->push_back(now); } -ErrCode FlowControlService::PublishSingleAppFlowCtrl(const std::shared_ptr &record, - std::chrono::system_clock::time_point now, const int32_t callingUid) +void CallerFlowController::RemoveExpired(const TimePoint &now) { - 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() >= threshold_.maxCreateNumPerSecondPerApp) { - ANS_LOGE("SingleAppPublishFlowControl failed"); - HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_3, EventBranchId::BRANCH_4) - .ErrorCode(ERR_ANS_OVER_MAX_ACTIVE_PERSECOND).Message("SingleAppPublishFlowControl failed"); - if (record != nullptr) { - NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + std::lock_guard lock(callerFlowControllerMutex_); + for (auto iter = callerFlowControllerMapper_.begin(); iter != callerFlowControllerMapper_.end();) { + auto latest = iter->second->back(); + if (std::chrono::abs(now - latest) > CALLER_FLOW_CONTRL_EXPIRE_TIME) { + iter = callerFlowControllerMapper_.erase(iter); + } else { + ++iter; } - return ERR_ANS_OVER_MAX_ACTIVE_PERSECOND; } - return ERR_OK; } -void FlowControlService::PublishRecordTimestamp(const std::shared_ptr &record, - std::chrono::system_clock::time_point now, const int32_t callingUid) +FlowControlService& FlowControlService::GetInstance() { - if (record->isThirdparty == true) { - std::lock_guard lock(flowControlMutex_); - flowControlPublishTimestampList_.push_back(now); - } else { - std::lock_guard lock(systemFlowControlMutex_); - systemFlowControlPublishTimestampList_.push_back(now); - } + static FlowControlService flowControlService; + return flowControlService; +} + +FlowControlService::FlowControlService() +{ + DelayedSingleton::GetInstance()->GetFlowCtrlConfigFromCCM(threshold_); + InitGlobalFlowControl(); + InitCallerFlowControl(); +} + +void FlowControlService::InitGlobalFlowControl() +{ + std::vector> configs = { + { + FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_CREATE, + threshold_.maxCreateNumPerSecond, + { + .msg = "GLOBAL_SYSTEM_NORMAL_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_0, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_UPDATE, + threshold_.maxUpdateNumPerSecond, + { + .msg = "GLOBAL_SYSTEM_NORMAL_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_1, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + { + FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_CREATE, + threshold_.maxCreateNumPerSecond, + { + .msg = "GLOBAL_SYSTEM_LIVEVIEW_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_2, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_UPDATE, + threshold_.maxUpdateNumPerSecond, + { + .msg = "GLOBAL_SYSTEM_LIVEVIEW_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_3, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + { + FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_CREATE, + threshold_.maxCreateNumPerSecond, + { + .msg = "GLOBAL_THIRD_PART_NORMAL_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_4, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_UPDATE, + threshold_.maxUpdateNumPerSecond, + { + .msg = "GLOBAL_THIRD_PART_NORMAL_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_5, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + { + FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_CREATE, + threshold_.maxCreateNumPerSecond, + { + .msg = "GLOBAL_THIRD_PART_LIVEVIEW_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_6, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_UPDATE, + threshold_.maxUpdateNumPerSecond, + { + .msg = "GLOBAL_THIRD_PART_LIVEVIEW_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_7, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + }; - std::lock_guard lock(singleAppFlowControlMutex_); - auto singleAppFlowControlIter = singleAppFlowControlPublishTimestampMap_.find(callingUid); - if (singleAppFlowControlIter == singleAppFlowControlPublishTimestampMap_.end()) { - singleAppFlowControlPublishTimestampMap_[callingUid] = - std::make_shared>(); - singleAppFlowControlIter = singleAppFlowControlPublishTimestampMap_.find(callingUid); + const int sceneTypeIdx = 0, thresholdIdx = 1, errMsgIdx = 2; + for (auto iter = configs.cbegin(); iter != configs.cend(); ++iter) { + globalFlowControllerMapper_[std::get(*iter)] = + std::make_shared(std::get(*iter), std::get(*iter)); } - singleAppFlowControlIter->second->push_back(now); } -void FlowControlService::PublishSingleAppFlowCtrlRemoveExpire(std::chrono::system_clock::time_point now) +void FlowControlService::InitCallerFlowControl() { - 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; - } + std::vector> configs = { + { + FlowControlSceneType::CALLER_SYSTEM_NORMAL_CREATE, + threshold_.maxCreateNumPerSecondPerApp, + { + .msg = "CALLER_SYSTEM_NORMAL_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_8, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::CALLER_SYSTEM_NORMAL_UPDATE, + threshold_.maxUpdateNumPerSecondPerApp, + { + .msg = "CALLER_SYSTEM_NORMAL_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_9, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + { + FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_CREATE, + threshold_.maxCreateNumPerSecondPerApp, + { + .msg = "CALLER_SYSTEM_LIVEVIEW_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_10, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_UPDATE, + threshold_.maxUpdateNumPerSecondPerApp, + { + .msg = "CALLER_SYSTEM_LIVEVIEW_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_11, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + { + FlowControlSceneType::CALLER_THIRD_PART_NORMAL_CREATE, + threshold_.maxCreateNumPerSecondPerApp, + { + .msg = "CALLER_THIRD_PART_NORMAL_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_12, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::CALLER_THIRD_PART_NORMAL_UPDATE, + threshold_.maxUpdateNumPerSecondPerApp, + { + .msg = "CALLER_THIRD_PART_NORMAL_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_13, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + { + FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_CREATE, + threshold_.maxCreateNumPerSecondPerApp, + { + .msg = "CALLER_THIRD_PART_LIVEVIEW_CREATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_14, + .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND + } + }, + { + FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_UPDATE, + threshold_.maxUpdateNumPerSecondPerApp, + { + .msg = "CALLER_THIRD_PART_LIVEVIEW_UPDATE flow control", + .sceneId = EventSceneId::SCENE_4, + .EventBranchId = EventBranchId::BRANCH_15, + .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND + } + }, + }; + + const int sceneTypeIdx = 0, thresholdIdx = 1, errMsgIdx = 2; + for (auto iter = configs.cbegin(); iter != configs.cend(); ++iter) { + callerFlowControllerMapper_[std::get(*iter)] = + std::make_shared(std::get(*iter), std::get(*iter)); } } -ErrCode FlowControlService::UpdateFlowCtrl(const std::shared_ptr &record, - const int32_t callingUid) +ErrCode FlowControlService::FlowControl( + const std::shared_ptr record, const int32_t callingUid, bool isNotificationExists) { if (record->isNeedFlowCtrl == false) { return ERR_OK; } - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + TimePoint now = std::chrono::system_clock::now(); + + auto sceneTypePair = GetSceneTypePair(record, isNotificationExists); ErrCode result = ERR_OK; - result = UpdateSingleAppFlowCtrl(record, now, callingUid); + auto globalFlowController = globalFlowControllerMapper_[sceneTypePair.first]; + result = globalFlowController->FlowControl(record, now); if (result != ERR_OK) { return result; } - result = UpdateGlobalFlowCtrl(record, now); + + auto callerFlowController = callerFlowControllerMapper_[sceneTypePair.second]; + result = callerFlowController->FlowControl(record, callingUid, now); if (result != ERR_OK) { return result; } - UpdateRecordTimestamp(record, now, callingUid); - UpdateSingleAppFlowCtrlRemoveExpire(now); + + globalFlowController->RecordTimestamp(now); + callerFlowController->RecordTimestamp(record, callingUid, now); + + auto begin = callerFlowControllerMapper_.begin(); + auto end = callerFlowControllerMapper_.end(); + for (auto it = begin; it != end; ++it) { + it->second->RemoveExpired(now); + } return result; } -ErrCode FlowControlService::UpdateGlobalFlowCtrl(const std::shared_ptr &record, - std::chrono::system_clock::time_point now) +std::pair FlowControlService::GetSceneTypePair( + const std::shared_ptr record, bool isNotificationExists) { - ANS_LOGD("UpdateGlobalFlowCtrl size %{public}zu,%{public}zu", - flowControlUpdateTimestampList_.size(), systemFlowControlUpdateTimestampList_.size()); - if (record->isThirdparty == true) { - // Third-part flow control - std::lock_guard lock(flowControlMutex_); - NotificationAnalyticsUtil::RemoveExpired(flowControlUpdateTimestampList_, now); - if (flowControlUpdateTimestampList_.size() >= threshold_.maxUpdateNumPerSecond) { - ANS_LOGE("Third-part UpdateGlobalFlowCtrl failed"); - HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_4, EventBranchId::BRANCH_3) - .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("Third-part updateGlobalFlowCtrl failed"); - if (record != nullptr) { - NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + bool isLiveview = record->request->IsCommonLiveView() || record->request->IsSystemLiveView(); + if (record->isThirdparty) { + // Third-Part caller + if (isLiveview) { + if (isNotificationExists) { + return {FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_UPDATE, + FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_UPDATE}; + } else { + return {FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_CREATE, + FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_CREATE}; } - return ERR_ANS_OVER_MAX_UPDATE_PERSECOND; - } - } else { - // System flow control - std::lock_guard lock(systemFlowControlMutex_); - NotificationAnalyticsUtil::RemoveExpired(systemFlowControlUpdateTimestampList_, now); - if (systemFlowControlUpdateTimestampList_.size() >= threshold_.maxUpdateNumPerSecond) { - ANS_LOGE("System UpdateGlobalFlowCtrl failed"); - HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_4, EventBranchId::BRANCH_4) - .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("System updateGlobalFlowCtrl failed"); - if (record != nullptr) { - NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + } else { + if (isNotificationExists) { + return {FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_UPDATE, + FlowControlSceneType::CALLER_THIRD_PART_NORMAL_UPDATE}; + } else { + return {FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_CREATE, + FlowControlSceneType::CALLER_THIRD_PART_NORMAL_CREATE}; } - return ERR_ANS_OVER_MAX_UPDATE_PERSECOND; } } - return ERR_OK; -} -ErrCode FlowControlService::UpdateSingleAppFlowCtrl(const std::shared_ptr &record, - std::chrono::system_clock::time_point now, const int32_t callingUid) -{ - 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() >= threshold_.maxUpdateNumPerSecondPerApp) { - ANS_LOGE("SingleAppUpdateFlowControl failed"); - HaMetaMessage message = HaMetaMessage(EventSceneId::SCENE_4, EventBranchId::BRANCH_5) - .ErrorCode(ERR_ANS_OVER_MAX_UPDATE_PERSECOND).Message("SingleAppUpdateFlowControl failed"); - if (record != nullptr) { - NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message); + // System caller + if (isLiveview) { + if (isNotificationExists) { + return {FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_UPDATE, + FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_UPDATE}; + } else { + return {FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_CREATE, + FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_CREATE}; } - return ERR_ANS_OVER_MAX_UPDATE_PERSECOND; - } - return ERR_OK; -} - -void FlowControlService::UpdateRecordTimestamp(const std::shared_ptr &record, - std::chrono::system_clock::time_point now, const int32_t callingUid) -{ - 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); -} - -void FlowControlService::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); + if (isNotificationExists) { + return {FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_UPDATE, + FlowControlSceneType::CALLER_SYSTEM_NORMAL_UPDATE}; } else { - ++iter; + return {FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_CREATE, + FlowControlSceneType::CALLER_SYSTEM_NORMAL_CREATE}; } } } diff --git a/services/ans/src/advanced_notification_publish_service.cpp b/services/ans/src/advanced_notification_publish_service.cpp index 4169be732..28d5d5d95 100644 --- a/services/ans/src/advanced_notification_publish_service.cpp +++ b/services/ans/src/advanced_notification_publish_service.cpp @@ -402,7 +402,7 @@ ErrCode AdvancedNotificationService::PublishNotificationForIndirectProxy(const s } bool isNotificationExists = IsNotificationExists(record->notification->GetKey()); - result = FlowControlService::GetInstance()->FlowControl(record, ipcUid, isNotificationExists); + result = FlowControlService::GetInstance().FlowControl(record, ipcUid, isNotificationExists); if (result != ERR_OK) { message.BranchId(EventBranchId::BRANCH_5).ErrorCode(result).Message("publish failed with FlowControl"); return; @@ -2679,7 +2679,7 @@ ErrCode AdvancedNotificationService::PublishNotificationBySa(const sptrnotification->GetKey()); - result = FlowControlService::GetInstance()->FlowControl(record, ipcUid, isNotificationExists); + result = FlowControlService::GetInstance().FlowControl(record, ipcUid, isNotificationExists); if (result != ERR_OK) { return; } diff --git a/services/ans/src/advanced_notification_service.cpp b/services/ans/src/advanced_notification_service.cpp index 3834be392..42170d233 100644 --- a/services/ans/src/advanced_notification_service.cpp +++ b/services/ans/src/advanced_notification_service.cpp @@ -724,7 +724,7 @@ ErrCode AdvancedNotificationService::PublishPreparedNotification(const sptrnotification->GetKey()); - result = FlowControlService::GetInstance()->FlowControl(record, uid, isNotificationExists); + result = FlowControlService::GetInstance().FlowControl(record, uid, isNotificationExists); if (result != ERR_OK) { return; } diff --git a/services/ans/src/advanced_notification_utils.cpp b/services/ans/src/advanced_notification_utils.cpp index 79a69d7ad..d30e15aa4 100644 --- a/services/ans/src/advanced_notification_utils.cpp +++ b/services/ans/src/advanced_notification_utils.cpp @@ -1013,7 +1013,7 @@ void AdvancedNotificationService::OnDistributedPublish( } bool isNotificationExists = IsNotificationExists(record->notification->GetKey()); - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, isNotificationExists); + result = FlowControlService::GetInstance().FlowControl(record, callingUid, isNotificationExists); if (result != ERR_OK) { return; } @@ -1092,7 +1092,7 @@ void AdvancedNotificationService::OnDistributedUpdate( return; } bool isNotificationExists = IsNotificationExists(record->notification->GetKey()); - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, isNotificationExists); + result = FlowControlService::GetInstance().FlowControl(record, callingUid, isNotificationExists); if (result != ERR_OK) { return; } diff --git a/services/ans/test/unittest/advanced_notification_flow_control_service_test.cpp b/services/ans/test/unittest/advanced_notification_flow_control_service_test.cpp index 4a2aaaa0f..0edefea1e 100644 --- a/services/ans/test/unittest/advanced_notification_flow_control_service_test.cpp +++ b/services/ans/test/unittest/advanced_notification_flow_control_service_test.cpp @@ -15,21 +15,15 @@ #include "gtest/gtest.h" -#define private public -#define protected public +#include #include "advanced_notification_flow_control_service.h" #include "ans_const_define.h" #include "ans_inner_errors.h" -#undef private -#undef protected using namespace testing::ext; namespace OHOS { namespace Notification { -namespace { - constexpr int32_t NON_SYSTEM_APP_UID = 1000; -} class FlowControlServiceTest : public testing::Test { public: static void SetUpTestCase(); @@ -46,211 +40,493 @@ void FlowControlServiceTest::SetUp() {} void FlowControlServiceTest::TearDown() {} -/** - * @tc.number : FlowControl_00001 - * @tc.name : Test FlowControl - * @tc.desc : Test FlowControl - */ -HWTEST_F(FlowControlServiceTest, FlowControl_00001, Function | SmallTest | Level1) +std::shared_ptr GetCommonNotificationRecord() { 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; + return record; +} + +std::shared_ptr GetLiveviewNotificationRecord() +{ + auto slotType = NotificationConstant::SlotType::LIVE_VIEW; + sptr request = new (std::nothrow) NotificationRequest(); + request->SetSlotType(slotType); + auto liveContent = std::make_shared(); + auto content = std::make_shared(liveContent); + request->SetContent(content); + sptr notification = new (std::nothrow) Notification(request); + auto record = std::make_shared(); + record->request = request; + record->notification = notification; + record->isNeedFlowCtrl = true; + return record; +} + +/** + * @tc.name: FlowControl_100 + * @tc.desc: Test FlowControl when no need to flow control + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_100, Function | SmallTest | Level1) +{ + std::shared_ptr record = std::make_shared(); + record->isNeedFlowCtrl = false; + auto result = FlowControlService::GetInstance().FlowControl(record, DEFAULT_UID, false); + ASSERT_EQ(result, ERR_OK); +} + +/** + * @tc.name: FlowControl_200 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_CREATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_200, Function | SmallTest | Level1) +{ + auto record = GetCommonNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; + int32_t index = 1; ErrCode result = ERR_OK; - int32_t callingUid = DEFAULT_UID; + uint32_t totalCreate = 0; + while (totalCreate + MAX_CREATE_NUM_PERSECOND_PERAPP < MAX_CREATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + } + totalCreate += MAX_CREATE_NUM_PERSECOND_PERAPP; + index++; + } - // create flow control - // single app flow control test - for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, false); + int gap = MAX_CREATE_NUM_PERSECOND - totalCreate; + for (int i = 0; i < gap; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + } + ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); +} + +/** + * @tc.name: FlowControl_300 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_UPDATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_300, Function | SmallTest | Level1) +{ + auto record = GetCommonNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; + int32_t index = 1; + ErrCode result = ERR_OK; + uint32_t totalCreate = 0; + while (totalCreate + MAX_UPDATE_NUM_PERSECOND_PERAPP < MAX_UPDATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + } + totalCreate += MAX_UPDATE_NUM_PERSECOND_PERAPP; + index++; } - ASSERT_EQ(result, (int)ERR_OK); - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, false); - ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); - // global flow control test - int gap = MAX_CREATE_NUM_PERSECOND - MAX_CREATE_NUM_PERSECOND_PERAPP; - callingUid = NON_SYSTEM_APP_UID; + int gap = MAX_UPDATE_NUM_PERSECOND - totalCreate; for (int i = 0; i < gap; i++) { - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, false); + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); } - ASSERT_EQ(result, (int)ERR_OK); - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, false); - ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + ASSERT_EQ(result, ERR_OK); - // update flow control - // single app flow control test - callingUid = DEFAULT_UID; - for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, true); + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); +} + +/** + * @tc.name: FlowControl_400 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_CREATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_400, Function | SmallTest | Level1) +{ + auto record = GetLiveviewNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; + int32_t index = 1; + ErrCode result = ERR_OK; + uint32_t totalCreate = 0; + while (totalCreate + MAX_CREATE_NUM_PERSECOND_PERAPP < MAX_CREATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + } + totalCreate += MAX_CREATE_NUM_PERSECOND_PERAPP; + index++; } - ASSERT_EQ(result, (int)ERR_OK); - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, true); - ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); - // global flow control test - gap = MAX_UPDATE_NUM_PERSECOND - MAX_UPDATE_NUM_PERSECOND_PERAPP; - callingUid = NON_SYSTEM_APP_UID; + int gap = MAX_CREATE_NUM_PERSECOND - totalCreate; for (int i = 0; i < gap; i++) { - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, true); + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); } - ASSERT_EQ(result, (int)ERR_OK); - result = FlowControlService::GetInstance()->FlowControl(record, callingUid, true); - ASSERT_EQ(result, (int)ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: FlowControl_0002 - * @tc.desc: Test FlowControl + * @tc.name: FlowControl_500 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_UPDATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, FlowControl_0002, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_500, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); - record->isNeedFlowCtrl = false; - auto result = FlowControlService::GetInstance()->FlowControl(record, DEFAULT_UID, false); + auto record = GetLiveviewNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; + int32_t index = 1; + ErrCode result = ERR_OK; + uint32_t totalCreate = 0; + while (totalCreate + MAX_UPDATE_NUM_PERSECOND_PERAPP < MAX_UPDATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + } + totalCreate += MAX_UPDATE_NUM_PERSECOND_PERAPP; + index++; + } + + int gap = MAX_UPDATE_NUM_PERSECOND - totalCreate; + for (int i = 0; i < gap; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + } ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: FlowControl_0003 - * @tc.desc: Test FlowControl + * @tc.name: FlowControl_600 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_CREATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, FlowControl_0003, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_600, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); - record->isNeedFlowCtrl = true; + auto record = GetCommonNotificationRecord(); + record->isThirdparty = true; + int32_t uid = 1000; + int32_t index = 1; + ErrCode result = ERR_OK; + uint32_t totalCreate = 0; + while (totalCreate + MAX_CREATE_NUM_PERSECOND_PERAPP < MAX_CREATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + } + totalCreate += MAX_CREATE_NUM_PERSECOND_PERAPP; + index++; + } - sptr req(new NotificationRequest(1)); - req->SetUpdateOnly(true); - record->request = req; + int gap = MAX_CREATE_NUM_PERSECOND - totalCreate; + for (int i = 0; i < gap; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + } + ASSERT_EQ(result, ERR_OK); - ErrCode result = FlowControlService::GetInstance()->FlowControl(record, DEFAULT_UID, false); - ASSERT_EQ(result, ERR_ANS_NOTIFICATION_NOT_EXISTS); + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: PublishFlowCtrl_0001 - * @tc.desc: Test PublishFlowCtrl + * @tc.name: FlowControl_700 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_UPDATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, PublishFlowCtrl_0001, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_700, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); - record->isNeedFlowCtrl = false; - bool result = FlowControlService::GetInstance()->PublishFlowCtrl(record, DEFAULT_UID); + auto record = GetCommonNotificationRecord(); + record->isThirdparty = true; + int32_t uid = 1000; + int32_t index = 1; + ErrCode result = ERR_OK; + uint32_t totalCreate = 0; + while (totalCreate + MAX_UPDATE_NUM_PERSECOND_PERAPP < MAX_UPDATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + } + totalCreate += MAX_UPDATE_NUM_PERSECOND_PERAPP; + index++; + } + + int gap = MAX_UPDATE_NUM_PERSECOND - totalCreate; + for (int i = 0; i < gap; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + } ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: PublishGlobalFlowCtrl_0001 - * @tc.desc: Test PublishGlobalFlowCtrl + * @tc.name: FlowControl_800 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_CREATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, PublishGlobalFlowCtrl_0001, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_800, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); + auto record = GetLiveviewNotificationRecord(); + record->isThirdparty = true; + int32_t uid = 1000; + int32_t index = 1; + ErrCode result = ERR_OK; + uint32_t totalCreate = 0; + while (totalCreate + MAX_CREATE_NUM_PERSECOND_PERAPP < MAX_CREATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + } + totalCreate += MAX_CREATE_NUM_PERSECOND_PERAPP; + index++; + } - sptr req(new NotificationRequest(1)); + int gap = MAX_CREATE_NUM_PERSECOND - totalCreate; + for (int i = 0; i < gap; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + } + ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid + index, false); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); +} + +/** + * @tc.name: FlowControl_900 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_UPDATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_900, Function | SmallTest | Level1) +{ + auto record = GetLiveviewNotificationRecord(); record->isThirdparty = true; - record->request = req; + int32_t uid = 1000; + int32_t index = 1; + ErrCode result = ERR_OK; + uint32_t totalCreate = 0; + while (totalCreate + MAX_UPDATE_NUM_PERSECOND_PERAPP < MAX_UPDATE_NUM_PERSECOND) { + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + } + totalCreate += MAX_UPDATE_NUM_PERSECOND_PERAPP; + index++; + } - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + int gap = MAX_UPDATE_NUM_PERSECOND - totalCreate; + for (int i = 0; i < gap; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + } + ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid + index, true); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); +} + +/** + * @tc.name: FlowControl_1000 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_SYSTEM_NORMAL_CREATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_1000, Function | SmallTest | Level1) +{ + auto record = GetCommonNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; ErrCode result = ERR_OK; + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { - result = FlowControlService::GetInstance()->FlowControl(record, DEFAULT_UID, false); + result = FlowControlService::GetInstance().FlowControl(record, uid, false); } + ASSERT_EQ(result, ERR_OK); - result = FlowControlService::GetInstance()->FlowControl(record, DEFAULT_UID, false); + result = FlowControlService::GetInstance().FlowControl(record, uid, false); ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: PublishRecordTimestamp_0001 - * @tc.desc: Test FlowControl + * @tc.name: FlowControl_1100 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_SYSTEM_NORMAL_UPDATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, PublishRecordTimestamp_0001, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_1100, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); - record->isThirdparty = true; + auto record = GetCommonNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; + ErrCode result = ERR_OK; + + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid, true); + } + ASSERT_EQ(result, ERR_OK); - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - FlowControlService::GetInstance()->PublishRecordTimestamp( - record, now, DEFAULT_UID); - - auto size = FlowControlService::GetInstance()->flowControlPublishTimestampList_.size(); - ASSERT_EQ(size, 1); - FlowControlService::GetInstance()->flowControlPublishTimestampList_.clear(); + result = FlowControlService::GetInstance().FlowControl(record, uid, true); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: UpdateFlowCtrl_0001 - * @tc.desc: Test UpdateFlowCtrl + * @tc.name: FlowControl_1200 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_CREATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, UpdateFlowCtrl_0001, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_1200, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); - record->isNeedFlowCtrl = false; - auto result = FlowControlService::GetInstance()->UpdateFlowCtrl(record, DEFAULT_UID); + auto record = GetLiveviewNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; + ErrCode result = ERR_OK; + + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid, false); + } ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid, false); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: UpdateGlobalFlowCtrl_0001 - * @tc.desc: Test UpdateGlobalFlowCtrl + * @tc.name: FlowControl_1300 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_UPDATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, UpdateGlobalFlowCtrl_0001, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_1300, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); + auto record = GetLiveviewNotificationRecord(); + record->isThirdparty = false; + int32_t uid = 1000; + ErrCode result = ERR_OK; + + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid, true); + } + ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid, true); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); +} + +/** + * @tc.name: FlowControl_1400 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_THIRD_PART_NORMAL_CREATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_1400, Function | SmallTest | Level1) +{ + auto record = GetCommonNotificationRecord(); record->isThirdparty = true; + int32_t uid = 1000; + ErrCode result = ERR_OK; - sptr req(new NotificationRequest(1)); - req->SetUpdateOnly(true); - record->request = req; - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid, false); + } + ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid, false); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); +} +/** + * @tc.name: FlowControl_1500 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_THIRD_PART_NORMAL_UPDATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_1500, Function | SmallTest | Level1) +{ + auto record = GetCommonNotificationRecord(); + record->isThirdparty = true; + int32_t uid = 1000; ErrCode result = ERR_OK; + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { - result = FlowControlService::GetInstance()->FlowControl(record, DEFAULT_UID, true); + result = FlowControlService::GetInstance().FlowControl(record, uid, true); } + ASSERT_EQ(result, ERR_OK); - result = FlowControlService::GetInstance()->FlowControl(record, DEFAULT_UID, true); + result = FlowControlService::GetInstance().FlowControl(record, uid, true); ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } /** - * @tc.name: UpdateRecordTimestamp_0001 - * @tc.desc: Test FlowControl + * @tc.name: FlowControl_1600 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_CREATE * @tc.type: FUNC * @tc.require: issue */ -HWTEST_F(FlowControlServiceTest, UpdateRecordTimestamp_0001, Function | SmallTest | Level1) +HWTEST_F(FlowControlServiceTest, FlowControl_1600, Function | SmallTest | Level1) { - std::shared_ptr record = std::make_shared(); + auto record = GetLiveviewNotificationRecord(); + record->isThirdparty = true; + int32_t uid = 1000; + ErrCode result = ERR_OK; + + for (int i = 0; i < MAX_CREATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid, false); + } + ASSERT_EQ(result, ERR_OK); + + result = FlowControlService::GetInstance().FlowControl(record, uid, false); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_ACTIVE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); +} + +/** + * @tc.name: FlowControl_1700 + * @tc.desc: Test FlowControl when scene type is FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_UPDATE + * @tc.type: FUNC + * @tc.require: issue + */ +HWTEST_F(FlowControlServiceTest, FlowControl_1700, Function | SmallTest | Level1) +{ + auto record = GetLiveviewNotificationRecord(); record->isThirdparty = true; + int32_t uid = 1000; + ErrCode result = ERR_OK; + + for (int i = 0; i < MAX_UPDATE_NUM_PERSECOND_PERAPP; i++) { + result = FlowControlService::GetInstance().FlowControl(record, uid, true); + } + ASSERT_EQ(result, ERR_OK); - std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); - FlowControlService::GetInstance()->UpdateRecordTimestamp( - record, now, DEFAULT_UID); - - auto size = FlowControlService::GetInstance()->flowControlUpdateTimestampList_.size(); - ASSERT_EQ(1, size); - FlowControlService::GetInstance()->flowControlUpdateTimestampList_.clear(); + result = FlowControlService::GetInstance().FlowControl(record, uid, true); + ASSERT_EQ(result, ERR_ANS_OVER_MAX_UPDATE_PERSECOND); + std::this_thread::sleep_for(std::chrono::seconds(1)); } } // namespace Notification } // namespace OHOS \ No newline at end of file -- Gitee