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