• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "animation_filter.h"
17 #include "string_help.h"
18 #include "string_to_numerical.h"
19 
20 namespace SysTuning {
21 namespace TraceStreamer {
22 constexpr uint8_t GENERATE_VSYNC_EVENT_MAX = 5;
23 constexpr uint8_t DYNAMIC_STACK_DEPTH_MIN = 4;
24 constexpr uint16_t FPS_60 = 60;
25 constexpr uint16_t FPS_70 = 70;
26 constexpr uint16_t FPS_90 = 90;
27 constexpr uint16_t FPS_100 = 100;
28 constexpr uint16_t FPS_120 = 120;
29 
AnimationFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)30 AnimationFilter::AnimationFilter(TraceDataCache* dataCache, const TraceStreamerFilters* filter)
31     : FilterBase(dataCache, filter)
32 {
33     dynamicFrame_ = traceDataCache_->GetDynamicFrame();
34     callStackSlice_ = traceDataCache_->GetInternalSlicesData();
35     if (dynamicFrame_ == nullptr || callStackSlice_ == nullptr) {
36         TS_LOGE("dynamicFrame_ or callStackSlice_ is nullptr.");
37     }
38 }
~AnimationFilter()39 AnimationFilter::~AnimationFilter() {}
UpdateDeviceFps(const BytraceLine & line)40 bool AnimationFilter::UpdateDeviceFps(const BytraceLine& line)
41 {
42     generateVsyncCnt_++;
43     if (generateFirstTime_ == INVALID_UINT64) {
44         generateFirstTime_ = line.ts;
45     }
46     if (generateVsyncCnt_ <= GENERATE_VSYNC_EVENT_MAX) {
47         return true;
48     }
49     // calculate the average frame rate
50     uint64_t generateTimePeriod = (line.ts - generateFirstTime_) / GENERATE_VSYNC_EVENT_MAX;
51     uint32_t fps = BILLION_NANOSECONDS / generateTimePeriod;
52     if (fps < FPS_70) {
53         traceDataCache_->GetDeviceInfo()->UpdateFrameRate(FPS_60);
54     } else if (fps < FPS_100) {
55         traceDataCache_->GetDeviceInfo()->UpdateFrameRate(FPS_90);
56     } else {
57         traceDataCache_->GetDeviceInfo()->UpdateFrameRate(FPS_120);
58     }
59     TS_LOGI("physical frame rate is %u", fps);
60     return true;
61 }
UpdateDeviceScreenSize(const TracePoint & point)62 bool AnimationFilter::UpdateDeviceScreenSize(const TracePoint& point)
63 {
64     // get width and height, eg:funcArgs=(0, 0, 1344, 2772) Alpha: 1.00
65     std::smatch matcheLine;
66     std::regex entryViewArgsPattern(R"(\(\d+,\s*\d+,\s*(\d+),\s*(\d+)\))");
67     if (!std::regex_search(point.funcArgs_, matcheLine, entryViewArgsPattern)) {
68         TS_LOGE("Not support this event: %s\n", point.name_.data());
69         return false;
70     }
71     uint8_t index = 0;
72     uint32_t width = base::StrToInt<uint32_t>(matcheLine[++index].str()).value();
73     uint32_t height = base::StrToInt<uint32_t>(matcheLine[++index].str()).value();
74     traceDataCache_->GetDeviceInfo()->UpdateWidthAndHeight(matcheLine);
75     TS_LOGI("physical width is %u, height is %u", width, height);
76     return true;
77 }
UpdateDeviceInfoEvent(const TracePoint & point,const BytraceLine & line)78 bool AnimationFilter::UpdateDeviceInfoEvent(const TracePoint& point, const BytraceLine& line)
79 {
80     if (traceDataCache_->GetConstDeviceInfo().PhysicalFrameRate() == INVALID_UINT32 &&
81         StartWith(point.name_, generateVsyncCmd_)) {
82         return UpdateDeviceFps(line);
83     } else if (traceDataCache_->GetConstDeviceInfo().PhysicalWidth() == INVALID_UINT32 &&
84                point.funcPrefixId_ == entryViewCmd_) {
85         return UpdateDeviceScreenSize(point);
86     }
87     return false;
88 }
BeginDynamicFrameEvent(const TracePoint & point,size_t callStackRow)89 bool AnimationFilter::BeginDynamicFrameEvent(const TracePoint& point, size_t callStackRow)
90 {
91     // get the parent frame of data
92     const std::optional<uint64_t>& parentId = callStackSlice_->ParentIdData()[callStackRow];
93     uint8_t depth = callStackSlice_->Depths()[callStackRow];
94     if (depth < DYNAMIC_STACK_DEPTH_MIN || !parentId.has_value()) {
95         return false;
96     }
97     const std::string& curStackName = traceDataCache_->GetDataFromDict(callStackSlice_->NamesData()[callStackRow]);
98     if (!StartWith(curStackName, leashWindowCmd_)) {
99         return false;
100     }
101     // get name 'xxx' from [xxx], eg:H:RSUniRender::Process:[xxx]
102     auto nameSize = point.funcPrefix_.size() - rsUniProcessCmd_.size() - 1;
103     if (nameSize <= 0) {
104         return false;
105     }
106     auto nameIndex = traceDataCache_->GetDataIndex(point.funcPrefix_.substr(rsUniProcessCmd_.size(), nameSize));
107     auto dynamicFramRow = dynamicFrame_->AppendDynamicFrame(nameIndex);
108     callStackRowMap_.emplace(callStackRow, dynamicFramRow);
109     return true;
110 }
StartAnimationEvent(const BytraceLine & line,size_t callStackRow)111 void AnimationFilter::StartAnimationEvent(const BytraceLine& line, size_t callStackRow)
112 {
113     auto animationRow = traceDataCache_->GetAnimation()->AppendAnimation(line.ts);
114     animationCallIds_.emplace(callStackRow, animationRow);
115 }
FinishAnimationEvent(const BytraceLine & line,size_t callStackRow)116 bool AnimationFilter::FinishAnimationEvent(const BytraceLine& line, size_t callStackRow)
117 {
118     auto iter = animationCallIds_.find(callStackRow);
119     if (iter == animationCallIds_.end()) {
120         return false;
121     }
122     auto animationRow = iter->second;
123     traceDataCache_->GetAnimation()->UpdateEndPoint(animationRow, line.ts);
124     animationCallIds_.erase(iter);
125     return true;
126 }
UpdateDynamicEndTime(const uint64_t curFrameRow,uint64_t curStackRow)127 bool AnimationFilter::UpdateDynamicEndTime(const uint64_t curFrameRow, uint64_t curStackRow)
128 {
129     // update dynamicFrame endTime, filter up from the curStackRow, until reach the top
130     for (uint8_t stackCurDepth = callStackSlice_->Depths()[curStackRow]; stackCurDepth > 0; stackCurDepth--) {
131         if (!callStackSlice_->ParentIdData()[curStackRow].has_value()) {
132             return false;
133         }
134         curStackRow = callStackSlice_->ParentIdData()[curStackRow].value();
135         // use 'H:RSMainThread::DoComposition' endTime as dynamicFrame endTime
136         if (rsDoCompCmd_ == callStackSlice_->NamesData()[curStackRow]) {
137             auto endTime = callStackSlice_->TimeStampData()[curStackRow] + callStackSlice_->DursData()[curStackRow];
138             dynamicFrame_->UpdateEndTime(curFrameRow, endTime);
139             return true;
140         }
141     }
142     return false;
143 }
UpdateDynamicFrameInfo()144 void AnimationFilter::UpdateDynamicFrameInfo()
145 {
146     std::smatch matcheLine;
147     std::regex leashWindowPattern(R"((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\)\s+Alpha:\s+-*(\d+\.\d+))");
148     uint64_t curStackRow = INVALID_UINT64;
149     uint64_t curFrameRow = INVALID_UINT64;
150     for (const auto& it : callStackRowMap_) {
151         curStackRow = it.first;
152         curFrameRow = it.second;
153         // update dynamicFrame pos, eg:H:RSUniRender::Process:[leashWindow25] (0, 0, 1344, 2772) Alpha: 1.00
154         auto nameDataIndex = callStackSlice_->NamesData()[curStackRow];
155         const std::string& curStackName = traceDataCache_->GetDataFromDict(nameDataIndex);
156         const std::string& funcArgs = curStackName.substr(leashWindowCmd_.size());
157         if (!std::regex_search(funcArgs, matcheLine, leashWindowPattern)) {
158             TS_LOGE("Not support this event: %s\n", funcArgs.data());
159             continue;
160         }
161         dynamicFrame_->UpdatePosition(
162             curFrameRow, matcheLine,
163             traceDataCache_->GetDataIndex((matcheLine[DYNAMICFRAME_MATCH_LAST].str()))); // alpha
164         UpdateDynamicEndTime(curFrameRow, curStackRow);
165     }
166     TS_LOGI("UpdateDynamicFrame (%zu) endTime and pos finish", callStackRowMap_.size());
167     // this can only be cleared by the UpdateDynamicFrameInfo function
168     callStackRowMap_.clear();
169 }
Clear()170 void AnimationFilter::Clear()
171 {
172     generateFirstTime_ = INVALID_UINT64;
173     generateVsyncCnt_ = 0;
174     animationCallIds_.clear();
175 }
176 } // namespace TraceStreamer
177 } // namespace SysTuning
178