• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 <thread>
17 #include <chrono>
18 #include <fstream>
19 #include <sstream>
20 #include <vector>
21 #include "list_swipe_fps_collection.h"
22 
23 namespace OHOS::perftest {
24     using namespace std;
25     const string TRACE_FILE_NAME = "/data/local/tmp/perftest_fps.ftrace";
26     const string HITRACE_START_COMMAND = "hitrace -b 204800 --overwrite --trace_begin graphic nweb ace";
27     const string HITRACE_FINISH_COMMAND = "hitrace --trace_finish -o " + TRACE_FILE_NAME;
28     const string REMOVE_TRACE_FILE = "rm -f " + TRACE_FILE_NAME;
29     const string SWIPE_START_STATE = "SWIPE_START";
30     const string SWIPE_FINISH_STATE = "SWIPE_FINISH";
31     const string SWIPE_INVALID_STATE = "SWIPE_INVALID";
32     const string DO_COMPOSITION_TAG = "H:RSMainThread::DoComposition";
33     const string APP_LIST_FLING_TAG = "H:APP_LIST_FLING";
34     const string WEB_LIST_FLING_TAG = "H:WEB_LIST_FLING";
35     const string APP_SWIPER_SCROLL_TAG = "H:APP_SWIPER_SCROLL";
36     const string APP_SWIPER_FLING_TAG = "H:APP_SWIPER_FLING";
37 
StartCollection(ApiCallErr & error)38     void ListSwipeFpsCollection::StartCollection(ApiCallErr &error)
39     {
40         string executeRes;
41         ExecuteCommand(HITRACE_FINISH_COMMAND, executeRes);
42         ExecuteCommand(REMOVE_TRACE_FILE, executeRes);
43         if (!ExecuteCommand(HITRACE_START_COMMAND, executeRes)) {
44             error = ApiCallErr(ERR_DATA_COLLECTION_FAILED, "Start list swipe fps measure failed");
45             return;
46         }
47         if (executeRes.find("OpenRecording done.") == string::npos) {
48             error = ApiCallErr(ERR_DATA_COLLECTION_FAILED, "Start list swipe fps measure failed");
49         }
50     }
51 
StopCollectionAndGetResult(ApiCallErr & error)52     double ListSwipeFpsCollection::StopCollectionAndGetResult(ApiCallErr &error)
53     {
54         string executeRes;
55         if (!ExecuteCommand(HITRACE_FINISH_COMMAND, executeRes)) {
56             error = ApiCallErr(ERR_DATA_COLLECTION_FAILED, "Stop list swipe fps measure failed");
57             return INVALID_VALUE;
58         }
59         if (executeRes.find("Trace Closed.") == string::npos) {
60             error = ApiCallErr(ERR_DATA_COLLECTION_FAILED, "Stop list swipe fps measure failed");
61             return INVALID_VALUE;
62         }
63         pid_ = GetPidByBundleName(bundleName_);
64         if (pid_ == -1) {
65             error = ApiCallErr(ERR_DATA_COLLECTION_FAILED, "The process does not exist when fps trace parse");
66             return INVALID_VALUE;
67         }
68         return ParseFpsByTrace(error);
69     }
70 
ParseFpsByTrace(ApiCallErr & error)71     double ListSwipeFpsCollection::ParseFpsByTrace(ApiCallErr &error)
72     {
73         ifstream file(TRACE_FILE_NAME);
74         if (!file.is_open()) {
75             error = ApiCallErr(ERR_DATA_COLLECTION_FAILED, "Get list swipe trace failed");
76             return INVALID_VALUE;
77         }
78         double startTime = INITIAL_VALUE;
79         double endTime = INITIAL_VALUE;
80         int32_t frameCount = ZERO;
81         string line;
82         while (getline(file, line)) {
83             const vector<string> tokens = SplitString(line, ' ');
84             int32_t stateIndex = 0;
85             if (line.find(APP_LIST_FLING_TAG) != string::npos) {
86                 if (GetSwipeState(tokens, APP_LIST_FLING_TAG, stateIndex) == SWIPE_START_STATE) {
87                     LOG_D("App list fling start");
88                     startTime = GetTime(tokens, stateIndex - TWO);
89                 } else if (GetSwipeState(tokens, APP_LIST_FLING_TAG, stateIndex) == SWIPE_FINISH_STATE) {
90                     LOG_D("App list fling finish");
91                     endTime = GetTime(tokens, stateIndex - TWO);
92                 }
93             } else if (line.find(WEB_LIST_FLING_TAG) != string::npos) {
94                 if (GetSwipeState(tokens, WEB_LIST_FLING_TAG, stateIndex) == SWIPE_START_STATE) {
95                     LOG_D("Web list fling start");
96                     startTime = GetTime(tokens, stateIndex - TWO);
97                 } else if (GetSwipeState(tokens, WEB_LIST_FLING_TAG, stateIndex) == SWIPE_FINISH_STATE) {
98                     LOG_D("Web list fling finish");
99                     endTime = GetTime(tokens, stateIndex - TWO);
100                 }
101             } else if (line.find(APP_SWIPER_SCROLL_TAG) != string::npos &&
102                        GetSwipeState(tokens, APP_SWIPER_SCROLL_TAG, stateIndex) == SWIPE_START_STATE) {
103                 LOG_D("Swiper scroll start");
104                 startTime = GetTime(tokens, stateIndex - TWO);
105             } else if (line.find(APP_SWIPER_FLING_TAG) != string::npos && startTime > INITIAL_VALUE &&
106                        GetSwipeState(tokens, APP_SWIPER_FLING_TAG, stateIndex) == SWIPE_FINISH_STATE) {
107                 LOG_D("Swiper scroll finish");
108                 endTime = GetTime(tokens, stateIndex - TWO);
109             } else if (line.find(DO_COMPOSITION_TAG) != string::npos && startTime > INITIAL_VALUE) {
110                 frameCount++;
111             }
112             if (startTime > INITIAL_VALUE && endTime > INITIAL_VALUE && frameCount != ZERO) {
113                 file.close();
114                 return frameCount / (endTime - startTime);
115             }
116         }
117         file.close();
118         return INVALID_VALUE;
119     }
120 
GetSwipeState(const vector<string> & tokens,const string traceTag,int32_t & stateIndex)121     string ListSwipeFpsCollection::GetSwipeState(const vector<string> &tokens, const string traceTag,
122                                                  int32_t &stateIndex)
123     {
124         string token = "";
125         for (int32_t index = ZERO; index < tokens.size(); index++) {
126             if (tokens[index].find(traceTag) != string::npos) {
127                 token = tokens[index];
128                 stateIndex = index;
129                 break;
130             }
131         }
132         vector<string> tagInfos = SplitString(token, '|');
133         if (tagInfos.size() > TWO && tagInfos[INDEX_TWO] == traceTag && tagInfos[INDEX_ONE] == to_string(pid_)) {
134             switch (tagInfos[INDEX_ZERO][INDEX_ZERO]) {
135                 case 'S':
136                     return SWIPE_START_STATE;
137                 case 'F':
138                     return SWIPE_FINISH_STATE;
139                 default:
140                     return SWIPE_INVALID_STATE;
141             }
142         }
143         return SWIPE_INVALID_STATE;
144     }
145 
GetTime(const vector<string> & tokens,const int32_t timeIndex)146     double ListSwipeFpsCollection::GetTime(const vector<string> &tokens, const int32_t timeIndex)
147     {
148         double time = INITIAL_VALUE;
149         if (timeIndex < 0) {
150             return time;
151         }
152         string token = tokens[timeIndex];
153         if (token.size() == 0) {
154             return time;
155         }
156         string timeStr = token.substr(0, token.size() - 1);
157         istringstream iss(timeStr);
158         if ((iss >> time) && iss.eof()) {
159             return time;
160         }
161         return time;
162     }
163 
SplitString(const string line,const char delimiter)164     vector<string> ListSwipeFpsCollection::SplitString(const string line, const char delimiter)
165     {
166         stringstream ss(line);
167         vector<std::string> tokens;
168         string token;
169         while (getline(ss, token, delimiter)) {
170             if (!token.empty()) {
171                 tokens.push_back(token);
172             }
173         }
174         return tokens;
175     }
176 }