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