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#include <cstdio>
16#include <thread>
17#include <cstring>
18#include <iterator>
19#include "unistd.h"
20#include "include/heartbeat.h"
21#include "include/sp_utils.h"
22#include "include/sp_csv_util.h"
23#include "include/sp_profiler_factory.h"
24#include "include/sp_thread_socket.h"
25#include "include/startup_delay.h"
26#include "include/ByTrace.h"
27#include "include/smartperf_command.h"
28#include "include/sp_log.h"
29#include "include/RAM.h"
30#include "include/common.h"
31
32namespace OHOS {
33namespace SmartPerf {
34SmartPerfCommand::SmartPerfCommand(std::vector<std::string> argv)
35{
36    LOGI("SmartPerfCommand::SmartPerfCommand size(%u)", argv.size());
37    if (argv.size() == oneParam) {
38        OHOS::SmartPerf::StartUpDelay sd;
39        sd.GetSpTcp();
40        std::string pidStr = sd.GetPidByPkg("SP_daemon");
41        std::string cmdStr = CMD_COMMAND_MAP.at(CmdCommand::TASKSET);
42        std::string result = "";
43        SPUtils::LoadCmd(cmdStr + pidStr, result);
44        daemon(0, 0);
45        CreateSocketThread();
46    }
47    if (argv.size() == twoParam) {
48        auto iterator = COMMAND_HELP_MAP.begin();
49        while (iterator != COMMAND_HELP_MAP.end()) {
50            if (iterator->second.compare(argv[1]) == 0) {
51                HelpCommand(iterator->first);
52                break;
53            }
54            ++iterator;
55        }
56    }
57    if (argv.size() >= threeParamMore) {
58        for (int i = 1; i <= static_cast<int>(argv.size()) - 1; i++) {
59            std::string argStr = argv[i];
60            std::string argStr1;
61            if (i < static_cast<int>(argv.size()) - 1) {
62                argStr1 = argv[i + 1];
63            }
64            if (COMMAND_MAP.count(argStr) > 0) {
65                HandleCommand(argStr, argStr1);
66            }
67        }
68    }
69
70    LOGI("SmartPerfCommand::SmartPerfCommand  complete");
71}
72void SmartPerfCommand::HelpCommand(CommandHelp type) const
73{
74    LOGI("SmartPerfCommand::HelpCommand  type(%d)", type);
75    if (type == CommandHelp::HELP) {
76        std::cout << smartPerfMsg << std::endl;
77    }
78    if (type == CommandHelp::VERSION) {
79        std::cout << "Version: " << smartPerfVersion << std::endl;
80    }
81    if (type == CommandHelp::SCREEN) {
82        std::string result = SPUtils::GetScreen();
83        std::cout << result << std::endl;
84    }
85    OHOS::SmartPerf::StartUpDelay sd;
86    if (type == CommandHelp::CLEAR) {
87        sd.GetSpClear();
88    }
89    if (type == CommandHelp::SERVER || type == CommandHelp::EDITORSERVER) {
90        sd.ClearOldServer();
91        std::string pidStr = sd.GetPidByPkg("SP_daemon");
92        std::string cmdStr = CMD_COMMAND_MAP.at(CmdCommand::TASKSET);
93        std::string result = "";
94        SPUtils::LoadCmd(cmdStr + pidStr, result);
95        if (type == CommandHelp::SERVER) {
96            daemon(0, 0);
97        }
98        CreateSocketThread();
99    }
100}
101
102void SmartPerfCommand::CreateSocketThread() const
103{
104    InitSomething();
105    SpThreadSocket udpThreadSocket;
106    SpThreadSocket udpExThreadSocket;
107    SpThreadSocket tcpThreadSocket;
108    auto tcpSocket = std::thread([&tcpThreadSocket]() { tcpThreadSocket.Process(ProtoType::TCP); });
109    sleep(1);
110    auto udpSocket = std::thread([&udpThreadSocket]() { udpThreadSocket.Process(ProtoType::UDP); });
111    sleep(1);
112    auto udpexSocket = std::thread([&udpExThreadSocket]() { udpExThreadSocket.Process(ProtoType::UDPEX); });
113    Heartbeat &heartbeat = Heartbeat::GetInstance();
114    heartbeat.UpdatestartTime();
115    std::thread threadHeartbeat([&heartbeat]() {heartbeat.HeartbeatRule(); });
116    threadHeartbeat.detach();
117    tcpSocket.join();
118    udpSocket.join();
119    udpexSocket.join();
120}
121void SmartPerfCommand::HandleCommand(std::string argStr, const std::string &argStr1)
122{
123    LOGI("SmartPerfCommand::HandleCommand  argStr(%s) argStr1(%s)", argStr.c_str(), argStr1.c_str());
124    switch (COMMAND_MAP.at(argStr)) {
125        case CommandType::CT_N:
126            num = atoi(argStr1.c_str());
127            break;
128        case CommandType::CT_PKG:
129            pkgName = argStr1;
130            if (pkgName.length() > 0) {
131                SpProfilerFactory::SetProfilerPkg(pkgName);
132            }
133            break;
134        case CommandType::CT_VIEW:
135            layerName = argStr1;
136            if (layerName.length() > 0) {
137                SpProfilerFactory::SetProfilerLayer(layerName);
138            }
139            break;
140        case CommandType::CT_OUT:
141            outPathParam = argStr1;
142            if (strcmp(outPathParam.c_str(), "") != 0) {
143                outPath = outPathParam;
144            }
145            break;
146        case CommandType::CT_C:
147        case CommandType::CT_G:
148        case CommandType::CT_D:
149        case CommandType::CT_F:
150        case CommandType::CT_T:
151        case CommandType::CT_P:
152        case CommandType::CT_R:
153        case CommandType::CT_NET:
154        case CommandType::CT_TTRACE:
155        case CommandType::CT_SNAPSHOT:
156        case CommandType::CT_HW:
157        case CommandType::CT_GC:
158        case CommandType::CT_NAV:
159            configs.push_back(argStr);
160            break;
161        default:
162            std::cout << "other unknown args:" << argStr << std::endl;
163            break;
164    }
165}
166
167int SmartPerfCommand::GetItemInfo(std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> &spMap)
168{
169    int rc = 0;
170    std::string errInfo;
171    if (!pkgName.empty()) {
172        std::string processId = "";
173        OHOS::SmartPerf::StartUpDelay sp;
174        processId = sp.GetPidByPkg(pkgName);
175        SpProfilerFactory::SetProfilerPidByPkg(processId);
176    }
177    for (size_t j = 0; j < configs.size(); j++) {
178        std::string curParam = configs[j];
179
180        if (curParam.find("-gc") != std::string::npos) {
181            continue;
182        }
183
184        SpProfiler *profiler = SpProfilerFactory::GetCmdProfilerItem(COMMAND_MAP.at(curParam), true);
185        if (profiler != nullptr) {
186            std::map<std::string, std::string> data = profiler->ItemData();
187            spMap.insert(data.cbegin(), data.cend());
188        }
189    }
190
191    if (!errInfo.empty()) { // GPU Counter init failed
192        printf("%s\n", errInfo.c_str());
193        LOGE("%s", errInfo.c_str());
194        return -1;
195    }
196
197    return rc;
198}
199
200void SmartPerfCommand::SaveGpuCounter() const
201{
202    std::string outGpuCounterDataPath = "/data/local/tmp";
203    gpuCounter.SaveData(outGpuCounterDataPath);
204    gpuCounter.StopCollect();
205}
206
207std::string SmartPerfCommand::ExecCommand()
208{
209    RAM &ram = RAM::GetInstance();
210    ram.SetFirstFlag();
211    int rc = 0;
212    int index = 0;
213    std::vector<SPData> vmap;
214    const long long freq = 1000;
215    num = num + 1;
216    bool gcFlag = false;
217    for (std::string itConfig : configs) {
218        if (itConfig.find("-gc") != std::string::npos) {
219            gpuCounter.StartCollect(GpuCounter::GC_START);
220            gcFlag = true;
221        }
222    }
223    while (index < num) {
224        std::multimap<std::string, std::string, decltype(SPUtils::Cmp) *> spMap(SPUtils::Cmp);
225        long long lastTime = SPUtils::GetCurTime();
226        spMap.insert(std::pair<std::string, std::string>(std::string("timestamp"), std::to_string(lastTime)));
227        rc = GetItemInfo(spMap);
228        if (rc == -1) {
229            break;
230        }
231        std::map<std::string, std::string> gpuCounterDataMap;
232        gpuCounter.GetGpuRealtimeData(gpuCounterDataMap);
233        spMap.insert(gpuCounterDataMap.begin(), gpuCounterDataMap.end());
234        std::cout << std::endl;
235        PrintMap(spMap, index);
236        std::cout << std::endl;
237        SPData spdata;
238        if (index != 0) {
239            spdata.values.insert(spMap.cbegin(), spMap.cend());
240            vmap.push_back(spdata);
241        }
242        long long nextTime = SPUtils::GetCurTime();
243        long long costTime = nextTime - lastTime;
244        if (costTime < freq) {
245            std::this_thread::sleep_for(std::chrono::milliseconds(freq - costTime));
246        }
247        index++;
248    }
249    if (gcFlag) {
250        SaveGpuCounter();
251    }
252    std::this_thread::sleep_for(std::chrono::milliseconds(freq));
253    LOGI("SmartPerfCommand::WriteCsv start");
254    SpCsvUtil::WriteCsv(std::string(outPath.c_str()), vmap);
255    LOGI("SmartPerfCommand::WriteCsv finish");
256    return std::string("command exec finished!");
257}
258void SmartPerfCommand::PrintfExecCommand(const std::map<std::string, std::string> data) const
259{
260    int i = 0;
261    for (auto a = data.cbegin(); a != data.cend(); ++a) {
262        printf("order:%d %s=%s\n", i++, a->first.c_str(), a->second.c_str());
263    }
264}
265
266void SmartPerfCommand::PrintMap(std::multimap<std::string, std::string,
267    decltype(SPUtils::Cmp) *> &spMap, int index) const
268{
269    int i = 0;
270    for (auto iter = spMap.cbegin(); iter != spMap.cend(); ++iter) {
271        if (index != 0) {
272            printf("order:%d %s=%s\n", i++, iter->first.c_str(), iter->second.c_str());
273        }
274    }
275}
276
277void SmartPerfCommand::InitSomething()
278{
279    std::string cmdResult;
280    std::string stat = CMD_COMMAND_MAP.at(CmdCommand::PROC_STAT);
281    if (SPUtils::LoadCmd(stat, cmdResult)) {
282        LOGI("SmartPerfCommand::InitSomething Privilege escalation!");
283    };
284}
285}
286}
287