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
16 #include "app_start_filter.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 constexpr uint32_t INVALID_DATA = 2;
21 constexpr uint32_t MIN_VECTOR_SIZE = 2;
22 constexpr uint32_t VALID_DATA_COUNT = 6;
APPStartupFilter(TraceDataCache * dataCache,const TraceStreamerFilters * filter)23 APPStartupFilter::APPStartupFilter(TraceDataCache *dataCache, const TraceStreamerFilters *filter)
24 : FilterBase(dataCache, filter), mAPPStartupData_(0)
25 {
26 }
27
28 APPStartupFilter::~APPStartupFilter() = default;
29
FilterAllAPPStartupData()30 void APPStartupFilter::FilterAllAPPStartupData()
31 {
32 ParserAppStartup();
33 ParserSoInitalization();
34 }
35
CaclRsDataByPid(appMap & mAPPStartupData)36 bool APPStartupFilter::CaclRsDataByPid(appMap &mAPPStartupData)
37 {
38 auto frameSliceData = traceDataCache_->GetFrameSliceData();
39 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
40 for (const auto &item : mAPPStartupData) {
41 if (item.second.empty()) {
42 continue;
43 }
44 auto itorSecond = item.second.begin();
45 if (itorSecond->second->ipid_ == INVALID_UINT32) {
46 continue;
47 }
48 for (int m = 0; m < frameSliceData->Ipids().size(); m++) {
49 if (itorSecond->second->ipid_ == frameSliceData->Ipids()[m] && !frameSliceData->Types()[m] &&
50 frameSliceData->Flags()[m] != INVALID_DATA) {
51 auto startTime = sliceData.TimeStampData()[frameSliceData->CallStackIds()[m]];
52 auto callId = sliceData.CallIds()[frameSliceData->CallStackIds()[m]];
53 auto endTime = startTime + frameSliceData->Durs()[m];
54 if (frameSliceData->Durs()[m] == INVALID_UINT64) {
55 endTime = INVALID_UINT64;
56 }
57 mAPPStartupData[item.first].emplace(FIRST_FRAME_APP_PHASE,
58 std::make_unique<APPStartupData>(callId, itorSecond->second->ipid_,
59 itorSecond->second->tid_,
60 startTime, endTime));
61 auto dstId = frameSliceData->Dsts()[m];
62 if (dstId == INVALID_UINT64) {
63 continue;
64 }
65 callId = sliceData.CallIds()[frameSliceData->CallStackIds()[dstId]];
66 startTime = frameSliceData->TimeStampData()[dstId];
67 endTime = startTime + frameSliceData->Durs()[dstId];
68 mAPPStartupData[item.first].emplace(FIRST_FRAME_RENDER_PHASE,
69 std::make_unique<APPStartupData>(callId, itorSecond->second->ipid_,
70 itorSecond->second->tid_,
71 startTime, endTime));
72 break;
73 }
74 }
75 }
76 return false;
77 }
78
UpdatePidByNameIndex(const appMap & mAPPStartupData)79 void APPStartupFilter::UpdatePidByNameIndex(const appMap &mAPPStartupData)
80 {
81 auto threadData = traceDataCache_->GetConstThreadData();
82 for (const auto &item : mAPPStartupData) {
83 auto ipid = INVALID_UINT32;
84 auto tid = INVALID_UINT32;
85 if (item.second.count(UI_ABILITY_LAUNCHING)) {
86 ipid = item.second.at(UI_ABILITY_LAUNCHING)->ipid_;
87 tid = item.second.at(UI_ABILITY_LAUNCHING)->tid_;
88 } else {
89 for (int i = 0; i < threadData.size(); ++i) {
90 if (item.first == threadData[i].nameIndex_) {
91 ipid = threadData[i].internalPid_;
92 tid = threadData[i].tid_;
93 }
94 }
95 }
96 for (const auto &itemSecond : item.second) {
97 itemSecond.second->ipid_ = ipid;
98 itemSecond.second->tid_ = tid;
99 }
100 }
101 }
102
AppendAssociatedData(DataIndex packedNameIndex,const std::map<uint32_t,std::unique_ptr<APPStartupData>> & stagesData)103 void APPStartupFilter::AppendAssociatedData(DataIndex packedNameIndex,
104 const std::map<uint32_t, std::unique_ptr<APPStartupData>> &stagesData)
105 {
106 for (auto itorSecond = stagesData.begin(); itorSecond != stagesData.end(); ++itorSecond) {
107 auto item = itorSecond;
108 auto endTime = INVALID_UINT64;
109 if (item->first < VALID_DATA_COUNT) {
110 int num = item->first + 1;
111 if ((++item) != stagesData.end() && num == item->first) {
112 endTime = (item)->second->startTime_;
113 }
114 } else {
115 endTime = itorSecond->second->endTime_;
116 }
117 AppStartupRow appStartupRow = {itorSecond->second->ipid_,
118 itorSecond->second->tid_,
119 itorSecond->second->callid_,
120 itorSecond->second->startTime_,
121 endTime,
122 itorSecond->first,
123 packedNameIndex};
124 traceDataCache_->GetAppStartupData()->AppendNewData(appStartupRow);
125 }
126 }
127
128 // AppenAllData
AppenAllData(const appMap & mAPPStartupData)129 void APPStartupFilter::AppenAllData(const appMap &mAPPStartupData)
130 {
131 for (auto itor = mAPPStartupData.begin(); itor != mAPPStartupData.end(); ++itor) {
132 if (!(itor->second).count(UI_ABILITY_LAUNCHING)) {
133 continue;
134 }
135 AppendAssociatedData(itor->first, itor->second);
136 }
137 }
138
UpdateAPPStartupData(uint32_t row,const std::string & nameString,uint32_t startIndex)139 bool APPStartupFilter::UpdateAPPStartupData(uint32_t row, const std::string &nameString, uint32_t startIndex)
140 {
141 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
142 auto vNameString = SplitStringToVec(nameString, "##");
143 TS_CHECK_TRUE_RET(vNameString.size() >= MIN_VECTOR_SIZE, false);
144 auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str());
145 // for update the last Item(valid val)
146 if (!procTouchItems_.empty()) {
147 auto lastProcTouchItem = std::move(procTouchItems_.back());
148 mAPPStartupData_[dataIndex].insert(std::make_pair(PROCESS_TOUCH, std::move(lastProcTouchItem)));
149 procTouchItems_.clear();
150 }
151 if (!startUIAbilityBySCBItems_.empty()) {
152 auto lastStartUIAbilityBySCBItem = std::move(startUIAbilityBySCBItems_.back());
153 mAPPStartupData_[dataIndex].insert(
154 std::make_pair(START_UI_ABILITY_BY_SCB, std::move(lastStartUIAbilityBySCBItem)));
155 startUIAbilityBySCBItems_.clear();
156 }
157 if (!loadAbilityItems_.empty()) {
158 auto lastLoadAbilityItem = std::move(loadAbilityItems_.back());
159 mAPPStartupData_[dataIndex].insert(std::make_pair(LOAD_ABILITY, std::move(lastLoadAbilityItem)));
160 loadAbilityItems_.clear();
161 }
162 auto callId = sliceData.CallIds()[row];
163 auto startTime = sliceData.TimeStampData()[row];
164 mAPPStartupData_[dataIndex].insert(
165 std::make_pair(startIndex, std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime,
166 INVALID_UINT64)));
167 return true;
168 }
169
ParserAppStartup()170 void APPStartupFilter::ParserAppStartup()
171 {
172 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
173 std::string mainThreadName = "";
174 for (auto i = 0; i < sliceData.NamesData().size(); i++) {
175 auto &nameString = traceDataCache_->GetDataFromDict(sliceData.NamesData()[i]);
176 auto callId = sliceData.CallIds()[i];
177 auto startTime = sliceData.TimeStampData()[i];
178 if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase1(nameString)) {
179 procTouchItems_.emplace_back(
180 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
181 } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase2(nameString)) {
182 startUIAbilityBySCBItems_.emplace_back(
183 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
184 } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase3(nameString)) {
185 loadAbilityItems_.emplace_back(
186 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
187 } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase4(nameString)) {
188 UpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING);
189 } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase5(nameString)) {
190 ProcAbilityLaunchData(nameString, i);
191 } else if (streamFilters_->configFilter_->GetAppStartupConfig().CheckIfPhase6(nameString)) {
192 ProcForegroundData(i);
193 }
194 }
195 for (auto &item : mAPPStartupDataWithPid_) {
196 UpdatePidByNameIndex(item.second);
197 CaclRsDataByPid(item.second);
198 AppenAllData(item.second);
199 }
200 return;
201 }
202
ProcAbilityLaunchData(const std::string & nameString,uint64_t raw)203 bool APPStartupFilter::ProcAbilityLaunchData(const std::string &nameString, uint64_t raw)
204 {
205 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
206 auto vNameString = SplitStringToVec(nameString, "##");
207 TS_CHECK_TRUE_RET(vNameString.size() >= MIN_VECTOR_SIZE, false);
208 auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str());
209 uint32_t callId = sliceData.CallIds()[raw];
210 uint64_t startTime = sliceData.TimeStampData()[raw];
211 if (dataIndex == INVALID_DATAINDEX) {
212 return false;
213 }
214 auto thread = traceDataCache_->GetThreadData(sliceData.CallIds()[raw]);
215 thread->nameIndex_ = dataIndex;
216 mAPPStartupData_[dataIndex].insert(std::make_pair(
217 UI_ABILITY_LAUNCHING,
218 std::make_unique<APPStartupData>(callId, thread->internalPid_, thread->tid_, startTime, INVALID_UINT64)));
219 mAPPStartupDataWithPid_.insert(std::make_pair(thread->internalPid_, std::move(mAPPStartupData_)));
220 return true;
221 }
222
ProcForegroundData(uint64_t raw)223 void APPStartupFilter::ProcForegroundData(uint64_t raw)
224 {
225 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
226 uint32_t callId = sliceData.CallIds()[raw];
227 uint64_t startTime = sliceData.TimeStampData()[raw];
228 auto threadData = traceDataCache_->GetConstThreadData();
229 // callid is thread table->itid
230 auto nameindex = threadData[callId].nameIndex_;
231 auto ipid = threadData[callId].internalPid_;
232 auto tid = threadData[callId].tid_;
233 if (mAPPStartupDataWithPid_.count(ipid) && mAPPStartupDataWithPid_[ipid].count(nameindex) &&
234 !mAPPStartupDataWithPid_[ipid][nameindex].count(UI_ABILITY_ONFOREGROUND)) {
235 mAPPStartupDataWithPid_[ipid][nameindex].insert(std::make_pair(
236 UI_ABILITY_ONFOREGROUND, std::make_unique<APPStartupData>(callId, ipid, tid, startTime, INVALID_UINT64)));
237 }
238 }
239
CalcDepthByTimeStamp(std::map<uint32_t,std::map<uint64_t,uint32_t>>::iterator it,uint32_t & depth,uint64_t endTime,uint64_t startTime)240 void APPStartupFilter::CalcDepthByTimeStamp(std::map<uint32_t, std::map<uint64_t, uint32_t>>::iterator it,
241 uint32_t &depth,
242 uint64_t endTime,
243 uint64_t startTime)
244 {
245 if (it->second.empty()) {
246 it->second.insert(std::make_pair(endTime, 0));
247 return;
248 }
249 auto itor = it->second.begin();
250 if (itor->first > startTime) {
251 depth = it->second.size();
252 it->second.insert(std::make_pair(endTime, it->second.size()));
253 return;
254 }
255 depth = itor->second;
256 for (auto itorSecond = itor; itorSecond != it->second.end(); ++itorSecond) {
257 if (itorSecond->first < startTime && depth > itorSecond->second) {
258 depth = itorSecond->second;
259 itor = itorSecond;
260 }
261 }
262 it->second.erase(itor);
263 it->second.insert(std::make_pair(endTime, depth));
264 }
265
ParserSoInitalization()266 void APPStartupFilter::ParserSoInitalization()
267 {
268 std::map<uint32_t, std::map<uint64_t, uint32_t>> mMaxTimeAndDepthWithPid;
269 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
270 auto threadData = traceDataCache_->GetConstThreadData();
271 std::string nameString = "";
272 for (auto i = 0; i < sliceData.NamesData().size(); i++) {
273 nameString = traceDataCache_->GetDataFromDict(sliceData.NamesData()[i]);
274 if (nameString.find(dlopenCmd_) != std::string::npos) {
275 uint64_t startTime = sliceData.TimeStampData()[i];
276 uint64_t endTime = startTime + sliceData.DursData()[i];
277 uint32_t depth = 0;
278 auto callId = sliceData.CallIds()[i];
279 auto pid = threadData[callId].internalPid_;
280 auto tid = threadData[callId].tid_;
281 auto it = mMaxTimeAndDepthWithPid.find(pid);
282 SoStaticInitalizationRow soStaticInitalizationRow;
283 if (it == mMaxTimeAndDepthWithPid.end()) {
284 mMaxTimeAndDepthWithPid.insert(std::make_pair(pid, std::map<uint64_t, uint32_t>{{endTime, 0}}));
285 soStaticInitalizationRow.ipid = pid;
286 soStaticInitalizationRow.tid = tid;
287 soStaticInitalizationRow.callId = callId;
288 soStaticInitalizationRow.startTime = startTime;
289 soStaticInitalizationRow.endTime = endTime;
290 soStaticInitalizationRow.soName = sliceData.NamesData()[i];
291 soStaticInitalizationRow.depth = depth;
292 traceDataCache_->GetSoStaticInitalizationData()->AppendNewData(soStaticInitalizationRow);
293 continue;
294 } else {
295 CalcDepthByTimeStamp(it, depth, endTime, startTime);
296 soStaticInitalizationRow.ipid = threadData[callId].internalPid_;
297 soStaticInitalizationRow.tid = threadData[callId].tid_;
298 soStaticInitalizationRow.callId = callId;
299 soStaticInitalizationRow.startTime = startTime;
300 soStaticInitalizationRow.endTime = endTime;
301 soStaticInitalizationRow.soName = sliceData.NamesData()[i];
302 soStaticInitalizationRow.depth = depth;
303 traceDataCache_->GetSoStaticInitalizationData()->AppendNewData(soStaticInitalizationRow);
304 }
305 }
306 }
307 }
308 } // namespace TraceStreamer
309 } // namespace SysTuning
310