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 "app_start_filter.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 constexpr uint32_t INVAILD_DATA = 2;
21 constexpr uint32_t MIN_VECTOR_SIZE = 2;
22 constexpr uint32_t VAILD_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] != INVAILD_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
AppendData(const appMap & mAPPStartupData)103 void APPStartupFilter::AppendData(const appMap& mAPPStartupData)
104 {
105 for (auto itor = mAPPStartupData.begin(); itor != mAPPStartupData.end(); ++itor) {
106 if (!(itor->second).count(UI_ABILITY_LAUNCHING)) {
107 continue;
108 }
109 for (auto itorSecond = itor->second.begin(); itorSecond != itor->second.end(); ++itorSecond) {
110 auto item = itorSecond;
111 auto endTime = INVALID_UINT64;
112 if (item->first < VAILD_DATA_COUNT) {
113 int num = item->first + 1;
114 if ((++item) != itor->second.end() && num == item->first) {
115 endTime = (item)->second->startTime_;
116 }
117 } else {
118 endTime = itorSecond->second->endTime_;
119 }
120 traceDataCache_->GetAppStartupData()->AppendNewData(
121 itorSecond->second->ipid_, itorSecond->second->tid_, itorSecond->second->callid_,
122 itorSecond->second->startTime_, endTime, itorSecond->first, itor->first);
123 }
124 }
125 }
126
UpdateAPPStartupData(uint32_t row,const std::string & nameString,uint32_t startIndex)127 bool APPStartupFilter::UpdateAPPStartupData(uint32_t row, const std::string& nameString, uint32_t startIndex)
128 {
129 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
130 auto vNameString = SplitStringToVec(nameString, "##");
131 TS_CHECK_TRUE_RET(vNameString.size() >= MIN_VECTOR_SIZE, false);
132 auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str());
133 // for update the last Item(valid val)
134 if (!procTouchItems_.empty()) {
135 auto lastProcTouchItem = std::move(procTouchItems_.back());
136 mAPPStartupData_[dataIndex].insert(std::make_pair(PROCESS_TOUCH, std::move(lastProcTouchItem)));
137 procTouchItems_.clear();
138 }
139 if (!startUIAbilityBySCBItems_.empty()) {
140 auto lastStartUIAbilityBySCBItem = std::move(startUIAbilityBySCBItems_.back());
141 mAPPStartupData_[dataIndex].insert(
142 std::make_pair(START_UI_ABILITY_BY_SCB, std::move(lastStartUIAbilityBySCBItem)));
143 startUIAbilityBySCBItems_.clear();
144 }
145 if (!loadAbilityItems_.empty()) {
146 auto lastLoadAbilityItem = std::move(loadAbilityItems_.back());
147 mAPPStartupData_[dataIndex].insert(std::make_pair(LOAD_ABILITY, std::move(lastLoadAbilityItem)));
148 loadAbilityItems_.clear();
149 }
150 auto callId = sliceData.CallIds()[row];
151 auto startTime = sliceData.TimeStampData()[row];
152 mAPPStartupData_[dataIndex].insert(
153 std::make_pair(startIndex, std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime,
154 INVALID_UINT64)));
155 return true;
156 }
157
ParserAppStartup()158 void APPStartupFilter::ParserAppStartup()
159 {
160 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
161 std::string mainThreadName = "";
162 for (auto i = 0; i < sliceData.NamesData().size(); i++) {
163 auto& nameString = traceDataCache_->GetDataFromDict(sliceData.NamesData()[i]);
164 auto callId = sliceData.CallIds()[i];
165 auto startTime = sliceData.TimeStampData()[i];
166 if (StartWith(nameString, procTouchCmd_)) {
167 procTouchItems_.emplace_back(
168 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
169 } else if (StartWith(nameString, startUIAbilityBySCBCmd_)) {
170 startUIAbilityBySCBItems_.emplace_back(
171 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
172 } else if (StartWith(nameString, loadAbilityCmd_)) {
173 loadAbilityItems_.emplace_back(
174 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
175 } else if (StartWith(nameString, appLaunchCmd_)) {
176 UpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING);
177 } else if (StartWith(nameString, uiLaunchCmd_)) {
178 if (!ProcAbilityLaunchData(nameString, i)) {
179 continue;
180 }
181 } else if (StartWith(nameString, uiOnForegroundFirstCmd_) || StartWith(nameString, uiOnForegroundSecCmd_)) {
182 ProcForegroundData(i);
183 }
184 }
185 for (auto& item : mAPPStartupDataWithPid_) {
186 UpdatePidByNameIndex(item.second);
187 CaclRsDataByPid(item.second);
188 AppendData(item.second);
189 }
190 return;
191 }
192
ProcAbilityLaunchData(const std::string & nameString,uint64_t raw)193 bool APPStartupFilter::ProcAbilityLaunchData(const std::string& nameString, uint64_t raw)
194 {
195 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
196 auto vNameString = SplitStringToVec(nameString, "##");
197 TS_CHECK_TRUE_RET(vNameString.size() >= MIN_VECTOR_SIZE, false);
198 auto dataIndex = traceDataCache_->GetDataIndex(vNameString[1].c_str());
199 uint32_t callId = sliceData.CallIds()[raw];
200 uint64_t startTime = sliceData.TimeStampData()[raw];
201 if (dataIndex == INVALID_DATAINDEX) {
202 return false;
203 }
204 auto thread = traceDataCache_->GetThreadData(sliceData.CallIds()[raw]);
205 thread->nameIndex_ = dataIndex;
206 mAPPStartupData_[dataIndex].insert(std::make_pair(
207 UI_ABILITY_LAUNCHING,
208 std::make_unique<APPStartupData>(callId, thread->internalPid_, thread->tid_, startTime, INVALID_UINT64)));
209 mAPPStartupDataWithPid_.insert(std::make_pair(thread->internalPid_, std::move(mAPPStartupData_)));
210 return true;
211 }
212
ProcForegroundData(uint64_t raw)213 void APPStartupFilter::ProcForegroundData(uint64_t raw)
214 {
215 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
216 uint32_t callId = sliceData.CallIds()[raw];
217 uint64_t startTime = sliceData.TimeStampData()[raw];
218 auto threadData = traceDataCache_->GetConstThreadData();
219 // callid is thread table->itid
220 auto nameindex = threadData[callId].nameIndex_;
221 auto ipid = threadData[callId].internalPid_;
222 auto tid = threadData[callId].tid_;
223 if (mAPPStartupDataWithPid_.count(ipid) && mAPPStartupDataWithPid_[ipid].count(nameindex) &&
224 !mAPPStartupDataWithPid_[ipid][nameindex].count(UI_ABILITY_ONFOREGROUND)) {
225 mAPPStartupDataWithPid_[ipid][nameindex].insert(std::make_pair(
226 UI_ABILITY_ONFOREGROUND, std::make_unique<APPStartupData>(callId, ipid, tid, startTime, INVALID_UINT64)));
227 }
228 }
229
CalcDepthByTimeStamp(std::map<uint32_t,std::map<uint64_t,uint32_t>>::iterator it,uint32_t & depth,uint64_t endTime,uint64_t startTime)230 void APPStartupFilter::CalcDepthByTimeStamp(std::map<uint32_t, std::map<uint64_t, uint32_t>>::iterator it,
231 uint32_t& depth,
232 uint64_t endTime,
233 uint64_t startTime)
234 {
235 if (!it->second.empty()) {
236 auto itor = it->second.begin();
237 if (itor->first > startTime) {
238 depth = it->second.size();
239 it->second.insert(std::make_pair(endTime, it->second.size()));
240 } else {
241 depth = itor->second;
242 for (auto itorSecond = itor; itorSecond != it->second.end(); ++itorSecond) {
243 if (itorSecond->first < startTime && depth > itorSecond->second) {
244 depth = itorSecond->second;
245 itor = itorSecond;
246 }
247 }
248 it->second.erase(itor);
249 it->second.insert(std::make_pair(endTime, depth));
250 }
251 } else {
252 it->second.insert(std::make_pair(endTime, 0));
253 }
254 }
255
ParserSoInitalization()256 void APPStartupFilter::ParserSoInitalization()
257 {
258 std::map<uint32_t, std::map<uint64_t, uint32_t>> mMaxTimeAndDepthWithPid;
259 auto sliceData = traceDataCache_->GetConstInternalSlicesData();
260 auto threadData = traceDataCache_->GetConstThreadData();
261 std::string nameString = "";
262 for (auto i = 0; i < sliceData.NamesData().size(); i++) {
263 nameString = traceDataCache_->GetDataFromDict(sliceData.NamesData()[i]);
264 if (nameString.find(dlopenCmd_) != std::string::npos) {
265 uint64_t startTime = sliceData.TimeStampData()[i];
266 uint64_t endTime = startTime + sliceData.DursData()[i];
267 uint32_t depth = 0;
268 auto callId = sliceData.CallIds()[i];
269 auto pid = threadData[callId].internalPid_;
270 auto tid = threadData[callId].tid_;
271 auto it = mMaxTimeAndDepthWithPid.find(pid);
272 if (it == mMaxTimeAndDepthWithPid.end()) {
273 mMaxTimeAndDepthWithPid.insert(std::make_pair(pid, std::map<uint64_t, uint32_t>{{endTime, 0}}));
274 traceDataCache_->GetSoStaticInitalizationData()->AppendNewData(pid, tid, callId, startTime, endTime,
275 sliceData.NamesData()[i], depth);
276 continue;
277 } else {
278 CalcDepthByTimeStamp(it, depth, endTime, startTime);
279 traceDataCache_->GetSoStaticInitalizationData()->AppendNewData(
280 threadData[callId].internalPid_, threadData[callId].tid_, callId, startTime, endTime,
281 sliceData.NamesData()[i], depth);
282 }
283 }
284 }
285 }
286 } // namespace TraceStreamer
287 } // namespace SysTuning
288