• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "advanced_notification_flow_control_service.h"
17 
18 #include <tuple>
19 #include <vector>
20 
21 #include "ans_inner_errors.h"
22 #include "notification_config_parse.h"
23 
24 namespace OHOS {
25 namespace Notification {
26 using TimePoint = std::chrono::system_clock::time_point;
27 constexpr int32_t TIME_GAP_FOR_SECOND = 1;
28 
RemoveExpiredTimestamp(std::list<TimePoint> & list,const TimePoint & now)29 void RemoveExpiredTimestamp(std::list<TimePoint> &list, const TimePoint &now)
30 {
31     auto iter = list.begin();
32     while (iter != list.end()) {
33         if (abs(now - *iter) > std::chrono::seconds(TIME_GAP_FOR_SECOND)) {
34             iter = list.erase(iter);
35         } else {
36             break;
37         }
38     }
39 }
40 
FlowControl(const std::shared_ptr<NotificationRecord> record,const TimePoint & now)41 ErrCode GlobalFlowController::FlowControl(const std::shared_ptr<NotificationRecord> record, const TimePoint &now)
42 {
43     std::lock_guard<ffrt::mutex> lock(globalFlowControllerMutex_);
44     RemoveExpiredTimestamp(globalFlowControllerList_, now);
45     if (globalFlowControllerList_.size() >= threshold_) {
46         ANS_LOGE("%{public}s", errMsg_.msg.c_str());
47         HaMetaMessage message = HaMetaMessage(errMsg_.sceneId, errMsg_.EventBranchId)
48             .ErrorCode(errMsg_.errCode).Message(errMsg_.msg);
49         NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message);
50         return errMsg_.errCode;
51     }
52     return ERR_OK;
53 }
54 
RecordTimestamp(const TimePoint & now)55 void GlobalFlowController::RecordTimestamp(const TimePoint &now)
56 {
57     std::lock_guard<ffrt::mutex> lock(globalFlowControllerMutex_);
58     globalFlowControllerList_.push_back(now);
59 }
60 
FlowControl(const std::shared_ptr<NotificationRecord> record,const int32_t callingUid,const TimePoint & now)61 ErrCode CallerFlowController::FlowControl(
62     const std::shared_ptr<NotificationRecord> record, const int32_t callingUid, const TimePoint &now)
63 {
64     std::lock_guard<ffrt::mutex> lock(callerFlowControllerMutex_);
65     auto callerFlowControlIter = callerFlowControllerMapper_.find(callingUid);
66     if (callerFlowControlIter == callerFlowControllerMapper_.end()) {
67         return ERR_OK;
68     }
69     RemoveExpiredTimestamp(*(callerFlowControlIter->second), now);
70     if (callerFlowControlIter->second->size() >= threshold_) {
71         ANS_LOGE("%{public}s", errMsg_.msg.c_str());
72         HaMetaMessage message = HaMetaMessage(errMsg_.sceneId, errMsg_.EventBranchId)
73             .ErrorCode(errMsg_.errCode).Message(errMsg_.msg);
74         NotificationAnalyticsUtil::ReportPublishFailedEvent(record->request, message);
75         return errMsg_.errCode;
76     }
77     return ERR_OK;
78 }
79 
RecordTimestamp(const std::shared_ptr<NotificationRecord> record,const int32_t callingUid,const TimePoint & now)80 void CallerFlowController::RecordTimestamp(
81     const std::shared_ptr<NotificationRecord> record, const int32_t callingUid, const TimePoint &now)
82 {
83     std::lock_guard<ffrt::mutex> lock(callerFlowControllerMutex_);
84     auto callerFlowControlIter = callerFlowControllerMapper_.find(callingUid);
85     if (callerFlowControlIter == callerFlowControllerMapper_.end()) {
86         callerFlowControllerMapper_[callingUid] = std::make_shared<std::list<TimePoint>>();
87         callerFlowControlIter = callerFlowControllerMapper_.find(callingUid);
88     }
89     callerFlowControlIter->second->push_back(now);
90 }
91 
RemoveExpired(const TimePoint & now)92 void CallerFlowController::RemoveExpired(const TimePoint &now)
93 {
94     std::lock_guard<ffrt::mutex> lock(callerFlowControllerMutex_);
95     for (auto iter = callerFlowControllerMapper_.begin(); iter != callerFlowControllerMapper_.end();) {
96         auto latest = iter->second->back();
97         if (std::chrono::abs(now - latest) > CALLER_FLOW_CONTRL_EXPIRE_TIME) {
98             iter = callerFlowControllerMapper_.erase(iter);
99         } else {
100             ++iter;
101         }
102     }
103 }
104 
GetInstance()105 FlowControlService& FlowControlService::GetInstance()
106 {
107     static FlowControlService flowControlService;
108     return flowControlService;
109 }
110 
FlowControlService()111 FlowControlService::FlowControlService()
112 {
113     DelayedSingleton<NotificationConfigParse>::GetInstance()->GetFlowCtrlConfigFromCCM(threshold_);
114     InitGlobalFlowControl();
115     InitCallerFlowControl();
116 }
117 
InitGlobalFlowControl()118 void FlowControlService::InitGlobalFlowControl()
119 {
120     std::vector<std::tuple<FlowControlSceneType, uint32_t, FlowControlErrMsg>> configs = {
121         {
122             FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_CREATE,
123             threshold_.maxCreateNumPerSecond,
124             {
125                 .msg = "GLOBAL_SYSTEM_NORMAL_CREATE flow control",
126                 .sceneId = EventSceneId::SCENE_4,
127                 .EventBranchId = EventBranchId::BRANCH_0,
128                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
129             }
130         },
131         {
132             FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_UPDATE,
133             threshold_.maxUpdateNumPerSecond,
134             {
135                 .msg = "GLOBAL_SYSTEM_NORMAL_UPDATE flow control",
136                 .sceneId = EventSceneId::SCENE_4,
137                 .EventBranchId = EventBranchId::BRANCH_1,
138                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
139             }
140         },
141         {
142             FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_CREATE,
143             threshold_.maxCreateNumPerSecond,
144             {
145                 .msg = "GLOBAL_SYSTEM_LIVEVIEW_CREATE flow control",
146                 .sceneId = EventSceneId::SCENE_4,
147                 .EventBranchId = EventBranchId::BRANCH_2,
148                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
149             }
150         },
151         {
152             FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_UPDATE,
153             threshold_.maxUpdateNumPerSecond,
154             {
155                 .msg = "GLOBAL_SYSTEM_LIVEVIEW_UPDATE flow control",
156                 .sceneId = EventSceneId::SCENE_4,
157                 .EventBranchId = EventBranchId::BRANCH_3,
158                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
159             }
160         },
161         {
162             FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_CREATE,
163             threshold_.maxCreateNumPerSecond,
164             {
165                 .msg = "GLOBAL_THIRD_PART_NORMAL_CREATE flow control",
166                 .sceneId = EventSceneId::SCENE_4,
167                 .EventBranchId = EventBranchId::BRANCH_4,
168                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
169             }
170         },
171         {
172             FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_UPDATE,
173             threshold_.maxUpdateNumPerSecond,
174             {
175                 .msg = "GLOBAL_THIRD_PART_NORMAL_UPDATE flow control",
176                 .sceneId = EventSceneId::SCENE_4,
177                 .EventBranchId = EventBranchId::BRANCH_5,
178                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
179             }
180         },
181         {
182             FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_CREATE,
183             threshold_.maxCreateNumPerSecond,
184             {
185                 .msg = "GLOBAL_THIRD_PART_LIVEVIEW_CREATE flow control",
186                 .sceneId = EventSceneId::SCENE_4,
187                 .EventBranchId = EventBranchId::BRANCH_6,
188                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
189             }
190         },
191         {
192             FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_UPDATE,
193             threshold_.maxUpdateNumPerSecond,
194             {
195                 .msg = "GLOBAL_THIRD_PART_LIVEVIEW_UPDATE flow control",
196                 .sceneId = EventSceneId::SCENE_4,
197                 .EventBranchId = EventBranchId::BRANCH_7,
198                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
199             }
200         },
201     };
202 
203     const int sceneTypeIdx = 0, thresholdIdx = 1, errMsgIdx = 2;
204     for (auto iter = configs.cbegin(); iter != configs.cend(); ++iter) {
205         globalFlowControllerMapper_[std::get<sceneTypeIdx>(*iter)] =
206             std::make_shared<GlobalFlowController>(std::get<thresholdIdx>(*iter), std::get<errMsgIdx>(*iter));
207     }
208 }
209 
InitCallerFlowControl()210 void FlowControlService::InitCallerFlowControl()
211 {
212     std::vector<std::tuple<FlowControlSceneType, uint32_t, FlowControlErrMsg>> configs = {
213         {
214             FlowControlSceneType::CALLER_SYSTEM_NORMAL_CREATE,
215             threshold_.maxCreateNumPerSecondPerApp,
216             {
217                 .msg = "CALLER_SYSTEM_NORMAL_CREATE flow control",
218                 .sceneId = EventSceneId::SCENE_4,
219                 .EventBranchId = EventBranchId::BRANCH_8,
220                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
221             }
222         },
223         {
224             FlowControlSceneType::CALLER_SYSTEM_NORMAL_UPDATE,
225             threshold_.maxUpdateNumPerSecondPerApp,
226             {
227                 .msg = "CALLER_SYSTEM_NORMAL_UPDATE flow control",
228                 .sceneId = EventSceneId::SCENE_4,
229                 .EventBranchId = EventBranchId::BRANCH_9,
230                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
231             }
232         },
233         {
234             FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_CREATE,
235             threshold_.maxCreateNumPerSecondPerApp,
236             {
237                 .msg = "CALLER_SYSTEM_LIVEVIEW_CREATE flow control",
238                 .sceneId = EventSceneId::SCENE_4,
239                 .EventBranchId = EventBranchId::BRANCH_10,
240                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
241             }
242         },
243         {
244             FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_UPDATE,
245             threshold_.maxUpdateNumPerSecondPerApp,
246             {
247                 .msg = "CALLER_SYSTEM_LIVEVIEW_UPDATE flow control",
248                 .sceneId = EventSceneId::SCENE_4,
249                 .EventBranchId = EventBranchId::BRANCH_11,
250                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
251             }
252         },
253         {
254             FlowControlSceneType::CALLER_THIRD_PART_NORMAL_CREATE,
255             threshold_.maxCreateNumPerSecondPerApp,
256             {
257                 .msg = "CALLER_THIRD_PART_NORMAL_CREATE flow control",
258                 .sceneId = EventSceneId::SCENE_4,
259                 .EventBranchId = EventBranchId::BRANCH_12,
260                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
261             }
262         },
263         {
264             FlowControlSceneType::CALLER_THIRD_PART_NORMAL_UPDATE,
265             threshold_.maxUpdateNumPerSecondPerApp,
266             {
267                 .msg = "CALLER_THIRD_PART_NORMAL_UPDATE flow control",
268                 .sceneId = EventSceneId::SCENE_4,
269                 .EventBranchId = EventBranchId::BRANCH_13,
270                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
271             }
272         },
273         {
274             FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_CREATE,
275             threshold_.maxCreateNumPerSecondPerApp,
276             {
277                 .msg = "CALLER_THIRD_PART_LIVEVIEW_CREATE flow control",
278                 .sceneId = EventSceneId::SCENE_4,
279                 .EventBranchId = EventBranchId::BRANCH_14,
280                 .errCode = ERR_ANS_OVER_MAX_ACTIVE_PERSECOND
281             }
282         },
283         {
284             FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_UPDATE,
285             threshold_.maxUpdateNumPerSecondPerApp,
286             {
287                 .msg = "CALLER_THIRD_PART_LIVEVIEW_UPDATE flow control",
288                 .sceneId = EventSceneId::SCENE_4,
289                 .EventBranchId = EventBranchId::BRANCH_15,
290                 .errCode = ERR_ANS_OVER_MAX_UPDATE_PERSECOND
291             }
292         },
293     };
294 
295     const int sceneTypeIdx = 0, thresholdIdx = 1, errMsgIdx = 2;
296     for (auto iter = configs.cbegin(); iter != configs.cend(); ++iter) {
297         callerFlowControllerMapper_[std::get<sceneTypeIdx>(*iter)] =
298             std::make_shared<CallerFlowController>(std::get<thresholdIdx>(*iter), std::get<errMsgIdx>(*iter));
299     }
300 }
301 
FlowControl(const std::shared_ptr<NotificationRecord> record,const int32_t callingUid,bool isNotificationExists)302 ErrCode FlowControlService::FlowControl(
303     const std::shared_ptr<NotificationRecord> record, const int32_t callingUid, bool isNotificationExists)
304 {
305     if (record->isNeedFlowCtrl == false) {
306         return ERR_OK;
307     }
308     TimePoint now = std::chrono::system_clock::now();
309 
310     auto sceneTypePair = GetSceneTypePair(record, isNotificationExists);
311     ErrCode result = ERR_OK;
312     auto globalFlowController = globalFlowControllerMapper_[sceneTypePair.first];
313     result = globalFlowController->FlowControl(record, now);
314     if (result != ERR_OK) {
315         return result;
316     }
317 
318     auto callerFlowController = callerFlowControllerMapper_[sceneTypePair.second];
319     result = callerFlowController->FlowControl(record, callingUid, now);
320     if (result != ERR_OK) {
321         return result;
322     }
323 
324     globalFlowController->RecordTimestamp(now);
325     callerFlowController->RecordTimestamp(record, callingUid, now);
326 
327     auto begin = callerFlowControllerMapper_.begin();
328     auto end = callerFlowControllerMapper_.end();
329     for (auto it = begin; it != end; ++it) {
330         it->second->RemoveExpired(now);
331     }
332     return result;
333 }
334 
GetSceneTypePair(const std::shared_ptr<NotificationRecord> record,bool isNotificationExists)335 std::pair<FlowControlSceneType, FlowControlSceneType> FlowControlService::GetSceneTypePair(
336     const std::shared_ptr<NotificationRecord> record, bool isNotificationExists)
337 {
338     bool isLiveview = record->request->IsCommonLiveView() || record->request->IsSystemLiveView();
339     if (record->isThirdparty) {
340         // Third-Part caller
341         if (isLiveview) {
342             if (isNotificationExists) {
343                 return {FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_UPDATE,
344                         FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_UPDATE};
345             } else {
346                 return {FlowControlSceneType::GLOBAL_THIRD_PART_LIVEVIEW_CREATE,
347                         FlowControlSceneType::CALLER_THIRD_PART_LIVEVIEW_CREATE};
348             }
349         } else {
350             if (isNotificationExists) {
351                 return {FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_UPDATE,
352                         FlowControlSceneType::CALLER_THIRD_PART_NORMAL_UPDATE};
353             } else {
354                 return {FlowControlSceneType::GLOBAL_THIRD_PART_NORMAL_CREATE,
355                         FlowControlSceneType::CALLER_THIRD_PART_NORMAL_CREATE};
356             }
357         }
358     }
359 
360     // System caller
361     if (isLiveview) {
362         if (isNotificationExists) {
363             return {FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_UPDATE,
364                     FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_UPDATE};
365         } else {
366             return {FlowControlSceneType::GLOBAL_SYSTEM_LIVEVIEW_CREATE,
367                     FlowControlSceneType::CALLER_SYSTEM_LIVEVIEW_CREATE};
368         }
369     } else {
370         if (isNotificationExists) {
371             return {FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_UPDATE,
372                     FlowControlSceneType::CALLER_SYSTEM_NORMAL_UPDATE};
373         } else {
374             return {FlowControlSceneType::GLOBAL_SYSTEM_NORMAL_CREATE,
375                     FlowControlSceneType::CALLER_SYSTEM_NORMAL_CREATE};
376         }
377     }
378 }
379 }  // namespace Notification
380 }  // namespace OHOS