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 "base/ressched/ressched_report.h"
17
18 namespace OHOS::Ace {
19 std::atomic<int32_t> ResSchedReport::createPageCount(0);
20 bool ResSchedReport::triggerExecuted(false);
21 namespace Ressched {
22 constexpr uint32_t RES_TYPE_CLICK_RECOGNIZE = 9;
23 constexpr uint32_t RES_TYPE_PUSH_PAGE = 10;
24 constexpr uint32_t RES_TYPE_SLIDE = 11;
25 constexpr uint32_t RES_TYPE_POP_PAGE = 28;
26 constexpr uint32_t RES_TYPE_WEB_GESTURE = 29;
27 constexpr uint32_t RES_TYPE_LOAD_PAGE = 34;
28 constexpr uint32_t RES_TYPE_KEY_EVENT = 122;
29 constexpr uint32_t RES_TYPE_AXIS_EVENT = 123;
30 constexpr uint32_t RES_TYPE_PAGE_TRANSITION = 140;
31 constexpr uint32_t RES_TYPE_ABILITY_OR_PAGE_SWITCH = 156;
32 constexpr uint32_t RES_TYPE_CHECK_APP_IS_IN_SCHEDULE_LIST = 504;
33 #ifdef FFRT_EXISTS
34 constexpr uint32_t RES_TYPE_LONG_FRAME = 71;
35 #endif
36 constexpr uint32_t RES_TYPE_OVERLAY = 151;
37 constexpr int32_t TOUCH_DOWN_EVENT = 1;
38 constexpr int32_t CLICK_EVENT = 2;
39 constexpr int32_t TOUCH_UP_EVENT = 3;
40 constexpr int32_t TOUCH_PULL_UP_EVENT = 4;
41 constexpr int32_t KEY_DOWN_EVENT = 1;
42 constexpr int32_t KEY_UP_EVENT = 2;
43 constexpr int32_t SLIDE_OFF_EVENT = 0;
44 constexpr int32_t SLIDE_DETECTING = 2;
45 constexpr int32_t AUTO_PLAY_ON_EVENT = 5;
46 constexpr int32_t AUTO_PLAY_OFF_EVENT = 6;
47 constexpr int32_t MOVE_DETECTING = 7;
48 constexpr int32_t PUSH_PAGE_START_EVENT = 0;
49 constexpr int32_t PUSH_PAGE_COMPLETE_EVENT = 1;
50 constexpr int32_t POP_PAGE_EVENT = 0;
51 constexpr int32_t AXIS_OFF_EVENT = 1;
52 constexpr int32_t AXIS_IS_PAD = 0;
53 constexpr int32_t AXIS_IS_MOUSE = 1;
54 constexpr int64_t TIME_INTERVAL = 300;
55 constexpr int32_t ABILITY_OR_PAGE_SWITCH_START_EVENT = 0;
56 constexpr int32_t ABILITY_OR_PAGE_SWITCH_END_EVENT = 1;
57 constexpr int32_t MODULE_SERIALIZER_COUNT = 3;
58 #ifdef FFRT_EXISTS
59 constexpr int32_t LONG_FRAME_START_EVENT = 0;
60 constexpr int32_t LONG_FRAME_END_EVENT = 1;
61 #endif
62 constexpr int32_t OVERLAY_ADD_EVENT = 0;
63 constexpr int32_t OVERLAY_REMOVE_EVENT = 1;
64 constexpr char NAME[] = "name";
65 constexpr char PID[] = "pid";
66 constexpr char UID[] = "uid";
67 constexpr char SCRTID[] = "scrTid";
68 constexpr char BUNDLE_NAME[] = "bundleName";
69 constexpr char ABILITY_NAME[] = "abilityName";
70 constexpr char CLICK[] = "click";
71 constexpr char KEY_EVENT[] = "key_event";
72 constexpr char PUSH_PAGE[] = "push_page";
73 constexpr char POP_PAGE[] = "pop_page";
74 constexpr char PAGE_END_FLUSH[] = "page_end_flush";
75 constexpr char AUTO_PLAY_ON[] = "auto_play_on";
76 constexpr char AUTO_PLAY_OFF[] = "auto_play_off";
77 constexpr char SLIDE_OFF[] = "slide_off";
78 constexpr char OVERLAY_ADD[] = "overlay_add";
79 constexpr char OVERLAY_REMOVE[] = "overlay_remove";
80 constexpr char TOUCH[] = "touch";
81 constexpr char WEB_GESTURE[] = "web_gesture";
82 constexpr char LOAD_PAGE[] = "load_page";
83 constexpr char UP_SPEED_KEY[] = "up_speed";
84 constexpr char KEY_CODE[] = "key_code";
85 constexpr char AXIS_OFF[] = "axis_off";
86 constexpr char AXIS_NORMAL_UP_SPEED[] = "0.0";
87 constexpr char AXIS_EVENT_TYPE[] = "axis_event_type";
88 constexpr char FROM_PAGE_INFO[] = "from_page";
89 constexpr char TO_PAGE_INFO[] = "to_page";
90 constexpr char TRANSITION_MODE[] = "transition_mode";
91 constexpr char ABILITY_OR_PAGE_SWITCH_START[] = "ability_or_page_switch_start";
92 constexpr char ABILITY_OR_PAGE_SWITCH_END[] = "ability_or_page_switch_end";
93 #ifdef FFRT_EXISTS
94 constexpr char LONG_FRAME_START[] = "long_frame_start";
95 constexpr char LONG_FRAME_END[] = "long_frame_end";
96 #endif
97
LoadAceApplicationContext(std::unordered_map<std::string,std::string> & payload)98 void LoadAceApplicationContext(std::unordered_map<std::string, std::string>& payload)
99 {
100 auto& aceApplicationInfo = AceApplicationInfo::GetInstance();
101 payload[PID] = std::to_string(aceApplicationInfo.GetPid());
102 payload[UID] = std::to_string(aceApplicationInfo.GetUid());
103 payload[BUNDLE_NAME] = aceApplicationInfo.GetPackageName();
104 payload[ABILITY_NAME] = aceApplicationInfo.GetAbilityName();
105 }
106
LoadReportConfig(const ReportConfig & config,std::unordered_map<std::string,std::string> & payload)107 void LoadReportConfig(
108 const ReportConfig& config, std::unordered_map<std::string, std::string>& payload)
109 {
110 if (config.isReportTid) {
111 payload[SCRTID] = std::to_string(config.tid);
112 }
113 }
114 }
115
116 using namespace Ressched;
117
118 thread_local bool ResSchedReport::isInSlide_ = false;
119 thread_local bool ResSchedReport::isInTouch_ = false;
120 thread_local Offset ResSchedReport::averageDistance_;
121
GetInstance()122 ResSchedReport& ResSchedReport::GetInstance()
123 {
124 thread_local ResSchedReport instance;
125 return instance;
126 }
127
ResSchedReport()128 ResSchedReport::ResSchedReport()
129 {
130 reportDataFunc_ = LoadReportDataFunc();
131 reportSyncEventFunc_ = LoadReportSyncEventFunc();
132 }
133
TriggerModuleSerializer()134 void ResSchedReport::TriggerModuleSerializer()
135 {
136 if (triggerExecuted) {
137 return;
138 }
139 auto curContainer = Container::Current();
140 auto taskExecutor = curContainer->GetTaskExecutor();
141 auto serializerTask = [weak = WeakPtr<Container>(curContainer)]() {
142 auto container = weak.Upgrade();
143 if (!container) {
144 LOGW("container is null, serializerTask failed.");
145 return;
146 }
147 container->TriggerModuleSerializer();
148 };
149 if (createPageCount == MODULE_SERIALIZER_COUNT) {
150 taskExecutor->PostTask(std::move(serializerTask), TaskExecutor::TaskType::UI, "TriggerModuleSerializer");
151 triggerExecuted = true;
152 delayTask_.Cancel();
153 return;
154 }
155 auto task = [taskExecutor, originTask = std::move(serializerTask)]() {
156 if (!triggerExecuted) {
157 taskExecutor->PostTask(originTask, TaskExecutor::TaskType::UI, "TriggerModuleSerializer");
158 triggerExecuted = true;
159 }
160 };
161 delayTask_.Cancel();
162 delayTask_.Reset(std::move(task));
163 const uint32_t delay = 5000;
164 taskExecutor->PostDelayedTask(delayTask_, TaskExecutor::TaskType::UI, delay, "TriggerModuleSerializer");
165 }
166
ResSchedDataReport(const char * name,const std::unordered_map<std::string,std::string> & param,int64_t tid)167 void ResSchedReport::ResSchedDataReport(const char* name, const std::unordered_map<std::string, std::string>& param,
168 int64_t tid)
169 {
170 std::unordered_map<std::string, std::string> payload = param;
171 payload[Ressched::NAME] = name;
172 #if !defined(MAC_PLATFORM) && !defined(IOS_PLATFORM) && defined(OHOS_PLATFORM)
173 if (tid == ResDefine::INVALID_DATA) {
174 tid = GetTid();
175 }
176 int64_t pid = GetPid();
177 if (pid != tid) {
178 payload["scrTid"] = std::to_string(static_cast<uint64_t>(GetPthreadSelf()));
179 }
180 #endif
181 if (!reportDataFunc_) {
182 reportDataFunc_ = LoadReportDataFunc();
183 }
184 if (!reportDataFunc_) {
185 return;
186 }
187 static std::unordered_map<std::string, std::function<void(std::unordered_map<std::string, std::string>&)>>
188 functionMap = {
189 { CLICK,
190 [this](std::unordered_map<std::string, std::string>& payload) {
191 reportDataFunc_(RES_TYPE_CLICK_RECOGNIZE, CLICK_EVENT, payload);
192 }
193 },
194 { AUTO_PLAY_ON,
195 [this](std::unordered_map<std::string, std::string>& payload) {
196 reportDataFunc_(RES_TYPE_SLIDE, AUTO_PLAY_ON_EVENT, payload);
197 }
198 },
199 { AUTO_PLAY_OFF,
200 [this](std::unordered_map<std::string, std::string>& payload) {
201 reportDataFunc_(RES_TYPE_SLIDE, AUTO_PLAY_OFF_EVENT, payload);
202 }
203 },
204 { SLIDE_OFF,
205 [this](std::unordered_map<std::string, std::string>& payload) {
206 reportDataFunc_(RES_TYPE_SLIDE, SLIDE_OFF_EVENT, payload);
207 }
208 },
209 { POP_PAGE,
210 [this](std::unordered_map<std::string, std::string>& payload) {
211 LoadAceApplicationContext(payload);
212 reportDataFunc_(RES_TYPE_POP_PAGE, POP_PAGE_EVENT, payload);
213 }
214 },
215 { PAGE_END_FLUSH,
216 [this](std::unordered_map<std::string, std::string>& payload) {
217 ResSchedReport::GetInstance().LoadPageEvent(ResDefine::LOAD_PAGE_NO_REQUEST_FRAME_EVENT);
218 }
219 },
220 { WEB_GESTURE,
221 [this](std::unordered_map<std::string, std::string>& payload) {
222 reportDataFunc_(RES_TYPE_WEB_GESTURE, 0, payload);
223 }
224 },
225 { AXIS_OFF,
226 [this](std::unordered_map<std::string, std::string>& payload) {
227 ResSchedReport::GetInstance().AxisEventReportEnd();
228 }
229 },
230 #ifdef FFRT_EXISTS
231 { LONG_FRAME_START,
232 [this](std::unordered_map<std::string, std::string>& payload) {
233 LoadAceApplicationContext(payload);
234 reportDataFunc_(RES_TYPE_LONG_FRAME, LONG_FRAME_START_EVENT, payload);
235 }
236 },
237 { LONG_FRAME_END,
238 [this](std::unordered_map<std::string, std::string>& payload) {
239 LoadAceApplicationContext(payload);
240 reportDataFunc_(RES_TYPE_LONG_FRAME, LONG_FRAME_END_EVENT, payload);
241 }
242 },
243 #endif
244 { OVERLAY_ADD,
245 [this](std::unordered_map<std::string, std::string>& payload) {
246 LoadAceApplicationContext(payload);
247 reportDataFunc_(RES_TYPE_OVERLAY, OVERLAY_ADD_EVENT, payload);
248 }
249 },
250 { OVERLAY_REMOVE,
251 [this](std::unordered_map<std::string, std::string>& payload) {
252 LoadAceApplicationContext(payload);
253 reportDataFunc_(RES_TYPE_OVERLAY, OVERLAY_REMOVE_EVENT, payload);
254 }
255 },
256 { ABILITY_OR_PAGE_SWITCH_START,
257 [this](std::unordered_map<std::string, std::string>& payload) {
258 LoadAceApplicationContext(payload);
259 reportDataFunc_(RES_TYPE_ABILITY_OR_PAGE_SWITCH, ABILITY_OR_PAGE_SWITCH_START_EVENT, payload);
260 }
261 },
262 { ABILITY_OR_PAGE_SWITCH_END,
263 [this](std::unordered_map<std::string, std::string>& payload) {
264 LoadAceApplicationContext(payload);
265 reportDataFunc_(RES_TYPE_ABILITY_OR_PAGE_SWITCH, ABILITY_OR_PAGE_SWITCH_END_EVENT, payload);
266 }
267 },
268 };
269 auto it = functionMap.find(name);
270 if (it == functionMap.end()) {
271 return;
272 }
273 it->second(payload);
274 }
275
ResSchedDataReport(uint32_t resType,int32_t value,const std::unordered_map<std::string,std::string> & payload)276 void ResSchedReport::ResSchedDataReport(uint32_t resType, int32_t value,
277 const std::unordered_map<std::string, std::string>& payload)
278 {
279 if (!reportDataFunc_) {
280 LOGD("reportDataFunc_ is null!");
281 return;
282 }
283 reportDataFunc_(resType, value, payload);
284 }
285
ResScheSyncEventReport(const uint32_t resType,const int64_t value,const std::unordered_map<std::string,std::string> & payload,std::unordered_map<std::string,std::string> & reply)286 void ResSchedReport::ResScheSyncEventReport(const uint32_t resType, const int64_t value,
287 const std::unordered_map<std::string, std::string>& payload, std::unordered_map<std::string, std::string>& reply)
288 {
289 if (!reportSyncEventFunc_) {
290 LOGD("reportSyncEventFunc_ is null!");
291 return;
292 }
293 reportSyncEventFunc_(resType, value, payload, reply);
294 }
295
AppWhiteListCheck(const std::unordered_map<std::string,std::string> & payload,std::unordered_map<std::string,std::string> & reply)296 bool ResSchedReport::AppWhiteListCheck(const std::unordered_map<std::string, std::string>& payload,
297 std::unordered_map<std::string, std::string>& reply)
298 {
299 ResScheSyncEventReport(RES_TYPE_CHECK_APP_IS_IN_SCHEDULE_LIST, 0, payload, reply);
300 return reply["result"] == "\"true\"" ? true : false;
301 }
302
OnTouchEvent(const TouchEvent & touchEvent,const ReportConfig & config)303 void ResSchedReport::OnTouchEvent(const TouchEvent& touchEvent, const ReportConfig& config)
304 {
305 if (!triggerExecuted) {
306 auto curContainer = Container::Current();
307 CHECK_NULL_VOID(curContainer);
308 auto taskExecutor = curContainer->GetTaskExecutor();
309 CHECK_NULL_VOID(taskExecutor);
310 auto serializerTask = [weak = WeakPtr<Container>(curContainer)]() {
311 auto container = weak.Upgrade();
312 if (!container) {
313 LOGW("container is null, serializerTask failed.");
314 return;
315 }
316 container->TriggerModuleSerializer();
317 };
318 taskExecutor->PostTask(std::move(serializerTask), TaskExecutor::TaskType::UI, "TriggerModuleSerializer");
319 triggerExecuted = true;
320 }
321 switch (touchEvent.type) {
322 case TouchType::DOWN:
323 HandleTouchDown(touchEvent, config);
324 break;
325 case TouchType::UP:
326 HandleTouchUp(touchEvent, config);
327 break;
328 case TouchType::MOVE:
329 HandleTouchMove(touchEvent, config);
330 break;
331 case TouchType::CANCEL:
332 HandleTouchCancel(touchEvent, config);
333 break;
334 case TouchType::PULL_DOWN:
335 HandleTouchPullDown(touchEvent, config);
336 break;
337 case TouchType::PULL_UP:
338 HandleTouchPullUp(touchEvent, config);
339 break;
340 case TouchType::PULL_MOVE:
341 HandleTouchPullMove(touchEvent, config);
342 break;
343 default:
344 break;
345 }
346 }
347
IsRateLimit(int64_t maxCount,std::chrono::seconds durTime,int64_t & keyEventCount,std::chrono::steady_clock::time_point & startTime)348 bool ResSchedReport::IsRateLimit(int64_t maxCount, std::chrono::seconds durTime,
349 int64_t& keyEventCount, std::chrono::steady_clock::time_point& startTime)
350 {
351 if (keyEventCount == -1) {
352 startTime = std::chrono::steady_clock::now();
353 keyEventCount = 0;
354 }
355
356 if (keyEventCount > maxCount) {
357 auto curTime = std::chrono::steady_clock::now();
358 auto elapsedTime = std::chrono::duration_cast<std::chrono::seconds>(curTime - startTime).count();
359 if (elapsedTime < durTime.count()) {
360 LOGD("The event report exceeds the throttling limit");
361 return true;
362 }
363 keyEventCount = 0;
364 startTime = curTime;
365 }
366 keyEventCount++;
367 return false;
368 }
369
IsPerSecRateLimit()370 bool ResSchedReport::IsPerSecRateLimit()
371 {
372 int64_t maxCountMS = 10;
373 auto durTimeMS = std::chrono::seconds(1);
374 return IsRateLimit(maxCountMS, durTimeMS, keyEventCountMS, startTimeMS);
375 }
376
IsPerMinRateLimit()377 bool ResSchedReport::IsPerMinRateLimit()
378 {
379 int64_t maxCountS = 180;
380 auto durTimeS = std::chrono::seconds(60);
381 return IsRateLimit(maxCountS, durTimeS, keyEventCountS, startTimeS);
382 }
383
OnKeyEvent(const KeyEvent & event)384 void ResSchedReport::OnKeyEvent(const KeyEvent& event)
385 {
386 if (IsPerSecRateLimit() || IsPerMinRateLimit()) {
387 return;
388 }
389 switch (event.action) {
390 case KeyAction::DOWN:
391 HandleKeyDown(event);
392 break;
393 case KeyAction::UP:
394 HandleKeyUp(event);
395 break;
396 default:
397 break;
398 }
399 }
400
RecordTouchEvent(const TouchEvent & touchEvent,bool enforce)401 void ResSchedReport::RecordTouchEvent(const TouchEvent& touchEvent, bool enforce)
402 {
403 if (enforce) {
404 lastTouchEvent_.timeStamp = touchEvent.GetTimeStamp();
405 lastTouchEvent_.offset = touchEvent.GetOffset();
406 curTouchEvent_.timeStamp = touchEvent.GetTimeStamp();
407 curTouchEvent_.offset = touchEvent.GetOffset();
408 } else if (curTouchEvent_.offset != touchEvent.GetOffset()) {
409 lastTouchEvent_.timeStamp = curTouchEvent_.timeStamp;
410 lastTouchEvent_.offset = curTouchEvent_.offset;
411 curTouchEvent_.timeStamp = touchEvent.GetTimeStamp();
412 curTouchEvent_.offset = touchEvent.GetOffset();
413 }
414 }
415
HandleTouchDown(const TouchEvent & touchEvent,const ReportConfig & config)416 void ResSchedReport::HandleTouchDown(const TouchEvent& touchEvent, const ReportConfig& config)
417 {
418 std::unordered_map<std::string, std::string> payload;
419 payload[Ressched::NAME] = TOUCH;
420 LoadReportConfig(config, payload);
421 ResSchedDataReport(RES_TYPE_CLICK_RECOGNIZE, TOUCH_DOWN_EVENT, payload);
422 RecordTouchEvent(touchEvent, true);
423 isInTouch_ = true;
424 }
425
HandleKeyDown(const KeyEvent & event)426 void ResSchedReport::HandleKeyDown(const KeyEvent& event)
427 {
428 std::unordered_map<std::string, std::string> payload;
429 payload[Ressched::NAME] = KEY_EVENT;
430 payload[KEY_CODE] = std::to_string(static_cast<int>(event.code));
431 ResSchedDataReport(RES_TYPE_KEY_EVENT, KEY_DOWN_EVENT, payload);
432 }
433
HandleTouchUp(const TouchEvent & touchEvent,const ReportConfig & config)434 void ResSchedReport::HandleTouchUp(const TouchEvent& touchEvent, const ReportConfig& config)
435 {
436 std::unordered_map<std::string, std::string> payload;
437 LoadReportConfig(config, payload);
438 RecordTouchEvent(touchEvent);
439 payload[Ressched::NAME] = TOUCH;
440 payload[UP_SPEED_KEY] = std::to_string(GetUpVelocity(lastTouchEvent_, curTouchEvent_));
441 LoadAceApplicationContext(payload);
442 ResSchedDataReport(RES_TYPE_CLICK_RECOGNIZE, TOUCH_UP_EVENT, payload);
443 isInSlide_ = false;
444 isInTouch_ = false;
445 averageDistance_.Reset();
446 }
447
HandleKeyUp(const KeyEvent & event)448 void ResSchedReport::HandleKeyUp(const KeyEvent& event)
449 {
450 std::unordered_map<std::string, std::string> payload;
451 payload[Ressched::NAME] = KEY_EVENT;
452 payload[KEY_CODE] = std::to_string(static_cast<int>(event.code));
453 ResSchedDataReport(RES_TYPE_KEY_EVENT, KEY_UP_EVENT, payload);
454 }
455
HandleTouchMove(const TouchEvent & touchEvent,const ReportConfig & config)456 void ResSchedReport::HandleTouchMove(const TouchEvent& touchEvent, const ReportConfig& config)
457 {
458 RecordTouchEvent(touchEvent);
459 averageDistance_ += curTouchEvent_.offset - lastTouchEvent_.offset;
460 bool ret = averageDistance_.GetDistance() >= ResDefine::JUDGE_DISTANCE &&
461 !isInSlide_ && isInTouch_;
462 if (ret) {
463 std::unordered_map<std::string, std::string> payload;
464 LoadReportConfig(config, payload);
465 LoadAceApplicationContext(payload);
466 ResSchedDataReport(RES_TYPE_SLIDE, SLIDE_DETECTING, payload);
467 isInSlide_ = true;
468 }
469 static uint64_t lastTime = 0;
470 auto now = std::chrono::steady_clock::now();
471 uint64_t curMs = static_cast<uint64_t>(
472 std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count());
473 if (isInSlide_ && curMs > lastTime && curMs - lastTime >= TIME_INTERVAL) {
474 lastTime = curMs;
475 std::unordered_map<std::string, std::string> payload;
476 LoadAceApplicationContext(payload);
477 ResSchedDataReport(RES_TYPE_SLIDE, MOVE_DETECTING, payload);
478 }
479 }
480
HandleTouchCancel(const TouchEvent & touchEvent,const ReportConfig & config)481 void ResSchedReport::HandleTouchCancel(const TouchEvent& touchEvent, const ReportConfig& config)
482 {
483 isInSlide_ = false;
484 isInTouch_ = false;
485 averageDistance_.Reset();
486 }
487
HandleTouchPullDown(const TouchEvent & touchEvent,const ReportConfig & config)488 void ResSchedReport::HandleTouchPullDown(const TouchEvent& touchEvent, const ReportConfig& config)
489 {
490 RecordTouchEvent(touchEvent, true);
491 isInTouch_ = true;
492 }
493
HandleTouchPullUp(const TouchEvent & touchEvent,const ReportConfig & config)494 void ResSchedReport::HandleTouchPullUp(const TouchEvent& touchEvent, const ReportConfig& config)
495 {
496 std::unordered_map<std::string, std::string> payload;
497 LoadReportConfig(config, payload);
498 payload[Ressched::NAME] = TOUCH;
499 ResSchedDataReport(RES_TYPE_CLICK_RECOGNIZE, TOUCH_PULL_UP_EVENT, payload);
500 averageDistance_.Reset();
501 isInTouch_ = false;
502 }
503
HandleTouchPullMove(const TouchEvent & touchEvent,const ReportConfig & config)504 void ResSchedReport::HandleTouchPullMove(const TouchEvent& touchEvent, const ReportConfig& config)
505 {
506 if (!isInSlide_) {
507 std::unordered_map<std::string, std::string> payload;
508 LoadReportConfig(config, payload);
509 LoadAceApplicationContext(payload);
510 ResSchedDataReport(RES_TYPE_SLIDE, SLIDE_DETECTING, payload);
511 isInSlide_ = true;
512 }
513 RecordTouchEvent(touchEvent);
514 }
515
GetUpVelocity(const ResEventInfo & lastMoveInfo,const ResEventInfo & upEventInfo)516 double ResSchedReport::GetUpVelocity(const ResEventInfo& lastMoveInfo,
517 const ResEventInfo& upEventInfo)
518 {
519 double distance = (upEventInfo.offset - lastMoveInfo.offset).GetDistance();
520 int64_t time = std::chrono::duration_cast<std::chrono::milliseconds>(upEventInfo.timeStamp -
521 lastMoveInfo.timeStamp).count();
522 if (time <= 0) {
523 return 0.0f;
524 }
525 return distance * dpi_ / static_cast<double>(time); //unit: pixel/ms
526 }
527
LoadPageEvent(int32_t value)528 void ResSchedReport::LoadPageEvent(int32_t value)
529 {
530 if (ACE_LIKELY((value == ResDefine::LOAD_PAGE_COMPLETE_EVENT && loadPageOn_ == false)
531 || (value == ResDefine::LOAD_PAGE_NO_REQUEST_FRAME_EVENT && loadPageRequestFrameOn_ == false))) {
532 return;
533 } else if (value == ResDefine::LOAD_PAGE_COMPLETE_EVENT && loadPageOn_ == true) {
534 loadPageOn_ = false;
535 } else if (value == ResDefine::LOAD_PAGE_NO_REQUEST_FRAME_EVENT && loadPageRequestFrameOn_ == true) {
536 loadPageRequestFrameOn_ = false;
537 } else if (value == ResDefine::LOAD_PAGE_START_EVENT) {
538 loadPageOn_ = true;
539 loadPageRequestFrameOn_ = true;
540 }
541
542 std::unordered_map<std::string, std::string> payload;
543 payload[Ressched::NAME] = LOAD_PAGE;
544 LoadAceApplicationContext(payload);
545 ResSchedDataReport(RES_TYPE_LOAD_PAGE, value, payload);
546 }
547
HandleAxisBegin(const AxisEvent & axisEvent)548 void ResSchedReport::HandleAxisBegin(const AxisEvent& axisEvent)
549 {
550 RecordAxisEvent(axisEvent, true);
551 std::unordered_map<std::string, std::string> payload;
552 LoadAceApplicationContext(payload);
553 ResSchedDataReport(RES_TYPE_SLIDE, SLIDE_DETECTING, payload);
554 }
555
HandleAxisUpdate(const AxisEvent & axisEvent)556 void ResSchedReport::HandleAxisUpdate(const AxisEvent& axisEvent)
557 {
558 RecordAxisEvent(axisEvent);
559 }
560
HandleAxisEnd(const AxisEvent & axisEvent)561 void ResSchedReport::HandleAxisEnd(const AxisEvent& axisEvent)
562 {
563 RecordAxisEvent(axisEvent);
564 }
565
RecordAxisEvent(const AxisEvent & axisEvent,bool enforce)566 void ResSchedReport::RecordAxisEvent(const AxisEvent& axisEvent, bool enforce)
567 {
568 if (enforce) {
569 lastAxisEvent_.timeStamp = axisEvent.time;
570 lastAxisEvent_.offset = axisEvent.ConvertToOffset();
571 lastAxisEvent_.sourceTool = axisEvent.sourceTool;
572 curAxisEvent_.timeStamp = axisEvent.time;
573 curAxisEvent_.offset = axisEvent.ConvertToOffset();
574 curAxisEvent_.sourceTool = axisEvent.sourceTool;
575 } else if (axisEvent.ConvertToOffset().GetX() != 0 || axisEvent.ConvertToOffset().GetY() != 0) {
576 lastAxisEvent_.timeStamp = curAxisEvent_.timeStamp;
577 lastAxisEvent_.offset = curAxisEvent_.offset;
578 lastAxisEvent_.sourceTool = curAxisEvent_.sourceTool;
579 curAxisEvent_.timeStamp = axisEvent.time;
580 curAxisEvent_.offset = axisEvent.ConvertToOffset();
581 curAxisEvent_.sourceTool = axisEvent.sourceTool;
582 }
583 }
584
GetAxisUpVelocity(const ResEventInfo & lastAxisEvent,const ResEventInfo & curAxisEvent)585 double ResSchedReport::GetAxisUpVelocity(const ResEventInfo& lastAxisEvent, const ResEventInfo& curAxisEvent)
586 {
587 double distance = curAxisEvent.offset.GetDistance();
588 int64_t time = std::chrono::duration_cast<std::chrono::milliseconds>(curAxisEvent.timeStamp -
589 lastAxisEvent.timeStamp).count();
590 if (time <= 0) {
591 return 0.0;
592 }
593 return distance * dpi_ / static_cast<double>(time); //unit: pixel/ms
594 }
595
AxisEventReportEnd()596 void ResSchedReport::AxisEventReportEnd()
597 {
598 std::unordered_map<std::string, std::string> payload;
599 payload[Ressched::NAME] = TOUCH;
600 if (curAxisEvent_.sourceTool != SourceTool::TOUCHPAD) {
601 payload[UP_SPEED_KEY] = Ressched::AXIS_NORMAL_UP_SPEED;
602 payload[AXIS_EVENT_TYPE] = AXIS_IS_MOUSE;
603 } else {
604 payload[UP_SPEED_KEY] = std::to_string(GetAxisUpVelocity(lastAxisEvent_, curAxisEvent_));
605 payload[AXIS_EVENT_TYPE] = AXIS_IS_PAD;
606 }
607 ResSchedReport::GetInstance().ResSchedDataReport(Ressched::RES_TYPE_AXIS_EVENT, Ressched::AXIS_OFF_EVENT, payload);
608 }
609
OnAxisEvent(const AxisEvent & axisEvent)610 void ResSchedReport::OnAxisEvent(const AxisEvent& axisEvent)
611 {
612 switch (axisEvent.action) {
613 case AxisAction::BEGIN:
614 HandleAxisBegin(axisEvent);
615 break;
616 case AxisAction::UPDATE:
617 HandleAxisUpdate(axisEvent);
618 break;
619 case AxisAction::END:
620 HandleAxisEnd(axisEvent);
621 break;
622 default:
623 break;
624 }
625 }
626
HandlePageTransition(const std::string & fromPage,const std::string & toPage,const std::string & mode)627 void ResSchedReport::HandlePageTransition(const std::string& fromPage,
628 const std::string& toPage, const std::string& mode)
629 {
630 if (fromPage.empty() && toPage.empty()) {
631 TAG_LOGD(AceLogTag::ACE_ROUTER, "rss report page transition empty info:%{public}s, %{public}s",
632 fromPage.c_str(), toPage.c_str());
633 return;
634 }
635 std::unordered_map<std::string, std::string> payload;
636 payload[FROM_PAGE_INFO] = fromPage;
637 payload[TO_PAGE_INFO] = toPage;
638 payload[TRANSITION_MODE] = mode;
639 LoadAceApplicationContext(payload);
640 ResSchedDataReport(RES_TYPE_PAGE_TRANSITION, 0, payload);
641 }
642
ResSchedReportScope(const std::string & name,const std::unordered_map<std::string,std::string> & param)643 ResSchedReportScope::ResSchedReportScope(const std::string& name,
644 const std::unordered_map<std::string, std::string>& param) : name_(name), payload_(param)
645 {
646 name_ = name;
647 payload_[Ressched::NAME] = name;
648 LoadAceApplicationContext(payload_);
649 if (name_ == PUSH_PAGE) {
650 ResSchedReport::GetInstance().ResSchedDataReport(RES_TYPE_PUSH_PAGE, PUSH_PAGE_START_EVENT, payload_);
651 ResSchedReport::GetInstance().LoadPageEvent(ResDefine::LOAD_PAGE_START_EVENT);
652 }
653 }
654
~ResSchedReportScope()655 ResSchedReportScope::~ResSchedReportScope()
656 {
657 if (!ResSchedReport::triggerExecuted) {
658 ResSchedReport::createPageCount++;
659 ResSchedReport::GetInstance().TriggerModuleSerializer();
660 }
661 if (name_ == PUSH_PAGE) {
662 ResSchedReport::GetInstance().ResSchedDataReport(RES_TYPE_PUSH_PAGE, PUSH_PAGE_COMPLETE_EVENT, payload_);
663 }
664 }
665 } // namespace OHOS::Ace
666