• 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 
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 (StartWith(nameString, procTouchCmd_)) {
179             procTouchItems_.emplace_back(
180                 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
181         } else if (StartWith(nameString, startUIAbilityBySCBCmd_)) {
182             startUIAbilityBySCBItems_.emplace_back(
183                 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
184         } else if (StartWith(nameString, loadAbilityCmd_)) {
185             loadAbilityItems_.emplace_back(
186                 std::make_unique<APPStartupData>(callId, INVALID_UINT32, INVALID_UINT32, startTime, INVALID_UINT64));
187         } else if (StartWith(nameString, appLaunchCmd_)) {
188             UpdateAPPStartupData(i, nameString, APPLICATION_LAUNCHING);
189         } else if (StartWith(nameString, uiLaunchCmd_)) {
190             ProcAbilityLaunchData(nameString, i);
191         } else if (StartWith(nameString, uiOnForegroundFirstCmd_) || StartWith(nameString, uiOnForegroundSecCmd_)) {
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