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 "unistd.h"
19#include <fstream>
20#include <sstream>
21#include "include/smartperf_command.h"
22#include "include/editor_command.h"
23#include "include/profiler_fps.h"
24#include "include/client_control.h"
25#include "include/sp_utils.h"
26#include "include/sp_log.h"
27#include "include/common.h"
28#include "parameters.h"
29
30static std::string GetOptions(const std::vector<std::string> &argv)
31{
32    std::string str = "";
33    std::string strFlag;
34    bool isFill = false;
35    for (std::size_t i = 0; i < argv.size(); i++) {
36        if (!isFill) {
37            strFlag = argv[i];
38            if (strFlag.find("SP_daemon") != std::string::npos) {
39                isFill = true;
40            }
41        } else {
42            str += argv[i];
43            if (i + 1 != argv.size()) {
44                str += " ";
45            }
46        }
47    }
48    return str;
49}
50
51static bool g_checkCmdParam(std::vector<std::string> &argv, std::string &errorInfo)
52{
53    std::string str = GetOptions(argv);
54    std::set<std::string> keys; // Includes three parts "SP_daemon" CommandType and CommandHelp
55    if (str.empty()) {
56        return true;
57    }
58    // 'help' and 'version' start with "--" and are processed separately
59    if (str.find("--help") != std::string::npos || str.find("--version") != std::string::npos) {
60        std::vector<std::string> out;
61        OHOS::SmartPerf::SPUtils::StrSplit(str, "-", out);
62        if (out.size() != 1) {
63            errorInfo = "--help and --version cannot be used together with other options";
64            return false;
65        } else {
66            return true;
67        }
68    }
69    keys.insert("editor");
70    keys.insert("profilerfps");
71    keys.insert("start");
72    keys.insert("stop");
73    keys.insert("screen");
74    keys.insert("clear");
75    keys.insert("server");
76    keys.insert("sections");
77    keys.insert("deviceinfo");
78    keys.insert("ohtestfps");
79    keys.insert("editorServer");
80    keys.insert("recordcapacity");
81    for (auto a : OHOS::SmartPerf::COMMAND_MAP) {
82        keys.insert(a.first.substr(1)); // No prefix required '-'
83    }
84
85    /* ************The command line for the following parameters is not implemented****************** */
86    auto itr = keys.find("f1");
87    if (keys.end() != itr) {
88        keys.erase(itr);
89    }
90    itr = keys.find("f2");
91    if (keys.end() != itr) {
92        keys.erase(itr);
93    }
94    itr = keys.find("fl");
95    if (keys.end() != itr) {
96        keys.erase(itr);
97    }
98    itr = keys.find("ftl");
99    if (keys.end() != itr) {
100        keys.erase(itr);
101    }
102    return OHOS::SmartPerf::SPUtils::VeriyParameter(keys, str, errorInfo);
103}
104
105static void SocketStopCommand()
106{
107    OHOS::SmartPerf::ClientControl cc;
108    cc.SocketStop();
109}
110
111static void RecordCapacity()
112{
113    const std::string capacityRmPath = "/sys/class/power_supply/Battery/capacity_rm";
114    const std::string capacitySavePath = "/data/local/tmp/powerLeftRecord.csv";
115    std::string capacityString;
116    std::ifstream infile(capacitySavePath.c_str());
117
118    if (infile.is_open()) {
119        std::stringstream buffer;
120        int capacityLine = 0;
121        std::string line;
122        const int MAX_RECORD_COUNT = 100;
123        buffer << infile.rdbuf();
124        capacityString = buffer.str();
125        infile.close();
126
127        while (std::getline(buffer, line)) {
128            capacityLine++;
129        }
130        if (capacityLine == MAX_RECORD_COUNT) {
131            std::size_t pos = capacityString.find('\n');
132            if (pos != std::string::npos) {
133                capacityString = capacityString.substr(pos + 1);
134            }
135        }
136    }
137
138    std::ofstream outFile(capacitySavePath.c_str(), std::ios::out | std::ios::trunc);
139    if (!outFile.is_open()) {
140        std::cout << "Error opening capacity file!" << std::endl;
141        return;
142    }
143    std::string recordPower;
144    auto recordTime = std::to_string(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()));
145    OHOS::SmartPerf::SPUtils::LoadFile(capacityRmPath, recordPower);
146    std::cout << "recordTime: " << recordTime << std::endl << "recordPower: " << recordPower << std::endl;
147    capacityString += recordTime + "," + recordPower;
148    outFile << capacityString << std::endl;
149    if (outFile.fail()) {
150        const int bufSize = 256;
151        char buf[bufSize] = { 0 };
152        std::cout << "Error writing capacity failed:" << strerror_r(errno, buf, bufSize) << std::endl;
153    }
154    outFile.close();
155}
156
157static int ProcessSpecificParameter(int argc, char *argv[], std::vector<std::string> &vec)
158{
159    if (argc > 1 && strcmp(argv[1], "-editor") == 0) {
160        OHOS::SmartPerf::EditorCommand(argc, vec);
161        return 0;
162    } else if (argc > 1 && strcmp(argv[1], "-profilerfps") == 0) {
163        OHOS::SmartPerf::ProfilerFPS::GetInstance().GetFPS(vec);
164        return 0;
165    } else if (argc > 1 && strcmp(argv[1], "-start") == 0) {
166        OHOS::SmartPerf::ClientControl cc;
167        cc.StartSPDaemon();
168        std::string result;
169        for (int i = 2; i < argc; i++) {
170            result += argv[i];
171            if (i != argc - 1) {
172                result += " ";
173            }
174        }
175        cc.SocketStart(result);
176        return 1;
177    } else if (argc > 1 && strcmp(argv[1], "-stop") == 0) {
178        SocketStopCommand();
179        return 1;
180    } else if (argc > 1 && strcmp(argv[1], "-deviceinfo") == 0) {
181        std::cout << OHOS::SmartPerf::SPUtils::GetDeviceInfoMap() << std::endl;
182        return 0;
183    } else if (argc > 1 && strcmp(argv[1], "-ohtestfps") == 0) {
184        OHOS::SmartPerf::ProfilerFPS::GetInstance().GetOhFps(vec);
185        return 0;
186    } else if (argc > 1 && strcmp(argv[1], "-recordcapacity") == 0) {
187        RecordCapacity();
188        return 0;
189    }
190
191    return 1;
192}
193
194int main(int argc, char *argv[])
195{
196    if (!OHOS::system::GetBoolParameter("const.security.developermode.state", true)) {
197        std::cout << "Not a development mode state" << std::endl;
198        return 0;
199    }
200    if (argc < 0) {
201        std::cout << "Invalid argument count" << std::endl;
202        return -1;
203    }
204    std::string errorInfo;
205    std::vector<std::string> vec;
206
207    for (int i = 0; i < argc; i++) {
208        vec.push_back(argv[i]);
209    }
210    if (!g_checkCmdParam(vec, errorInfo)) {
211        std::cout << "SP_daemon:" << errorInfo << std::endl <<
212             "Usage: SP_daemon [options] [arguments]" << std::endl << std::endl <<
213             "Try `SP_daemon --help' for more options." << std::endl;
214        return 0;
215    }
216    OHOS::SmartPerf::SPUtils::SetRkFlag();
217    if (ProcessSpecificParameter(argc, argv, vec) == 0) {
218        return 0;
219    }
220    OHOS::SmartPerf::SmartPerfCommand cmd(vec);
221    std::cout << cmd.ExecCommand() << std::endl;
222    return 0;
223}
224