• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 #include "print_event_parser.h"
16 #include "animation_filter.h"
17 #include "clock_filter_ex.h"
18 #include "frame_filter.h"
19 #include "measure_filter.h"
20 #include "stat_filter.h"
21 #include "string_to_numerical.h"
22 #include <cinttypes>
23 namespace SysTuning {
24 namespace TraceStreamer {
25 const uint8_t POINT_LENGTH = 1;
26 const uint8_t MAX_POINT_LENGTH = 2;
27 const uint8_t CATEGORY_INDEX = 2;
28 const uint8_t PARSER_SYNC_SUM = 2;
29 const uint8_t PARSER_ASYNC_SUM = 3;
PrintEventParser(TraceDataCache * dataCache,const TraceStreamerFilters * filter)30 PrintEventParser::PrintEventParser(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
31     : EventParserBase(dataCache, filter)
32 {
33     rsOnDoCompositionEvent_ = traceDataCache_->GetDataIndex(rsOnDoCompositionStr_);
34     eventToFrameFunctionMap_ = {
35         {recvievVsync_, bind(&PrintEventParser::ReciveVsync, this, std::placeholders::_1, std::placeholders::_2,
36                              std::placeholders::_3)},
37         {rsOnDoCompositionEvent_, bind(&PrintEventParser::RSReciveOnDoComposition, this, std::placeholders::_1,
38                                        std::placeholders::_2, std::placeholders::_3)},
39         {onVsyncEvent_, bind(&PrintEventParser::OnVsyncEvent, this, std::placeholders::_1, std::placeholders::_2,
40                              std::placeholders::_3)},
41         {marshRwTransactionData_, bind(&PrintEventParser::OnRwTransaction, this, std::placeholders::_1,
42                                        std::placeholders::_2, std::placeholders::_3)},
43         {rsMainThreadProcessCmd_, bind(&PrintEventParser::OnMainThreadProcessCmd, this, std::placeholders::_1,
44                                        std::placeholders::_2, std::placeholders::_3)}};
45 }
46 
ParsePrintEvent(const std::string & comm,uint64_t ts,uint32_t pid,std::string_view event,const BytraceLine & line)47 bool PrintEventParser::ParsePrintEvent(const std::string &comm,
48                                        uint64_t ts,
49                                        uint32_t pid,
50                                        std::string_view event,
51                                        const BytraceLine &line)
52 {
53     streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_RECEIVED);
54     TracePoint point;
55     if (GetTracePoint(event, point) != PARSE_SUCCESS) {
56         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
57         return false;
58     }
59     if (point.tgid_) {
60         // tgid use 'B|' after with 'TGID', the '(TGID)' maybe wrong, eg: xxx-21675 ( 1264) ...: print: B|21675|...
61         const_cast<BytraceLine &>(line).tgid = point.tgid_;
62         streamFilters_->processFilter_->GetOrCreateInternalPid(ts, point.tgid_);
63     }
64     switch (point.phase_) {
65         case 'B': {
66             ParseBeginEvent(comm, ts, pid, point, line);
67             break;
68         }
69         case 'E': {
70             ParseEndEvent(ts, pid, point);
71             break;
72         }
73         case 'S': {
74             ParseStartEvent(comm, ts, pid, point, line);
75             break;
76         }
77         case 'F': {
78             ParseFinishEvent(ts, pid, point, line);
79             break;
80         }
81         case 'C': {
82             ParseCreateEvent(ts, point);
83             break;
84         }
85         case 'G': {
86             ParseGEvent(ts, pid, point);
87             break;
88         }
89         case 'H': {
90             ParseHEvent(ts, point);
91             break;
92         }
93         default:
94             TS_LOGD("point missing!");
95             return false;
96     }
97     return true;
98 }
ParseBeginEvent(const std::string & comm,uint64_t ts,uint32_t pid,TracePoint & point,const BytraceLine & line)99 void PrintEventParser::ParseBeginEvent(const std::string &comm,
100                                        uint64_t ts,
101                                        uint32_t pid,
102                                        TracePoint &point,
103                                        const BytraceLine &line)
104 {
105     uint32_t index = streamFilters_->sliceFilter_->BeginSlice(comm, ts, pid, point.tgid_, INVALID_DATAINDEX,
106                                                               traceDataCache_->GetDataIndex(point.name_));
107     if (index != INVALID_UINT32) {
108         // add distributed data
109         traceDataCache_->GetInternalSlicesData()->SetDistributeInfo(index, point.chainId_, point.spanId_,
110                                                                     point.parentSpanId_, point.flag_);
111 
112         // add traceMeta data
113         traceDataCache_->GetInternalSlicesData()->SetTraceMetadata(index, point.traceLevel_, point.traceTagId_,
114                                                                    point.customArgsId_);
115         if (HandleFrameSliceBeginEvent(point.funcPrefixId_, index, point.funcArgs_, line)) {
116             return;
117         }
118         bool isDiscontinued = false;
119         if (streamFilters_->configFilter_->GetSwitchConfig().TaskPoolConfigEnabled()) {
120             isDiscontinued = streamFilters_->taskPoolFilter_->TaskPoolEvent(point.name_, index);
121         }
122         if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled() && !isDiscontinued) {
123             (void)HandleAnimationBeginEvent(point, index, line);
124         }
125     } else {
126         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_LOST);
127     }
128 }
ParseEndEvent(uint64_t ts,uint32_t pid,const TracePoint & point)129 void PrintEventParser::ParseEndEvent(uint64_t ts, uint32_t pid, const TracePoint &point)
130 {
131     uint32_t index = streamFilters_->sliceFilter_->EndSlice(ts, pid, point.tgid_);
132     HandleFrameSliceEndEvent(ts, point.tgid_, pid, index);
133     if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled()) {
134         streamFilters_->animationFilter_->EndDynamicFrameEvent(ts, index);
135     }
136 }
ParseStartEvent(const std::string & comm,uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)137 void PrintEventParser::ParseStartEvent(const std::string &comm,
138                                        uint64_t ts,
139                                        uint32_t pid,
140                                        const TracePoint &point,
141                                        const BytraceLine &line)
142 {
143     auto cookie = static_cast<int64_t>(point.value_);
144     auto index = streamFilters_->sliceFilter_->StartAsyncSlice(ts, pid, point.tgid_, cookie,
145                                                                traceDataCache_->GetDataIndex(point.name_));
146     if (index == INVALID_UINT64) {
147         return;
148     }
149     // add traceMeta data
150     traceDataCache_->GetInternalSlicesData()->SetTraceMetadata(index, point.traceLevel_, point.traceTagId_,
151                                                                point.customArgsId_, point.customCategoryId_);
152 
153     if (point.name_ == onFrameQueeuStartEvent_) {
154         OnFrameQueueStart(ts, index, point.tgid_);
155     } else if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled() && index != INVALID_UINT64 &&
156                streamFilters_->configFilter_->GetAnimationConfig().CheckIfAnimationEvents(
157                    comm)) { // the comm is taskName
158         streamFilters_->animationFilter_->StartAnimationEvent(line, point, index);
159     }
160 }
ParseFinishEvent(uint64_t ts,uint32_t pid,const TracePoint & point,const BytraceLine & line)161 void PrintEventParser::ParseFinishEvent(uint64_t ts, uint32_t pid, const TracePoint &point, const BytraceLine &line)
162 {
163     auto cookie = static_cast<int64_t>(point.value_);
164     auto index = streamFilters_->sliceFilter_->FinishAsyncSlice(ts, pid, point.tgid_, cookie,
165                                                                 traceDataCache_->GetDataIndex(point.name_));
166     HandleFrameQueueEndEvent(ts, point.tgid_, point.tgid_, index);
167     if (streamFilters_->configFilter_->GetSwitchConfig().AnimationConfigEnabled()) {
168         streamFilters_->animationFilter_->FinishAnimationEvent(line, index);
169     }
170 }
ParseCreateEvent(uint64_t ts,const TracePoint & point)171 void PrintEventParser::ParseCreateEvent(uint64_t ts, const TracePoint &point)
172 {
173     DataIndex nameIndex = traceDataCache_->GetDataIndex(point.name_);
174     uint32_t internalPid = streamFilters_->processFilter_->GetInternalPid(point.tgid_);
175     if (internalPid != INVALID_ID) {
176         streamFilters_->measureFilter_->AppendNewMeasureData(EnumMeasureFilter::PROCESS, internalPid, nameIndex, ts,
177                                                              point.value_);
178         streamFilters_->processFilter_->AddProcessMemory(internalPid);
179     } else {
180         streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_TRACING_MARK_WRITE, STAT_EVENT_DATA_INVALID);
181     }
182 }
ParseGEvent(uint64_t ts,uint32_t pid,TracePoint & point)183 void PrintEventParser::ParseGEvent(uint64_t ts, uint32_t pid, TracePoint &point)
184 {
185     auto cookie = static_cast<int64_t>(point.value_);
186     streamFilters_->sliceFilter_->StartGEvent(ts, pid, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_));
187 }
ParseHEvent(uint64_t ts,const TracePoint & point)188 void PrintEventParser::ParseHEvent(uint64_t ts, const TracePoint &point)
189 {
190     auto cookie = static_cast<int64_t>(point.value_);
191     streamFilters_->sliceFilter_->FinishHEvent(ts, point.tgid_, cookie, traceDataCache_->GetDataIndex(point.name_));
192 }
HandleAnimationBeginEvent(const TracePoint & point,size_t callStackRow,const BytraceLine & line)193 bool PrintEventParser::HandleAnimationBeginEvent(const TracePoint &point, size_t callStackRow, const BytraceLine &line)
194 {
195     if (!streamFilters_->animationFilter_->UpdateDeviceInfoEvent(point, line)) {
196         return streamFilters_->animationFilter_->BeginDynamicFrameEvent(point, callStackRow);
197     }
198     return true;
199 }
SetTraceType(TraceFileType traceType)200 void PrintEventParser::SetTraceType(TraceFileType traceType)
201 {
202     streamFilters_->frameFilter_->SetTraceType(traceType);
203 }
SetTraceClockId(BuiltinClocks clock)204 void PrintEventParser::SetTraceClockId(BuiltinClocks clock)
205 {
206     if (clock != clock_) {
207         clock_ = clock;
208     }
209 }
Finish()210 void PrintEventParser::Finish()
211 {
212     eventToFrameFunctionMap_.clear();
213     frameCallIds_.clear();
214     vsyncSliceMap_.clear();
215     streamFilters_->animationFilter_->Clear();
216     streamFilters_->frameFilter_->Clear();
217 }
CheckTracePoint(std::string_view pointStr) const218 ParseResult PrintEventParser::CheckTracePoint(std::string_view pointStr) const
219 {
220     if (pointStr.size() == 0) {
221         TS_LOGD("get trace point data size is 0!");
222         return PARSE_ERROR;
223     }
224 
225     std::string clockSyncSts = "trace_event_clock_sync";
226     if (pointStr.compare(0, clockSyncSts.length(), clockSyncSts.c_str()) == 0) {
227         TS_LOGD("skip trace point :%s!", clockSyncSts.c_str());
228         return PARSE_ERROR;
229     }
230 
231     if (pointStr.find_first_of('B') != 0 && pointStr.find_first_of('E') != 0 && pointStr.find_first_of('C') != 0 &&
232         pointStr.find_first_of('S') != 0 && pointStr.find_first_of('F') != 0 && pointStr.find_first_of('G') != 0 &&
233         pointStr.find_first_of('H') != 0) {
234         TS_LOGD("trace point not supported : [%c] !", pointStr[0]);
235         return PARSE_ERROR;
236     }
237 
238     if (pointStr.find_first_of('E') != 0 && pointStr.size() == 1) {
239         TS_LOGD("point string size error!");
240         return PARSE_ERROR;
241     }
242 
243     if (pointStr.size() >= MAX_POINT_LENGTH) {
244         if ((pointStr[1] != '|') && (pointStr[1] != '\n')) {
245             TS_LOGD("not support data formart!");
246             return PARSE_ERROR;
247         }
248     }
249 
250     return PARSE_SUCCESS;
251 }
252 
GetPointNameForBegin(std::string_view pointStr,size_t tGidlength) const253 std::string_view PrintEventParser::GetPointNameForBegin(std::string_view pointStr, size_t tGidlength) const
254 {
255     size_t index = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
256 
257     size_t length = pointStr.size() - index - ((pointStr.back() == '\n') ? 1 : 0);
258     std::string_view name = std::string_view(pointStr.data() + index, length);
259     // remove space at the end
260     name = std::string_view(name.data(), name.find_last_not_of(" ") + 1);
261     return name;
262 }
263 
ParseSplitTraceMetaData(const std::string & dataStr,TracePoint & outPoint,bool isAsynEvent) const264 void PrintEventParser::ParseSplitTraceMetaData(const std::string &dataStr, TracePoint &outPoint, bool isAsynEvent) const
265 {
266     std::string metaDataStr = base::Strip(dataStr);
267     uint32_t expectedCount = isAsynEvent ? PARSER_ASYNC_SUM : PARSER_SYNC_SUM;
268     std::vector<std::string> traceMetaDatas = base::SplitStringToVec(metaDataStr, "|", expectedCount);
269     if (traceMetaDatas.size() <= 1) {
270         TS_LOGD("traceMetaDatas size: %zu, dataStr: %s", traceMetaDatas.size(), dataStr.c_str());
271         return;
272     }
273 
274     std::string &marker = traceMetaDatas[1];
275     if (!marker.empty()) {
276         outPoint.traceLevel_ = marker.substr(0, 1);
277         if (marker.size() > 1) {
278             std::string traceTag = marker.substr(1);
279             outPoint.traceTagId_ = traceDataCache_->GetDataIndex(traceTag);
280         }
281     }
282 
283     if (isAsynEvent && traceMetaDatas.size() > CATEGORY_INDEX) {
284         std::string customCategory = traceMetaDatas[CATEGORY_INDEX];
285         outPoint.customCategoryId_ = traceDataCache_->GetDataIndex(customCategory);
286     }
287 
288     if (traceMetaDatas.size() > expectedCount) {
289         std::string customArgs = traceMetaDatas[expectedCount];
290         outPoint.customArgsId_ = traceDataCache_->GetDataIndex(customArgs);
291     }
292 }
293 
HandlerB(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const294 ParseResult PrintEventParser::HandlerB(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
295 {
296     outPoint.name_ = GetPointNameForBegin(pointStr, tGidlength);
297     if (outPoint.name_.empty()) {
298         TS_LOGD("point name is empty!");
299         return PARSE_ERROR;
300     }
301     // Distributed data:
302     // <...>-357 (-------) .... 174330.287420: tracing_mark_write:
303     // B|1298|H:[8b00e96b2,2,1]#C##napi::NativeAsyncWork::QueueWithQos
304     std::smatch matcheLine;
305     bool matched = std::regex_match(outPoint.name_, matcheLine, distributeMatcher_);
306     if (matched) {
307         size_t index = 0;
308         outPoint.chainId_ = matcheLine[++index].str();
309         outPoint.spanId_ = matcheLine[++index].str();
310         outPoint.parentSpanId_ = matcheLine[++index].str();
311         outPoint.flag_ = matcheLine[++index].str();
312     } else {
313         auto space = outPoint.name_.find(' ');
314         if (space != std::string::npos) {
315             outPoint.funcPrefix_ = outPoint.name_.substr(0, space);
316             outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.funcPrefix_);
317             outPoint.funcArgs_ = outPoint.name_.substr(space + 1);
318         } else {
319             outPoint.funcPrefixId_ = traceDataCache_->GetDataIndex(outPoint.name_);
320         }
321     }
322     // traceMetaDatasSrt: H:name|%X%TAG|customArgs
323     ParseSplitTraceMetaData(outPoint.name_, outPoint, false);
324     return PARSE_SUCCESS;
325 }
326 
HandleFrameSliceBeginEvent(DataIndex eventName,size_t callStackRow,std::string & args,const BytraceLine & line)327 bool PrintEventParser::HandleFrameSliceBeginEvent(DataIndex eventName,
328                                                   size_t callStackRow,
329                                                   std::string &args,
330                                                   const BytraceLine &line)
331 {
332     auto it = eventToFrameFunctionMap_.find(eventName);
333     if (it != eventToFrameFunctionMap_.end()) {
334         it->second(callStackRow, args, line);
335         return true;
336     } else if (StartWith(traceDataCache_->GetDataFromDict(eventName), rsOnDoCompositionStr_)) {
337         RSReciveOnDoComposition(callStackRow, args, line);
338         return true;
339     } else if (StartWith(traceDataCache_->GetDataFromDict(eventName), uiVsyncTaskStr_)) {
340         DealUIVsyncTaskEvent(eventName, line);
341     }
342     return false;
343 }
ReciveVsync(size_t callStackRow,std::string & args,const BytraceLine & line)344 bool PrintEventParser::ReciveVsync(size_t callStackRow, std::string &args, const BytraceLine &line)
345 {
346     streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_RECEIVED);
347     // args is like "dataCount:24bytes now:211306766162 expectedEnd:211323423844 vsyncId:3179"
348     std::sregex_iterator it(args.begin(), args.end(), recvVsyncPattern_);
349     std::sregex_iterator end;
350     uint64_t now = INVALID_UINT64;
351     uint64_t expectEnd = INVALID_UINT64;
352     uint32_t vsyncId = INVALID_UINT32;
353     while (it != end) {
354         std::smatch match = *it;
355         std::string key = match.str(1);
356         std::string value = match.str(2);
357         if (key == "now") {
358             now = base::StrToInt<uint64_t>(value).value();
359         } else if (key == "expectedEnd") {
360             expectEnd = base::StrToInt<uint64_t>(value).value();
361         } else if (key == "vsyncId") {
362             vsyncId = base::StrToInt<uint64_t>(value).value();
363         }
364         ++it;
365     }
366     if (now == 0 || expectEnd == 0 || vsyncId == 0) {
367         TS_LOGE("Now,expectedEnd or vsyncId should not be 0!");
368         return false;
369     }
370     streamFilters_->frameFilter_->BeginVsyncEvent(line, now, expectEnd, vsyncId, callStackRow);
371     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
372     if (vsyncSliceMap_.count(iTid)) {
373         vsyncSliceMap_[iTid].push_back(callStackRow);
374     } else {
375         vsyncSliceMap_[iTid] = {callStackRow};
376     }
377     return true;
378 }
379 
DealUIVsyncTaskEvent(DataIndex eventName,const BytraceLine & line)380 bool PrintEventParser::DealUIVsyncTaskEvent(DataIndex eventName, const BytraceLine &line)
381 {
382     auto eventNameStr = traceDataCache_->GetDataFromDict(eventName);
383     std::sregex_iterator it(eventNameStr.begin(), eventNameStr.end(), uiVsyncTaskPattern_);
384     std::sregex_iterator end;
385     uint64_t timeId = 0;
386     while (it != end) {
387         std::smatch match = *it;
388         std::string key = match.str(1);
389         std::string value = match.str(2);
390         if (key == "timestamp") {
391             timeId = base::StrToInt<uint64_t>(value).value();
392         }
393         if (key == "vsyncID") {
394             (void)streamFilters_->frameFilter_->UpdateVsyncId(line, base::StrToInt<uint32_t>(value).value(), timeId);
395             return true;
396         }
397         ++it;
398     }
399     return false;
400 }
OnVsyncEvent(size_t callStackRow,std::string & args,const BytraceLine & line)401 bool PrintEventParser::OnVsyncEvent(size_t callStackRow, std::string &args, const BytraceLine &line)
402 {
403     Unused(args);
404     streamFilters_->frameFilter_->BeginParallelTraceEvent(line, callStackRow);
405     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
406     // when there are mutiple nested OnVsyncEvent,only handle the OnvsyncEvent of the next layer under ReceiveVsync
407     if (vsyncSliceMap_[iTid].size() >= maxVsyncEventSize_) {
408         return false;
409     }
410     vsyncSliceMap_[iTid].push_back(callStackRow);
411     return true;
412 }
RSReciveOnDoComposition(size_t callStackRow,std::string & args,const BytraceLine & line)413 bool PrintEventParser::RSReciveOnDoComposition(size_t callStackRow, std::string &args, const BytraceLine &line)
414 {
415     streamFilters_->statFilter_->IncreaseStat(TRACE_ON_DO_COMPOSITION, STAT_EVENT_RECEIVED);
416     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
417     (void)streamFilters_->frameFilter_->MarkRSOnDoCompositionEvent(iTid);
418     return true;
419 }
OnRwTransaction(size_t callStackRow,std::string & args,const BytraceLine & line)420 bool PrintEventParser::OnRwTransaction(size_t callStackRow, std::string &args, const BytraceLine &line)
421 {
422     // H:MarshRSTransactionData cmdCount:20 transactionFlag:[3799,8] isUni:1
423     std::smatch match;
424     if (std::regex_search(args, match, newTransFlagPattern_)) {
425         std::string mainTheadId = match.str(1);
426         std::string flag2 = match.str(2);
427         std::string currentThread = match.str(3);
428         std::string timeFlag = match.str(4);
429         auto mainThreadId =
430             streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(mainTheadId).value());
431         auto currentThreadId =
432             streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(currentThread).value());
433         auto timeId = base::StrToInt<uint64_t>(timeFlag).value();
434         return streamFilters_->frameFilter_->BeginRSTransactionData(
435             currentThreadId, base::StrToInt<uint32_t>(flag2).value(), mainThreadId, timeId);
436     }
437     if (std::regex_search(args, match, transFlagPattern_)) {
438         std::string mainTheadId = match.str(1);
439         std::string flag2 = match.str(2);
440         // use to update dstRenderSlice_
441         auto mainThreadId =
442             streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(mainTheadId).value());
443         // use to update vsyncRenderSlice_
444         auto currentThreadId = streamFilters_->processFilter_->GetInternalTid(line.pid);
445         return streamFilters_->frameFilter_->BeginRSTransactionData(
446             currentThreadId, base::StrToInt<uint32_t>(flag2).value(), mainThreadId);
447     }
448     return true;
449 }
OnMainThreadProcessCmd(size_t callStackRow,std::string & args,const BytraceLine & line)450 bool PrintEventParser::OnMainThreadProcessCmd(size_t callStackRow, std::string &args, const BytraceLine &line)
451 {
452     std::sregex_iterator it(args.begin(), args.end(), mainProcessCmdPattern_);
453     std::sregex_iterator end;
454     std::vector<FrameFilter::FrameMap> frames;
455     while (it != end) {
456         std::smatch match = *it;
457         std::string value1 = match.str(1);
458         std::string value2 = match.str(2);
459         frames.push_back({streamFilters_->processFilter_->GetInternalTid(base::StrToInt<uint32_t>(value1).value()),
460                           base::StrToInt<uint32_t>(value2).value()});
461         ++it;
462     }
463     auto iTid = streamFilters_->processFilter_->GetInternalTid(line.pid);
464     return streamFilters_->frameFilter_->BeginProcessCommandUni(iTid, frames, callStackRow);
465 }
OnFrameQueueStart(uint64_t ts,size_t callStackRow,uint64_t pid)466 bool PrintEventParser::OnFrameQueueStart(uint64_t ts, size_t callStackRow, uint64_t pid)
467 {
468     streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_RECEIVED);
469     auto iTid = streamFilters_->processFilter_->GetInternalTid(pid);
470     if (streamFilters_->frameFilter_->StartFrameQueue(ts, iTid)) {
471         frameCallIds_.push_back(callStackRow);
472     }
473     return true;
474 }
HandleFrameSliceEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)475 void PrintEventParser::HandleFrameSliceEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
476 {
477     // it can be frame or slice
478     auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
479     if (vsyncSliceMap_.count(iTid)) {
480         auto pos = std::find(vsyncSliceMap_[iTid].begin(), vsyncSliceMap_[iTid].end(), callStackRow);
481         if (pos != vsyncSliceMap_[iTid].end()) {
482             if (!streamFilters_->frameFilter_->EndVsyncEvent(ts, iTid)) {
483                 streamFilters_->statFilter_->IncreaseStat(TRACE_VSYNC, STAT_EVENT_NOTMATCH);
484             }
485             vsyncSliceMap_[iTid].erase(pos);
486         }
487     }
488     return;
489 }
490 
HandleFrameQueueEndEvent(uint64_t ts,uint64_t pid,uint64_t tid,size_t callStackRow)491 void PrintEventParser::HandleFrameQueueEndEvent(uint64_t ts, uint64_t pid, uint64_t tid, size_t callStackRow)
492 {
493     // it can be frame or slice
494     auto iTid = streamFilters_->processFilter_->GetInternalTid(tid);
495     auto pos = std::find(frameCallIds_.begin(), frameCallIds_.end(), callStackRow);
496     if (pos != frameCallIds_.end()) {
497         TS_LOGD("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 "", ts, tid);
498         if (!streamFilters_->frameFilter_->EndFrameQueue(ts, iTid)) {
499             streamFilters_->statFilter_->IncreaseStat(TRACE_FRAMEQUEUE, STAT_EVENT_NOTMATCH);
500             TS_LOGW("ts:%" PRIu64 ", frameSliceEnd:%" PRIu64 " failed", ts, tid);
501         }
502         frameCallIds_.erase(pos);
503     }
504     return;
505 }
HandlerE(void)506 ParseResult PrintEventParser::HandlerE(void)
507 {
508     return PARSE_SUCCESS;
509 }
510 
GetNameLength(std::string_view pointStr,size_t nameIndex)511 size_t PrintEventParser::GetNameLength(std::string_view pointStr, size_t nameIndex)
512 {
513     size_t namelength = 0;
514     for (size_t i = nameIndex; i < pointStr.size(); i++) {
515         if (pointStr[i] == ' ') {
516             namelength = i - nameIndex;
517         }
518         if (pointStr[i] == '|') {
519             namelength = i - nameIndex;
520             break;
521         }
522     }
523     return namelength;
524 }
525 
GetValueLength(std::string_view pointStr,size_t valueIndex) const526 size_t PrintEventParser::GetValueLength(std::string_view pointStr, size_t valueIndex) const
527 {
528     size_t valuePipe = pointStr.find('|', valueIndex);
529     size_t valueLen = pointStr.size() - valueIndex;
530     if (valuePipe != std::string_view::npos) {
531         valueLen = valuePipe - valueIndex;
532     }
533 
534     if (valueLen == 0) {
535         return 0;
536     }
537 
538     if (pointStr[valueIndex + valueLen - POINT_LENGTH] == '\n') {
539         valueLen--;
540     }
541 
542     return valueLen;
543 }
544 
HandlerCSF(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const545 ParseResult PrintEventParser::HandlerCSF(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
546 {
547     // point name
548     size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
549     size_t namelength = GetNameLength(pointStr, nameIndex);
550     if (namelength == 0) {
551         TS_LOGD("point name length is error!");
552         return PARSE_ERROR;
553     }
554     outPoint.name_ = std::string_view(pointStr.data() + nameIndex, namelength);
555 
556     // point value
557     size_t valueIndex = nameIndex + namelength + POINT_LENGTH;
558     size_t valueLen = GetValueLength(pointStr, valueIndex);
559     if (valueLen == 0) {
560         TS_LOGD("point value length is error!");
561         return PARSE_ERROR;
562     }
563 
564     std::string valueStr(pointStr.data() + valueIndex, valueLen);
565     if (!base::StrToInt<int64_t>(valueStr).has_value()) {
566         TS_LOGD("point value is error!");
567         return PARSE_ERROR;
568     }
569     outPoint.value_ = base::StrToInt<int64_t>(valueStr).value();
570 
571     size_t valuePipe = pointStr.find('|', valueIndex);
572     if (valuePipe != std::string_view::npos) {
573         size_t groupLen = pointStr.size() - valuePipe - POINT_LENGTH;
574         if (groupLen == 0) {
575             return PARSE_ERROR;
576         }
577 
578         if (pointStr[pointStr.size() - POINT_LENGTH] == '\n') {
579             groupLen--;
580         }
581 
582         outPoint.categoryGroup_ = std::string_view(pointStr.data() + valuePipe + 1, groupLen);
583     }
584     // traceMetaDatasSrt: taskId|%X%TAG|customCategory|customArgs
585     std::string metaDataStr(pointStr.data() + valueIndex);
586     if (outPoint.phase_ == 'S') {
587         ParseSplitTraceMetaData(metaDataStr, outPoint, true);
588     }
589     return PARSE_SUCCESS;
590 }
591 
GetGHNameLength(std::string_view pointStr,size_t nameIndex)592 size_t PrintEventParser::GetGHNameLength(std::string_view pointStr, size_t nameIndex)
593 {
594     size_t endPos = pointStr.find('|', nameIndex);
595     if (endPos == std::string_view::npos) {
596         return 0;
597     }
598     size_t nextEndPos = pointStr.find('|', endPos + 1);
599     if (nextEndPos == std::string_view::npos) {
600         return 0;
601     }
602     return nextEndPos - nameIndex;
603 }
HandlerGH(std::string_view pointStr,TracePoint & outPoint,size_t tGidlength) const604 ParseResult PrintEventParser::HandlerGH(std::string_view pointStr, TracePoint &outPoint, size_t tGidlength) const
605 {
606     size_t nameIndex = MAX_POINT_LENGTH + tGidlength + POINT_LENGTH;
607     size_t nameLength = GetGHNameLength(pointStr, nameIndex);
608     if (nameLength == 0) {
609         TS_LOGD("point name length is error!");
610         return PARSE_ERROR;
611     }
612     outPoint.name_ = std::string_view(pointStr.data() + nameIndex, nameLength);
613     size_t valueIndex = nameIndex + nameLength + POINT_LENGTH;
614     size_t valueLen = GetValueLength(pointStr, valueIndex);
615     if (valueLen == 0) {
616         TS_LOGD("point value length is error!");
617         return PARSE_ERROR;
618     }
619     if (!base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).has_value()) {
620         TS_LOGD("point value is error!");
621         return PARSE_ERROR;
622     }
623     outPoint.value_ = base::StrToInt<int64_t>(std::string(pointStr.data() + valueIndex, valueLen)).value();
624     return PARSE_SUCCESS;
625 }
626 
GetTracePoint(std::string_view pointStr,TracePoint & outPoint) const627 ParseResult PrintEventParser::GetTracePoint(std::string_view pointStr, TracePoint &outPoint) const
628 {
629     if (CheckTracePoint(pointStr) != PARSE_SUCCESS) {
630         return PARSE_ERROR;
631     }
632 
633     size_t tGidlength = 0;
634     // we may get wrong format data like tracing_mark_write: E
635     // while the format data must be E|call-tid
636     // please use a regular-format to get all the data
637     outPoint.phase_ = pointStr.front();
638     outPoint.tgid_ = GetThreadGroupId(pointStr, tGidlength);
639 
640     ParseResult ret = PARSE_ERROR;
641     switch (outPoint.phase_) {
642         case 'B': {
643             ret = HandlerB(pointStr, outPoint, tGidlength);
644             break;
645         }
646         case 'E': {
647             ret = HandlerE();
648             break;
649         }
650         case 'S':
651         case 'F':
652         case 'C': {
653             ret = HandlerCSF(pointStr, outPoint, tGidlength);
654             break;
655         }
656         case 'G':
657         case 'H': {
658             ret = HandlerGH(pointStr, outPoint, tGidlength);
659             break;
660         }
661         default:
662             return PARSE_ERROR;
663     }
664     return ret;
665 }
666 
GetThreadGroupId(std::string_view pointStr,size_t & length) const667 uint32_t PrintEventParser::GetThreadGroupId(std::string_view pointStr, size_t &length) const
668 {
669     for (size_t i = MAX_POINT_LENGTH; i < pointStr.size(); i++) {
670         if (pointStr[i] == '|' || pointStr[i] == '\n') {
671             break;
672         }
673 
674         if (pointStr[i] < '0' || pointStr[i] > '9') {
675             return PARSE_ERROR;
676         }
677 
678         length++;
679     }
680 
681     std::string str(pointStr.data() + MAX_POINT_LENGTH, length);
682     return base::StrToInt<uint32_t>(str).value_or(0);
683 }
684 } // namespace TraceStreamer
685 } // namespace SysTuning
686