• 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 "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