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 "sp_log.h"
25 #include "common.h"
26 #include "heartbeat.h"
27 #include "Dubai.h"
28 namespace OHOS {
29 namespace SmartPerf {
30 class SpThreadSocket {
31 public:
32     static bool flagRunning;
33     static std::string resultFPS;
MapToString(std::map<std::string, std::string> dataMap) const34     std::string MapToString(std::map<std::string, std::string> dataMap) const
35     {
36         std::string result;
37         int i = 0;
38         std::string splitStr = "";
39         for (auto iter = dataMap.cbegin(); iter != dataMap.cend(); ++iter) {
40             printf("%s = %s\n", iter->first.c_str(), iter->second.c_str());
41             if (i > 0) {
42                 splitStr = "$$";
43             }
44             result += splitStr + iter->first.c_str() + "||" + iter->second.c_str();
45             i++;
46         }
47         return result;
48     }
SplitMsg(const std::string &recvBuf) const49     std::string SplitMsg(const std::string &recvBuf) const
50     {
51         std::vector<std::string> sps;
52         SPUtils::StrSplit(recvBuf, "::", sps);
53         return sps[1];
54     }
55 
Process(ProtoType type) const56     void Process(ProtoType type) const
57     {
58         std::cout << "Socket Process called!" << std::endl;
59         LOGI("Socket Process called!");
60         SpServerSocket spSocket;
61         spSocket.Init(type);
62         if (type == ProtoType::TCP) {
63             std::cout << "Socket TCP Init called!" << std::endl;
64             LOGI("Socket TCP Init called!");
65             TypeTcp(spSocket);
66         }
67         if (type == ProtoType::UDP || type == ProtoType::UDPEX) {
68             LOGI("Socket UDP Init called! type(%d)", static_cast<int>(type));
69             SocketHeartbeat();
70             while (1) {
71                 spSocket.Recvfrom();
72                 HandleMsg(spSocket);
73             }
74         }
75         std::cout << "Socket Process finished!" << std::endl;
76         LOGI("Socket Process finished!");
77         spSocket.Close();
78     }
TypeTcp(SpServerSocket &spSocket) const79     void TypeTcp(SpServerSocket &spSocket) const
80     {
81         SocketHeartbeat();
82         while (1) {
83             int procFd = spSocket.Accept();
84             std::cout << "Socket TCP procFd: " << procFd << std::endl;
85             while (procFd > 0) {
86                 int reFd = spSocket.Recv();
87                 if (reFd < 0) {
88                     break;
89                 }
90                 std::string recvStr = spSocket.RecvBuf();
91                 std::cout << "Socket TCP Recv: " << recvStr << std::endl;
92                 // 解析消息 分发处理
93                 DealMsg(recvStr, spSocket);
94             }
95         }
96     }
97     // TCP
InitRecv(std::string recvStr, SpServerSocket &spSocket) const98     void InitRecv(std::string recvStr, SpServerSocket &spSocket) const
99     {
100         std::string errorInfo;
101         std::string checkStr = recvStr.substr(std::string("init::").length());
102         if (!SPTask::GetInstance().CheckTcpParam(checkStr, errorInfo)) {
103             LOGE("init error(%s) recvStr(%s)", errorInfo.c_str(), recvStr.c_str());
104             spSocket.Send("init::False,\"error\":" + errorInfo);
105             return;
106         }
107         ErrCode code = SPTask::GetInstance().InitTask(SplitMsg(recvStr));
108         LOGI("init::%s", (code == ErrCode::OK) ? "True" : "False");
109         spSocket.Send(std::string("init::") + ((code == ErrCode::OK) ? "True" : "False"));
110     }
StartRecv(SpServerSocket &spSocket) const111     void StartRecv(SpServerSocket &spSocket) const
112     {
113         if (flagRunning) {
114             LOGI("SP_daemon is running");
115             spSocket.Send("SP_daemon is running");
116             return;
117         }
118         auto lambdaTask = [](const std::string &data) {
119             std::cout << data << std::endl;
120         };
121         ErrCode code = SPTask::GetInstance().StartTask(lambdaTask);
122         SPTask::GetInstance().StartRecord();
123         LOGI("start:::%s", (code == ErrCode::OK) ? "True" : "False");
124         if (code == ErrCode::OK) {
125             spSocket.Send("start::True");
126             flagRunning = true;
127         } else if (code == ErrCode::FAILED) {
128             spSocket.Send("start::False");
129         }
130     }
StartRecvRealtime(SpServerSocket &spSocket) const131     void StartRecvRealtime(SpServerSocket &spSocket) const
132     {
133         auto lambdaTask = [&spSocket](const std::string &data) { spSocket.Send(data); };
134         ErrCode code = SPTask::GetInstance().StartTask(lambdaTask);
135         LOGI("start::%s", (code == ErrCode::OK) ? "True" : "False");
136         if (code == ErrCode::OK) {
137             spSocket.Send("start::True");
138         } else if (code == ErrCode::FAILED) {
139             spSocket.Send("start::False");
140         }
141     }
StopRecvRealtime(SpServerSocket &spSocket) const142     void StopRecvRealtime(SpServerSocket &spSocket) const
143     {
144         SPTask::GetInstance().StopTask();
145         LOGI("stop::True");
146         spSocket.Send("stop::True");
147         flagRunning = false;
148         spSocket.Close();
149     }
StartRecvRecord(SpServerSocket &spSocket) const150     void StartRecvRecord(SpServerSocket &spSocket) const
151     {
152         LOGI("startRecord::True");
153         SPTask::GetInstance().StartRecord();
154 
155         spSocket.Send("startRecord::True");
156     }
StopRecvRecord(SpServerSocket &spSocket) const157     void StopRecvRecord(SpServerSocket &spSocket) const
158     {
159         LOGI("stopRecord::True");
160         SPTask::GetInstance().StopRecord();
161 
162         spSocket.Send("stopRecord::True");
163     }
DealMsg(std::string recvStr, SpServerSocket &spSocket) const164     void DealMsg(std::string recvStr, SpServerSocket &spSocket) const
165     {
166         SocketHeartbeat();
167         if (recvStr.find("init::") != std::string::npos) {
168             InitRecv(recvStr, spSocket);
169         } else if (recvStr.find("start:::") != std::string::npos) {
170             StartRecv(spSocket);
171         } else if (recvStr.find("start::") != std::string::npos) {
172             StartRecvRealtime(spSocket);
173         } else if (recvStr.find("stop::") != std::string::npos) {
174             StopRecvRealtime(spSocket);
175         } else if (recvStr.find("startRecord::") != std::string::npos) {
176             StartRecvRecord(spSocket);
177         } else if (recvStr.find("stopRecord::") != std::string::npos) {
178             StopRecvRecord(spSocket);
179         } else if (recvStr.find("SP_daemon -editor") != std::string::npos) {
180             EditorRecv(recvStr, spSocket);
181         }
182     }
EditorRecv(std::string recvStr, const SpServerSocket &spSocket) const183     void EditorRecv(std::string recvStr, const SpServerSocket &spSocket) const
184     {
185         std::vector<std::string> vec;
186         size_t size = recvStr.size();
187         size_t j = 0;
188         for (size_t i = 0; i < size; i++) {
189             if (recvStr[i] == ' ') {
190                 vec.push_back(recvStr.substr(j, i - j));
191                 j = i + 1;
192             }
193         }
194         vec.push_back(recvStr.substr(j, size - j));
195         const int type = 2;
196         if (vec[type] == "findAppPage") {
197             BackDesktop();
198         }
199         OHOS::SmartPerf::ControlCallCmd controlCallCmd;
200         std::string result = controlCallCmd.GetResult(vec);
201         spSocket.Send(result);
202     }
203 
BackDesktop() const204     void BackDesktop() const
205     {
206         std::string cmdResult;
207         std::string uinput = CMD_COMMAND_MAP.at(CmdCommand::UINPUT_BACK);
208         SPUtils::LoadCmd(uinput, cmdResult);
209     }
210 
211     // UDP
HandleMsg(SpServerSocket &spSocket) const212     void HandleMsg(SpServerSocket &spSocket) const
213     {
214         std::string retCode = "";
215         auto iterator = MESSAGE_MAP.begin();
216         while (iterator != MESSAGE_MAP.end()) {
217             std::string recvBuf = spSocket.RecvBuf();
218             if (recvBuf.size() != 0) {
219                 Heartbeat &heartbeat = Heartbeat::GetInstance();
220                 heartbeat.UpdatestartTime();
221             }
222             if (!SPUtils::IsSubString(recvBuf, iterator->second)) {
223                 ++iterator;
224                 continue;
225             }
226             SpProfiler *profiler = SpProfilerFactory::GetProfilerItem(iterator->first);
227             if (profiler == nullptr) {
228                 HandleNullMsg(spSocket, profiler, retCode, recvBuf, iterator);
229             } else {
230                 std::map<std::string, std::string> data;
231                 if (iterator->first == MessageType::CATCH_NETWORK_TRAFFIC) {
232                     profiler->ItemData(); // record the collection point for the first time,no need to return
233                     data["network_traffic"] = "true";
234                 } else if (iterator->first == MessageType::GET_NETWORK_TRAFFIC) {
235                     data = profiler->ItemData();
236                     data["network_traffic"] = "true";
237                 } else {
238                     data = profiler->ItemData();
239                 }
240                 HandleUDPMsg(spSocket, data, retCode, iterator);
241             }
242             LOGI("sendData key(%d) content(%s)", iterator->first, retCode.c_str());
243             break;
244         }
245     }
HandleUDPMsg(SpServerSocket &spSocket, std::map<std::string, std::string> data, std::string retCode, std::unordered_map<MessageType, std::string>::const_iterator iterator) const246     void HandleUDPMsg(SpServerSocket &spSocket, std::map<std::string, std::string> data, std::string retCode,
247         std::unordered_map<MessageType, std::string>::const_iterator iterator) const
248     {
249         std::cout << "iterator->first: " << static_cast<int>(iterator->first) << std::endl;
250         if (iterator->first == MessageType::GET_LOW_POWER_FPS) {
251             for (auto iter = data.cbegin(); iter != data.cend(); ++iter) {
252                 if (iter->first != "fpsJitters") {
253                     std::string temp = iter->second + "@@";
254                     resultFPS += std::string(temp.c_str());
255                 }
256             }
257         } else if (iterator->first == MessageType::GET_CUR_FPS) {
258             std::string resultfps = "vfps||";
259             for (auto iter = data.cbegin(); iter != data.cend(); ++iter) {
260                 if (iter->first != "fpsJitters") {
261                     std::string temp = iter->second + "@@";
262                     resultFPS += std::string(temp.c_str());
263                     resultfps += std::string(temp.c_str());
264                 }
265             }
266             spSocket.Sendto(resultfps);
267         } else if (iterator->first == MessageType::GET_CPU_FREQ_LOAD) {
268             FetchCpuStats(spSocket, data);
269         } else {
270             retCode = MapToString(data);
271             spSocket.Sendto(retCode);
272         }
273     }
SocketHeartbeat() const274     void SocketHeartbeat() const
275     {
276         Heartbeat &heartbeat = Heartbeat::GetInstance();
277         heartbeat.UpdatestartTime();
278     }
FetchCpuStats(SpServerSocket &spSocket, std::map<std::string, std::string> data) const279     void FetchCpuStats(SpServerSocket &spSocket, std::map<std::string, std::string> data) const
280     {
281         std::string resultCpuFrequency = "";
282         std::string resultCpuUsage = "";
283         std::string resultCpu = "";
284         int cpuFrequencyNum = 0;
285         int cpuUsageNum = 0;
286         int cpuFlag = 1;
287         while (cpuFlag) {
288             resultCpuFrequency = "cpu" + std::to_string(cpuFrequencyNum) + "Frequency";
289             resultCpuUsage = "cpu" + std::to_string(cpuUsageNum) + "Usage";
290             auto iterCpuFrequency = data.find(resultCpuFrequency);
291             auto iterCpuUsage = data.find(resultCpuUsage);
292             if (iterCpuFrequency != data.end()) {
293                 resultCpuFrequency += "||" + iterCpuFrequency->second;
294                 resultCpu += "$$" + resultCpuFrequency;
295                 cpuFrequencyNum++;
296             } else {
297                 cpuFlag = 0;
298             }
299             if (iterCpuUsage != data.end()) {
300                 resultCpuUsage += "||" + iterCpuUsage->second;
301                 resultCpu += "$$" + resultCpuUsage;
302                 cpuUsageNum++;
303             } else {
304                 cpuFlag = 0;
305             }
306         }
307         spSocket.Sendto(resultCpu);
308     }
HandleNullMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string retCode, std::string recvBuf, std::unordered_map<MessageType, std::string>::const_iterator iterator) const309     void HandleNullMsg(SpServerSocket &spSocket, SpProfiler *profiler, std::string retCode, std::string recvBuf,
310         std::unordered_map<MessageType, std::string>::const_iterator iterator) const
311     {
312         if (iterator->first == MessageType::SET_PKG_NAME) {
313             retCode = SplitMsg(recvBuf);
314             if (retCode.find("smartperf") != std::string::npos) {
315                 OHOS::SmartPerf::Dubai::dubaiPkgName = retCode;
316             }
317             std::string processId = "";
318             OHOS::SmartPerf::StartUpDelay sp;
319             processId = sp.GetPidByPkg(retCode);
320             SpProfilerFactory::SetProfilerPidByPkg(processId);
321             SpProfilerFactory::SetProfilerPkg(retCode);
322             spSocket.Sendto(retCode);
323         } else if (iterator->first == MessageType::FPS_STOP) {
324             spSocket.Sendto(resultFPS);
325             resultFPS = "FPS||";
326         } else if (profiler == nullptr && (iterator->first == MessageType::SET_GAME_VIEW)) {
327             retCode = SplitMsg(recvBuf);
328             SpProfilerFactory::SetProfilerGameLayer(retCode);
329         } else if (iterator->first == MessageType::CATCH_TRACE_CONFIG ||
330             iterator->first == MessageType::CATCH_TRACE_CMD) {
331             SpProfilerFactory::SetByTrace(SplitMsg(recvBuf));
332         } else if (iterator->first == MessageType::GET_CPU_NUM) {
333             retCode = SPUtils::GetCpuNum();
334             spSocket.Sendto(retCode);
335         } else if (iterator->first == MessageType::BACK_TO_DESKTOP) {
336             BackDesktop();
337         } else {
338             retCode = iterator->second;
339             spSocket.Sendto(retCode);
340             LOGI("UDP sendData: (%s)", retCode.c_str());
341         }
342     }
343 };
344 bool SpThreadSocket::flagRunning = false;
345 std::string SpThreadSocket::resultFPS = "FPS||";
346 }
347 }
348 #endif