• 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 #ifndef SP_THREAD_SOCKET_H
16 #define SP_THREAD_SOCKET_H
17 #include <functional>
18 #include "sp_profiler_factory.h"
19 #include "sp_server_socket.h"
20 #include "sp_utils.h"
21 #include "sp_task.h"
22 #include "control_call_cmd.h"
23 #include "startup_delay.h"
24 #include "profiler_fps.h"
25 #include "sp_log.h"
26 #include "common.h"
27 #include "heartbeat.h"
28 #include "Dubai.h"
29 #include "Network.h"
30 namespace OHOS {
31 namespace SmartPerf {
32 class SpThreadSocket {
33 public:
34     static bool flagRunning;
35     enum SocketConnectType {
36         CMD_SOCKET,
37         EDITOR_SOCKET,
38     };
39 
40     enum SocketErrorType {
41         OK,
42         TOKEN_CHECK_FAILED,
43         INIT_FAILED,
44         START_FAILED,
45         STOP_FAILED,
46         START_RECORD_FAILED,
47         STOP_RECORD_FAILED,
48     };
MapToString(std::map<std::string,std::string> dataMap)49     std::string MapToString(std::map<std::string, std::string> dataMap) const
50     {
51         std::string result;
52         int i = 0;
53         std::string splitStr = "";
54         for (auto iter = dataMap.cbegin(); iter != dataMap.cend(); ++iter) {
55             printf("%s = %s\n", iter->first.c_str(), iter->second.c_str());
56             if (i > 0) {
57                 splitStr = "$$";
58             }
59             result += splitStr + iter->first.c_str() + "||" + iter->second.c_str();
60             i++;
61         }
62         return result;
63     }
SplitMsg(const std::string & recvBuf)64     std::string SplitMsg(const std::string &recvBuf) const
65     {
66         if (recvBuf.empty()) {
67             LOGE("SplitMsg recvBuf is null");
68             return recvBuf;
69         }
70         size_t pos = recvBuf.find("::");
71         if (pos != std::string::npos) {
72             std::vector<std::string> sps;
73             SPUtils::StrSplit(recvBuf, "::", sps);
74             if (sps.size() > 1) {
75                 return sps[1];
76             } else {
77                 LOGE("SplitMsg sps size is zreo");
78                 return recvBuf;
79             }
80         } else {
81             return recvBuf;
82         }
83     }
84 
Process(ProtoType type)85     void Process(ProtoType type) const
86     {
87         std::cout << "Socket Process called!" << std::endl;
88         SpServerSocket spSocket;
89         spSocket.Init(type);
90         if (type == ProtoType::TCP) {
91             std::cout << "Socket TCP Init called!" << std::endl;
92             TypeTcp(spSocket);
93         }
94         if (type == ProtoType::UDP || type == ProtoType::UDPEX) {
95             SocketHeartbeat();
96             while (1) {
97                 spSocket.Recvfrom();
98                 HandleMsg(spSocket);
99             }
100         }
101         std::cout << "Socket Process finished!" << std::endl;
102         spSocket.Close();
103     }
CheckToken(std::string recvStr,SpServerSocket & spSocket)104     SocketErrorType CheckToken(std::string recvStr, SpServerSocket &spSocket) const
105     {
106         if (recvStr.find_last_of(":") == std::string::npos) {
107             if (recvStr.find("SP_daemon -editor") != std::string::npos) {
108                 return OK;
109             } else {
110                 return TOKEN_CHECK_FAILED;
111             }
112         }
113         std::string token = recvStr.substr(recvStr.find_last_of(":") + 1);
114         token = token.substr(0, token.find(' '));
115         std::string tcpToken = SPTask::GetInstance().GetTcpToken();
116         if (tcpToken == "" && token == "-SESSIONID") {
117             return OK;
118         }
119         if (token != tcpToken) {
120             return TOKEN_CHECK_FAILED;
121         }
122 
123         return OK;
124     }
125 
TypeTcp(SpServerSocket & spSocket)126     void TypeTcp(SpServerSocket &spSocket) const
127     {
128         SocketHeartbeat();
129         while (1) {
130             int procFd = spSocket.Accept();
131             std::cout << "Socket TCP procFd: " << procFd << std::endl;
132             while (procFd > 0) {
133                 int reFd = spSocket.Recv();
134                 if (reFd < 0) {
135                     break;
136                 }
137                 std::string recvStr = spSocket.RecvBuf();
138                 LOGD("TCP recv : %s", recvStr.c_str());
139                 // 解析消息 分发处理
140                 const SocketErrorType tokenStatus = CheckToken(recvStr, spSocket);
141                 DealMsg(recvStr, spSocket, tokenStatus);
142             }
143         }
144     }
145     // TCP
InitRecv(std::string recvStr,SpServerSocket & spSocket,SocketConnectType type)146     void InitRecv(std::string recvStr, SpServerSocket &spSocket, SocketConnectType type) const
147     {
148         std::string errorInfo;
149         std::string checkStr = recvStr.substr(std::string("init::").length());
150         if (!SPTask::GetInstance().CheckTcpParam(checkStr, errorInfo) &&
151             checkStr.find(SPTask::GetInstance().GetTcpToken()) == std::string::npos) {
152             LOGE("init error(%s) recvStr(%s)", errorInfo.c_str(), recvStr.c_str());
153             if (type == CMD_SOCKET) {
154                 spSocket.Send("init::False,\"error\":" + errorInfo);
155             } else {
156                 spSocket.Send(std::string("init::") + std::to_string(INIT_FAILED));
157             }
158             return;
159         }
160         if (recvStr.find("-lockfreq") != std::string::npos &&
161             SPTask::GetInstance().GetTcpToken() == "") {
162             LOGE("lockfreq must have token");
163             return;
164         }
165         ErrCode code = SPTask::GetInstance().InitTask(SplitMsg(recvStr));
166         LOGD("init::%s", (code == ErrCode::OK) ? "True" : "False");
167         if (type == CMD_SOCKET) {
168             spSocket.Send(std::string("init::") + ((code == ErrCode::OK) ? "True" : "False"));
169             return;
170         }
171         if (code == ErrCode::OK) {
172             spSocket.Send("init::True");
173         } else {
174             spSocket.Send(std::string("init::") + std::to_string(INIT_FAILED));
175         }
176     }
StartRecv(SpServerSocket & spSocket)177     void StartRecv(SpServerSocket &spSocket) const
178     {
179         if (flagRunning) {
180             spSocket.Send("SP_daemon is running");
181             return;
182         }
183         auto lambdaTask = [](const std::string &data) {
184             std::cout << data << std::endl;
185         };
186         ErrCode code = SPTask::GetInstance().StartTask(lambdaTask);
187         SPTask::GetInstance().StartRecord();
188         LOGD("start:::%s", (code == ErrCode::OK) ? "True" : "False");
189         if (code == ErrCode::OK) {
190             spSocket.Send("start::True");
191             flagRunning = true;
192         } else if (code == ErrCode::FAILED) {
193             spSocket.Send("start::False");
194         }
195     }
StartRecvRealtime(SpServerSocket & spSocket)196     void StartRecvRealtime(SpServerSocket &spSocket) const
197     {
198         auto lambdaTask = [&spSocket](const std::string &data) { spSocket.Send(data); };
199         ErrCode code = SPTask::GetInstance().StartTask(lambdaTask);
200         LOGD("start::%s", (code == ErrCode::OK) ? "True" : "False");
201         if (code == ErrCode::OK) {
202             spSocket.Send("start::True");
203         } else if (code == ErrCode::FAILED) {
204             spSocket.Send(std::string("start::") + std::to_string(START_FAILED));
205         }
206     }
StopRecvRealtime(SpServerSocket & spSocket)207     void StopRecvRealtime(SpServerSocket &spSocket) const
208     {
209         ErrCode code = SPTask::GetInstance().StopTask();
210         if (code == ErrCode::OK) {
211             spSocket.Send("stop::True");
212             flagRunning = false;
213             spSocket.Close();
214         } else if (code == ErrCode::FAILED) {
215             spSocket.Send(std::string("stop::") + std::to_string(STOP_FAILED));
216         }
217     }
StartRecvRecord(SpServerSocket & spSocket)218     void StartRecvRecord(SpServerSocket &spSocket) const
219     {
220         LOGD("startRecord::True");
221         ErrCode code = SPTask::GetInstance().StartRecord();
222         if (code == ErrCode::OK) {
223             spSocket.Send("startRecord::True");
224         } else {
225             spSocket.Send(std::string("startRecord::") + std::to_string(START_RECORD_FAILED));
226         }
227         spSocket.Send("startRecord::True");
228     }
StopRecvRecord(SpServerSocket & spSocket)229     void StopRecvRecord(SpServerSocket &spSocket) const
230     {
231         ErrCode code = SPTask::GetInstance().StopRecord();
232         if (code == ErrCode::OK) {
233             spSocket.Send("stopRecord::True");
234         } else {
235             spSocket.Send(std::string("stopRecord::") + std::to_string(STOP_RECORD_FAILED));
236         }
237     }
SendTokenFailedMessage(SpServerSocket & socket,std::string & message)238     void SendTokenFailedMessage(SpServerSocket &socket, std::string &message) const
239     {
240         if (message.find("init:::") != std::string::npos ||
241             message.find("start:::") != std::string::npos) {
242             return;
243         }
244         const std::vector<std::string> messageType = {
245             "init::",
246             "start::",
247             "stop::",
248             "startRecord::",
249             "stopRecord::",
250         };
251         for (auto it : messageType) {
252             if (message.find(it) != std::string::npos) {
253                 LOGD((it + std::to_string(TOKEN_CHECK_FAILED)).c_str());
254                 socket.Send(it + std::to_string(TOKEN_CHECK_FAILED));
255                 return;
256             }
257         }
258     }
DealMsg(std::string recvStr,SpServerSocket & spSocket,SocketErrorType tokenStatus)259     void DealMsg(std::string recvStr, SpServerSocket &spSocket, SocketErrorType tokenStatus) const
260     {
261         SocketHeartbeat();
262         if (tokenStatus == TOKEN_CHECK_FAILED) {
263             SendTokenFailedMessage(spSocket, recvStr);
264             return;
265         }
266         if (recvStr.find("init:::") != std::string::npos) {
267             InitRecv(recvStr, spSocket, CMD_SOCKET);
268         } else if (recvStr.find("start:::") != std::string::npos) {
269             StartRecv(spSocket);
270         } else if (recvStr.find("init::") != std::string::npos) {
271             InitRecv(recvStr, spSocket, EDITOR_SOCKET);
272         } else if (recvStr.find("start::") != std::string::npos) {
273             StartRecvRealtime(spSocket);
274         } else if (recvStr.find("stop::") != std::string::npos) {
275             StopRecvRealtime(spSocket);
276         } else if (recvStr.find("startRecord::") != std::string::npos) {
277             StartRecvRecord(spSocket);
278         } else if (recvStr.find("stopRecord::") != std::string::npos) {
279             StopRecvRecord(spSocket);
280         } else if (recvStr.find("SP_daemon -editor") != std::string::npos) {
281             EditorRecv(recvStr, spSocket);
282         }
283     }
EditorRecv(std::string recvStr,const SpServerSocket & spSocket)284     void EditorRecv(std::string recvStr, const SpServerSocket &spSocket) const
285     {
286         std::vector<std::string> vec;
287         size_t size = recvStr.size();
288         size_t j = 0;
289         for (size_t i = 0; i < size; i++) {
290             if (recvStr[i] == ' ') {
291                 vec.push_back(recvStr.substr(j, i - j));
292                 j = i + 1;
293             }
294         }
295         vec.push_back(recvStr.substr(j, size - j));
296         const int type = 2;
297         if (vec[type] == "findAppPage") {
298             BackDesktop();
299         }
300         OHOS::SmartPerf::ControlCallCmd controlCallCmd;
301         std::string result = controlCallCmd.GetResult(vec);
302         spSocket.Send(result);
303     }
304 
BackDesktop()305     void BackDesktop() const
306     {
307         std::string cmdResult;
308         std::string uinput = CMD_COMMAND_MAP.at(CmdCommand::UINPUT_BACK);
309         SPUtils::LoadCmd(uinput, cmdResult);
310     }
311 
312     // UDP
HandleMsg(SpServerSocket & spSocket)313     void HandleMsg(SpServerSocket &spSocket) const
314     {
315         std::string retCode = "";
316         auto iterator = MESSAGE_MAP.begin();
317         while (iterator != MESSAGE_MAP.end()) {
318             std::string recvBuf = spSocket.RecvBuf();
319             if (recvBuf.size() != 0) {
320                 Heartbeat &heartbeat = Heartbeat::GetInstance();
321                 heartbeat.UpdatestartTime();
322             }
323             if (!SPUtils::IsSubString(recvBuf, iterator->second)) {
324                 ++iterator;
325                 continue;
326             }
327             LOGD("UDP recv : %s", recvBuf.c_str());
328             SpProfiler *profiler = SpProfilerFactory::GetProfilerItem(iterator->first);
329             if (profiler == nullptr) {
330                 HandleNullMsg(spSocket, profiler, retCode, recvBuf, iterator);
331             } else {
332                 std::map<std::string, std::string> data;
333                 if (iterator->first == MessageType::CATCH_NETWORK_TRAFFIC) {
334                     Network::GetInstance().IsFindHap();
335                     profiler->ItemData(); // record the collection point for the first time,no need to return
336                     data["network_traffic"] = "true";
337                 } else if (iterator->first == MessageType::GET_NETWORK_TRAFFIC) {
338                     Network::GetInstance().IsStopFindHap();
339                     data = profiler->ItemData();
340                     data["network_traffic"] = "true";
341                 } else {
342                     data = profiler->ItemData();
343                 }
344                 HandleUDPMsg(spSocket, data, retCode, iterator);
345             }
346             LOGD("sendData key(%d) content(%s)", iterator->first, retCode.c_str());
347             break;
348         }
349     }
HandleUDPMsg(SpServerSocket & spSocket,std::map<std::string,std::string> data,std::string retCode,std::unordered_map<MessageType,std::string>::const_iterator iterator)350     void HandleUDPMsg(SpServerSocket &spSocket, std::map<std::string, std::string> data, std::string retCode,
351         std::unordered_map<MessageType, std::string>::const_iterator iterator) const
352     {
353         std::cout << "iterator->first: " << static_cast<int>(iterator->first) << std::endl;
354         if (iterator->first == MessageType::GET_CUR_FPS) {
355             ProfilerFPS::isLowCurFps = true;
356             std::string resultfps = "vfps||";
357             for (auto iter = data.cbegin(); iter != data.cend(); ++iter) {
358                 if (iter->first != "fpsJitters") {
359                     std::string temp = iter->second + "@@";
360                     resultfps += std::string(temp.c_str());
361                 }
362             }
363             spSocket.Sendto(resultfps);
364             LOGD("UDP send Cur_resultfps = %s", resultfps.c_str());
365         } else if (iterator->first == MessageType::GET_CPU_FREQ_LOAD) {
366             FetchCpuStats(spSocket, data);
367         } else {
368             retCode = MapToString(data);
369             spSocket.Sendto(retCode);
370             LOGD("UDP send retCode = %s", retCode.c_str());
371         }
372     }
SocketHeartbeat()373     void SocketHeartbeat() const
374     {
375         Heartbeat &heartbeat = Heartbeat::GetInstance();
376         heartbeat.UpdatestartTime();
377     }
FetchCpuStats(SpServerSocket & spSocket,std::map<std::string,std::string> data)378     void FetchCpuStats(SpServerSocket &spSocket, std::map<std::string, std::string> data) const
379     {
380         std::string resultCpuFrequency = "";
381         std::string resultCpuUsage = "";
382         std::string resultCpu = "";
383         int cpuFrequencyNum = 0;
384         int cpuUsageNum = 0;
385         int cpuFlag = 1;
386         while (cpuFlag) {
387             resultCpuFrequency = "cpu" + std::to_string(cpuFrequencyNum) + "Frequency";
388             resultCpuUsage = "cpu" + std::to_string(cpuUsageNum) + "Usage";
389             auto iterCpuFrequency = data.find(resultCpuFrequency);
390             auto iterCpuUsage = data.find(resultCpuUsage);
391             if (iterCpuFrequency != data.end()) {
392                 resultCpuFrequency += "||" + iterCpuFrequency->second;
393                 resultCpu += "$$" + resultCpuFrequency;
394                 cpuFrequencyNum++;
395             } else {
396                 cpuFlag = 0;
397             }
398             if (iterCpuUsage != data.end()) {
399                 resultCpuUsage += "||" + iterCpuUsage->second;
400                 resultCpu += "$$" + resultCpuUsage;
401                 cpuUsageNum++;
402             } else {
403                 cpuFlag = 0;
404             }
405         }
406         spSocket.Sendto(resultCpu);
407         LOGD("UDP send resultCpu = %s", resultCpu.c_str());
408     }
HandleNullMsg(SpServerSocket & spSocket,SpProfiler * profiler,std::string retCode,std::string recvBuf,std::unordered_map<MessageType,std::string>::const_iterator iterator)409     void HandleNullMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string retCode, std::string recvBuf,
410         std::unordered_map<MessageType, std::string>::const_iterator iterator) const
411     {
412         if (iterator->first == MessageType::SET_PKG_NAME) {
413             if (recvBuf.find("smartperf") != std::string::npos) {
414                 retCode = SplitMsg(recvBuf);
415                 if (retCode.find("smartperf") != std::string::npos) {
416                     Dubai::dubaiPkgName = retCode;
417                     LOGD("UDP send dubaiPkgName: (%s)", Dubai::dubaiPkgName.c_str());
418                 }
419             } else {
420                 retCode = SplitMsg(recvBuf);
421                 if (!SpProfilerFactory::editorFlag) {
422                     std::string processId = "";
423                     OHOS::SmartPerf::StartUpDelay sp;
424                     processId = sp.GetPidByPkg(retCode);
425                     SpProfilerFactory::SetProfilerPidByPkg(processId);
426                     SpProfilerFactory::SetProfilerPkg(retCode);
427                 }
428             }
429             spSocket.Sendto(retCode);
430             LOGD("UDP send PkgName = %s", retCode.c_str());
431         } else if (profiler == nullptr && (iterator->first == MessageType::GET_APP_TYPE)) {
432             retCode = SplitMsg(recvBuf);
433             ProfilerFPS &pfps = ProfilerFPS::GetInstance();
434             pfps.isGameApp = SPUtils::GetIsGameApp(retCode);
435             pfps.firstDump = true;
436         } else if (profiler == nullptr && (iterator->first == MessageType::SET_GAME_VIEW)) {
437             retCode = SplitMsg(recvBuf);
438             SpProfilerFactory::SetProfilerGameLayer(retCode);
439         } else if (iterator->first == MessageType::CATCH_TRACE_CONFIG ||
440             iterator->first == MessageType::CATCH_TRACE_CMD) {
441             SpProfilerFactory::SetByTrace(SplitMsg(recvBuf));
442         } else if (iterator->first == MessageType::GET_CPU_NUM) {
443             retCode = SPUtils::GetCpuNum();
444             spSocket.Sendto(retCode);
445             LOGD("UDP send cpuNum = %s", retCode.c_str());
446         } else if (iterator->first == MessageType::BACK_TO_DESKTOP) {
447             BackDesktop();
448         } else {
449             HandleNullAddMsg(spSocket, profiler, retCode, recvBuf, iterator);
450         }
451     }
HandleNullAddMsg(SpServerSocket & spSocket,SpProfiler * profiler,std::string retCode,std::string recvBuf,std::unordered_map<MessageType,std::string>::const_iterator iterator)452     void HandleNullAddMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string retCode, std::string recvBuf,
453         std::unordered_map<MessageType, std::string>::const_iterator iterator) const
454     {
455         if (iterator->first == MessageType::START_DUBAI_DB) {
456             if (recvBuf.find("smartperf") != std::string::npos) {
457                 retCode = SplitMsg(recvBuf);
458                 if (retCode.find("smartperf") != std::string::npos) {
459                     Dubai::dubaiPkgName = retCode;
460                     LOGD("UDP send dubaiPkgName: (%s)", Dubai::dubaiPkgName.c_str());
461                 }
462             }
463             Dubai::CallBeginAndFinish();
464         } else if (iterator->first == MessageType::SET_DUBAI_DB) {
465             Dubai::CallBeginAndFinish();
466             Dubai::isDumpDubaiFinish = true;
467             ProfilerFPS::isLowCurFps = false;
468             retCode = Dubai::CallMoveDubaiDbFinished();
469             spSocket.Sendto(retCode);
470             LOGD("UDP send DuBai get finish");
471         } else if (iterator->first == MessageType::CHECK_UDP_STATUS) {
472             retCode = "UDP status is normal";
473             spSocket.Sendto(retCode);
474             LOGD("UDP status is normal");
475         } else {
476             retCode = iterator->second;
477             spSocket.Sendto(retCode);
478             LOGD("UDP sendData: (%s)", retCode.c_str());
479         }
480     }
481 };
482 bool SpThreadSocket::flagRunning = false;
483 }
484 }
485 #endif