1c29fa5a6Sopenharmony_ci/*
2c29fa5a6Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License.
5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at
6c29fa5a6Sopenharmony_ci *
7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8c29fa5a6Sopenharmony_ci *
9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and
13c29fa5a6Sopenharmony_ci * limitations under the License.
14c29fa5a6Sopenharmony_ci */
15c29fa5a6Sopenharmony_ci
16c29fa5a6Sopenharmony_ci#include "util.h"
17c29fa5a6Sopenharmony_ci
18c29fa5a6Sopenharmony_ci#include <array>
19c29fa5a6Sopenharmony_ci#include <chrono>
20c29fa5a6Sopenharmony_ci#include <cinttypes>
21c29fa5a6Sopenharmony_ci#include <cstdarg>
22c29fa5a6Sopenharmony_ci#include <fstream>
23c29fa5a6Sopenharmony_ci#include <iostream>
24c29fa5a6Sopenharmony_ci
25c29fa5a6Sopenharmony_ci#include <sys/prctl.h>
26c29fa5a6Sopenharmony_ci#include <sys/stat.h>
27c29fa5a6Sopenharmony_ci#include <sys/syscall.h>
28c29fa5a6Sopenharmony_ci#include <sys/time.h>
29c29fa5a6Sopenharmony_ci#include <sys/types.h>
30c29fa5a6Sopenharmony_ci#include <unistd.h>
31c29fa5a6Sopenharmony_ci
32c29fa5a6Sopenharmony_ci#include "aggregator.h"
33c29fa5a6Sopenharmony_ci#include "config_multimodal.h"
34c29fa5a6Sopenharmony_ci#include "define_multimodal.h"
35c29fa5a6Sopenharmony_ci#include "error_multimodal.h"
36c29fa5a6Sopenharmony_ci#include "mmi_log.h"
37c29fa5a6Sopenharmony_ci#include "securec.h"
38c29fa5a6Sopenharmony_ci
39c29fa5a6Sopenharmony_ci#undef MMI_LOG_TAG
40c29fa5a6Sopenharmony_ci#define MMI_LOG_TAG "Util"
41c29fa5a6Sopenharmony_ci
42c29fa5a6Sopenharmony_cinamespace OHOS {
43c29fa5a6Sopenharmony_cinamespace MMI {
44c29fa5a6Sopenharmony_cinamespace {
45c29fa5a6Sopenharmony_ciconstexpr int32_t FILE_SIZE_MAX { 0x6C445 };
46c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_PRO_FILE_SIZE { 128000 };
47c29fa5a6Sopenharmony_ciconstexpr int32_t INVALID_FILE_SIZE { -1 };
48c29fa5a6Sopenharmony_ciconstexpr int32_t MIN_INTERVALTIME { 36 };
49c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_INTERVALTIME { 100 };
50c29fa5a6Sopenharmony_ciconstexpr int32_t MIN_DELAYTIME { 300 };
51c29fa5a6Sopenharmony_ciconstexpr int32_t MAX_DELAYTIME { 1000 };
52c29fa5a6Sopenharmony_ciconstexpr int32_t COMMENT_SUBSCRIPT { 0 };
53c29fa5a6Sopenharmony_ciconst std::string CONFIG_ITEM_REPEAT = "Key.autorepeat";
54c29fa5a6Sopenharmony_ciconst std::string CONFIG_ITEM_DELAY = "Key.autorepeat.delaytime";
55c29fa5a6Sopenharmony_ciconst std::string CONFIG_ITEM_INTERVAL = "Key.autorepeat.intervaltime";
56c29fa5a6Sopenharmony_ciconst std::string CONFIG_ITEM_TYPE = "Key.keyboard.type";
57c29fa5a6Sopenharmony_ciconst std::string CURSORSTYLE_PATH = "/system/etc/multimodalinput/mouse_icon/";
58c29fa5a6Sopenharmony_ciconst std::string DATA_PATH = "/data";
59c29fa5a6Sopenharmony_ciconst std::string INPUT_PATH = "/system/";
60c29fa5a6Sopenharmony_ciconst std::string KEY_PATH = "/vendor/etc/keymap/";
61c29fa5a6Sopenharmony_ciconstexpr size_t BUF_TID_SIZE { 10 };
62c29fa5a6Sopenharmony_ciconstexpr size_t BUF_CMD_SIZE { 512 };
63c29fa5a6Sopenharmony_ciconstexpr size_t PROGRAM_NAME_SIZE { 256 };
64c29fa5a6Sopenharmony_ciconstexpr int32_t TIME_CONVERSION_UNIT { 1000 };
65c29fa5a6Sopenharmony_ci} // namespace
66c29fa5a6Sopenharmony_ci
67c29fa5a6Sopenharmony_ciint64_t GetSysClockTime()
68c29fa5a6Sopenharmony_ci{
69c29fa5a6Sopenharmony_ci    struct timespec ts = { 0, 0 };
70c29fa5a6Sopenharmony_ci    if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
71c29fa5a6Sopenharmony_ci        MMI_HILOGD("clock_gettime failed:%{public}d", errno);
72c29fa5a6Sopenharmony_ci        return 0;
73c29fa5a6Sopenharmony_ci    }
74c29fa5a6Sopenharmony_ci    return (ts.tv_sec * TIME_CONVERSION_UNIT * TIME_CONVERSION_UNIT) + (ts.tv_nsec / TIME_CONVERSION_UNIT);
75c29fa5a6Sopenharmony_ci}
76c29fa5a6Sopenharmony_ci
77c29fa5a6Sopenharmony_ciint64_t GetMillisTime()
78c29fa5a6Sopenharmony_ci{
79c29fa5a6Sopenharmony_ci    auto timeNow = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now());
80c29fa5a6Sopenharmony_ci    auto tmp = std::chrono::duration_cast<std::chrono::milliseconds>(timeNow.time_since_epoch());
81c29fa5a6Sopenharmony_ci    return tmp.count();
82c29fa5a6Sopenharmony_ci}
83c29fa5a6Sopenharmony_ci
84c29fa5a6Sopenharmony_cistatic std::string GetThisThreadIdOfString()
85c29fa5a6Sopenharmony_ci{
86c29fa5a6Sopenharmony_ci    thread_local std::string threadLocalId;
87c29fa5a6Sopenharmony_ci    if (threadLocalId.empty()) {
88c29fa5a6Sopenharmony_ci        long tid = syscall(SYS_gettid);
89c29fa5a6Sopenharmony_ci        char buf[BUF_TID_SIZE] = {};
90c29fa5a6Sopenharmony_ci        const int32_t ret = sprintf_s(buf, BUF_TID_SIZE, "%06d", tid);
91c29fa5a6Sopenharmony_ci        if (ret < 0) {
92c29fa5a6Sopenharmony_ci            printf("ERR: in %s, #%d, call sprintf_s failed, ret = %d", __func__, __LINE__, ret);
93c29fa5a6Sopenharmony_ci            return threadLocalId;
94c29fa5a6Sopenharmony_ci        }
95c29fa5a6Sopenharmony_ci        buf[BUF_TID_SIZE - 1] = '\0';
96c29fa5a6Sopenharmony_ci        threadLocalId = buf;
97c29fa5a6Sopenharmony_ci    }
98c29fa5a6Sopenharmony_ci
99c29fa5a6Sopenharmony_ci    return threadLocalId;
100c29fa5a6Sopenharmony_ci}
101c29fa5a6Sopenharmony_ci
102c29fa5a6Sopenharmony_ciuint64_t GetThisThreadId()
103c29fa5a6Sopenharmony_ci{
104c29fa5a6Sopenharmony_ci    std::string stid = GetThisThreadIdOfString();
105c29fa5a6Sopenharmony_ci    auto tid = std::atoll(stid.c_str());
106c29fa5a6Sopenharmony_ci    return tid;
107c29fa5a6Sopenharmony_ci}
108c29fa5a6Sopenharmony_ci
109c29fa5a6Sopenharmony_cistatic size_t StringToken(std::string &str, const std::string &sep, std::string &token)
110c29fa5a6Sopenharmony_ci{
111c29fa5a6Sopenharmony_ci    token = "";
112c29fa5a6Sopenharmony_ci    if (str.empty()) {
113c29fa5a6Sopenharmony_ci        return str.npos;
114c29fa5a6Sopenharmony_ci    }
115c29fa5a6Sopenharmony_ci    size_t pos = str.npos;
116c29fa5a6Sopenharmony_ci    size_t tmp = 0;
117c29fa5a6Sopenharmony_ci    for (auto &item : sep) {
118c29fa5a6Sopenharmony_ci        tmp = str.find(item);
119c29fa5a6Sopenharmony_ci        if (str.npos != tmp) {
120c29fa5a6Sopenharmony_ci            pos = (std::min)(pos, tmp);
121c29fa5a6Sopenharmony_ci        }
122c29fa5a6Sopenharmony_ci    }
123c29fa5a6Sopenharmony_ci    if (str.npos != pos) {
124c29fa5a6Sopenharmony_ci        token = str.substr(0, pos);
125c29fa5a6Sopenharmony_ci        if (str.npos != pos + 1) {
126c29fa5a6Sopenharmony_ci            str = str.substr(pos + 1, str.npos);
127c29fa5a6Sopenharmony_ci        }
128c29fa5a6Sopenharmony_ci        if (pos == 0) {
129c29fa5a6Sopenharmony_ci            return StringToken(str, sep, token);
130c29fa5a6Sopenharmony_ci        }
131c29fa5a6Sopenharmony_ci    } else {
132c29fa5a6Sopenharmony_ci        token = str;
133c29fa5a6Sopenharmony_ci        str = "";
134c29fa5a6Sopenharmony_ci    }
135c29fa5a6Sopenharmony_ci    return token.size();
136c29fa5a6Sopenharmony_ci}
137c29fa5a6Sopenharmony_ci
138c29fa5a6Sopenharmony_cisize_t StringSplit(const std::string &str, const std::string &sep, std::vector<std::string> &vecList)
139c29fa5a6Sopenharmony_ci{
140c29fa5a6Sopenharmony_ci    size_t size;
141c29fa5a6Sopenharmony_ci    auto strs = str;
142c29fa5a6Sopenharmony_ci    std::string token;
143c29fa5a6Sopenharmony_ci    while (str.npos != (size = StringToken(strs, sep, token))) {
144c29fa5a6Sopenharmony_ci        vecList.push_back(token);
145c29fa5a6Sopenharmony_ci    }
146c29fa5a6Sopenharmony_ci    return vecList.size();
147c29fa5a6Sopenharmony_ci}
148c29fa5a6Sopenharmony_ci
149c29fa5a6Sopenharmony_cistd::string IdsListToString(const std::vector<int32_t> &list, const std::string &sep)
150c29fa5a6Sopenharmony_ci{
151c29fa5a6Sopenharmony_ci    std::string str;
152c29fa5a6Sopenharmony_ci    for (const auto &it : list) {
153c29fa5a6Sopenharmony_ci        str += std::to_string(it) + sep;
154c29fa5a6Sopenharmony_ci    }
155c29fa5a6Sopenharmony_ci    if (str.size() > 0) {
156c29fa5a6Sopenharmony_ci        str.resize(str.size() - sep.size());
157c29fa5a6Sopenharmony_ci    }
158c29fa5a6Sopenharmony_ci    return str;
159c29fa5a6Sopenharmony_ci}
160c29fa5a6Sopenharmony_ci
161c29fa5a6Sopenharmony_ciint32_t GetPid()
162c29fa5a6Sopenharmony_ci{
163c29fa5a6Sopenharmony_ci    return static_cast<int32_t>(getpid());
164c29fa5a6Sopenharmony_ci}
165c29fa5a6Sopenharmony_ci
166c29fa5a6Sopenharmony_cistatic std::string GetFileName(const std::string &strPath)
167c29fa5a6Sopenharmony_ci{
168c29fa5a6Sopenharmony_ci    size_t nPos = strPath.find_last_of('/');
169c29fa5a6Sopenharmony_ci    if (strPath.npos == nPos) {
170c29fa5a6Sopenharmony_ci        nPos = strPath.find_last_of('\\');
171c29fa5a6Sopenharmony_ci    }
172c29fa5a6Sopenharmony_ci    if (strPath.npos == nPos) {
173c29fa5a6Sopenharmony_ci        return strPath;
174c29fa5a6Sopenharmony_ci    }
175c29fa5a6Sopenharmony_ci
176c29fa5a6Sopenharmony_ci    return strPath.substr(nPos + 1, strPath.npos);
177c29fa5a6Sopenharmony_ci}
178c29fa5a6Sopenharmony_ci
179c29fa5a6Sopenharmony_ciconst char *GetProgramName()
180c29fa5a6Sopenharmony_ci{
181c29fa5a6Sopenharmony_ci    static char programName[PROGRAM_NAME_SIZE] = {};
182c29fa5a6Sopenharmony_ci    if (programName[0] != '\0') {
183c29fa5a6Sopenharmony_ci        return programName;
184c29fa5a6Sopenharmony_ci    }
185c29fa5a6Sopenharmony_ci
186c29fa5a6Sopenharmony_ci    char buf[BUF_CMD_SIZE] = { 0 };
187c29fa5a6Sopenharmony_ci    if (sprintf_s(buf, BUF_CMD_SIZE, "/proc/%d/cmdline", static_cast<int32_t>(getpid())) == -1) {
188c29fa5a6Sopenharmony_ci        KMSG_LOGE("GetProcessInfo sprintf_s /proc/.../cmdline error");
189c29fa5a6Sopenharmony_ci        return "";
190c29fa5a6Sopenharmony_ci    }
191c29fa5a6Sopenharmony_ci    FILE *fp = fopen(buf, "rb");
192c29fa5a6Sopenharmony_ci    CHKPS(fp);
193c29fa5a6Sopenharmony_ci    static constexpr size_t bufLineSize = 512;
194c29fa5a6Sopenharmony_ci    char bufLine[bufLineSize] = { 0 };
195c29fa5a6Sopenharmony_ci    if ((fgets(bufLine, bufLineSize, fp) == nullptr)) {
196c29fa5a6Sopenharmony_ci        KMSG_LOGE("fgets failed");
197c29fa5a6Sopenharmony_ci        if (fclose(fp) != 0) {
198c29fa5a6Sopenharmony_ci            KMSG_LOGW("Close file:%s failed", buf);
199c29fa5a6Sopenharmony_ci        }
200c29fa5a6Sopenharmony_ci        fp = nullptr;
201c29fa5a6Sopenharmony_ci        return "";
202c29fa5a6Sopenharmony_ci    }
203c29fa5a6Sopenharmony_ci    if (fclose(fp) != 0) {
204c29fa5a6Sopenharmony_ci        KMSG_LOGW("Close file:%s failed", buf);
205c29fa5a6Sopenharmony_ci    }
206c29fa5a6Sopenharmony_ci    fp = nullptr;
207c29fa5a6Sopenharmony_ci
208c29fa5a6Sopenharmony_ci    std::string tempName(bufLine);
209c29fa5a6Sopenharmony_ci    tempName = GetFileName(tempName);
210c29fa5a6Sopenharmony_ci    if (tempName.empty()) {
211c29fa5a6Sopenharmony_ci        KMSG_LOGE("tempName is empty");
212c29fa5a6Sopenharmony_ci        return "";
213c29fa5a6Sopenharmony_ci    }
214c29fa5a6Sopenharmony_ci    const size_t copySize = std::min(tempName.size(), PROGRAM_NAME_SIZE - 1);
215c29fa5a6Sopenharmony_ci    if (copySize == 0) {
216c29fa5a6Sopenharmony_ci        KMSG_LOGE("The copySize is 0");
217c29fa5a6Sopenharmony_ci        return "";
218c29fa5a6Sopenharmony_ci    }
219c29fa5a6Sopenharmony_ci    errno_t ret = memcpy_s(programName, PROGRAM_NAME_SIZE, tempName.c_str(), copySize);
220c29fa5a6Sopenharmony_ci    if (ret != EOK) {
221c29fa5a6Sopenharmony_ci        return "";
222c29fa5a6Sopenharmony_ci    }
223c29fa5a6Sopenharmony_ci    KMSG_LOGI("GetProgramName success. programName = %s", programName);
224c29fa5a6Sopenharmony_ci
225c29fa5a6Sopenharmony_ci    return programName;
226c29fa5a6Sopenharmony_ci}
227c29fa5a6Sopenharmony_ci
228c29fa5a6Sopenharmony_civoid SetThreadName(const std::string &name)
229c29fa5a6Sopenharmony_ci{
230c29fa5a6Sopenharmony_ci    prctl(PR_SET_NAME, name.c_str());
231c29fa5a6Sopenharmony_ci}
232c29fa5a6Sopenharmony_ci
233c29fa5a6Sopenharmony_cistatic bool IsFileExists(const std::string &fileName)
234c29fa5a6Sopenharmony_ci{
235c29fa5a6Sopenharmony_ci    return (access(fileName.c_str(), F_OK) == 0);
236c29fa5a6Sopenharmony_ci}
237c29fa5a6Sopenharmony_ci
238c29fa5a6Sopenharmony_cistatic bool CheckFileExtendName(const std::string &filePath, const std::string &checkExtension)
239c29fa5a6Sopenharmony_ci{
240c29fa5a6Sopenharmony_ci    std::string::size_type pos = filePath.find_last_of('.');
241c29fa5a6Sopenharmony_ci    if (pos == std::string::npos) {
242c29fa5a6Sopenharmony_ci        MMI_HILOGE("File is not find extension");
243c29fa5a6Sopenharmony_ci        return false;
244c29fa5a6Sopenharmony_ci    }
245c29fa5a6Sopenharmony_ci    return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
246c29fa5a6Sopenharmony_ci}
247c29fa5a6Sopenharmony_ci
248c29fa5a6Sopenharmony_cistatic int32_t GetFileSize(const std::string &filePath)
249c29fa5a6Sopenharmony_ci{
250c29fa5a6Sopenharmony_ci    struct stat statbuf = { 0 };
251c29fa5a6Sopenharmony_ci    if (stat(filePath.c_str(), &statbuf) != 0) {
252c29fa5a6Sopenharmony_ci        MMI_HILOGE("Get file size error");
253c29fa5a6Sopenharmony_ci        return INVALID_FILE_SIZE;
254c29fa5a6Sopenharmony_ci    }
255c29fa5a6Sopenharmony_ci    return statbuf.st_size;
256c29fa5a6Sopenharmony_ci}
257c29fa5a6Sopenharmony_ci
258c29fa5a6Sopenharmony_cistatic std::string ReadFile(const std::string &filePath)
259c29fa5a6Sopenharmony_ci{
260c29fa5a6Sopenharmony_ci    FILE *fp = fopen(filePath.c_str(), "r");
261c29fa5a6Sopenharmony_ci    CHKPS(fp);
262c29fa5a6Sopenharmony_ci    std::string dataStr;
263c29fa5a6Sopenharmony_ci    char buf[256] = {};
264c29fa5a6Sopenharmony_ci    while (fgets(buf, sizeof(buf), fp) != nullptr) {
265c29fa5a6Sopenharmony_ci        dataStr += buf;
266c29fa5a6Sopenharmony_ci    }
267c29fa5a6Sopenharmony_ci    if (fclose(fp) != 0) {
268c29fa5a6Sopenharmony_ci        MMI_HILOGW("Close file failed");
269c29fa5a6Sopenharmony_ci    }
270c29fa5a6Sopenharmony_ci    return dataStr;
271c29fa5a6Sopenharmony_ci}
272c29fa5a6Sopenharmony_ci
273c29fa5a6Sopenharmony_cistatic bool IsValidPath(const std::string &rootDir, const std::string &filePath)
274c29fa5a6Sopenharmony_ci{
275c29fa5a6Sopenharmony_ci    return (filePath.compare(0, rootDir.size(), rootDir) == 0);
276c29fa5a6Sopenharmony_ci}
277c29fa5a6Sopenharmony_ci
278c29fa5a6Sopenharmony_cibool IsValidJsonPath(const std::string &filePath)
279c29fa5a6Sopenharmony_ci{
280c29fa5a6Sopenharmony_ci    return IsValidPath(DATA_PATH, filePath) || IsValidPath(INPUT_PATH, filePath);
281c29fa5a6Sopenharmony_ci}
282c29fa5a6Sopenharmony_ci
283c29fa5a6Sopenharmony_cistatic bool IsValidProPath(const std::string &filePath)
284c29fa5a6Sopenharmony_ci{
285c29fa5a6Sopenharmony_ci    return IsValidPath(KEY_PATH, filePath);
286c29fa5a6Sopenharmony_ci}
287c29fa5a6Sopenharmony_ci
288c29fa5a6Sopenharmony_cistatic bool IsValidTomlPath(const std::string &filePath)
289c29fa5a6Sopenharmony_ci{
290c29fa5a6Sopenharmony_ci    return IsValidPath(KEY_PATH, filePath);
291c29fa5a6Sopenharmony_ci}
292c29fa5a6Sopenharmony_ci
293c29fa5a6Sopenharmony_civoid ReadProFile(const std::string &filePath, int32_t deviceId,
294c29fa5a6Sopenharmony_ci    std::map<int32_t, std::map<int32_t, int32_t>> &configMap)
295c29fa5a6Sopenharmony_ci{
296c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
297c29fa5a6Sopenharmony_ci    if (filePath.empty()) {
298c29fa5a6Sopenharmony_ci        MMI_HILOGE("FilePath is empty");
299c29fa5a6Sopenharmony_ci        return;
300c29fa5a6Sopenharmony_ci    }
301c29fa5a6Sopenharmony_ci    char realPath[PATH_MAX] = {};
302c29fa5a6Sopenharmony_ci    CHKPV(realpath(filePath.c_str(), realPath));
303c29fa5a6Sopenharmony_ci    if (!IsValidProPath(realPath)) {
304c29fa5a6Sopenharmony_ci        MMI_HILOGE("File path is error");
305c29fa5a6Sopenharmony_ci        return;
306c29fa5a6Sopenharmony_ci    }
307c29fa5a6Sopenharmony_ci    if (!IsFileExists(realPath)) {
308c29fa5a6Sopenharmony_ci        MMI_HILOGE("File is not existent");
309c29fa5a6Sopenharmony_ci        return;
310c29fa5a6Sopenharmony_ci    }
311c29fa5a6Sopenharmony_ci    if (!CheckFileExtendName(realPath, "pro")) {
312c29fa5a6Sopenharmony_ci        MMI_HILOGE("Unable to parse files other than json format");
313c29fa5a6Sopenharmony_ci        return;
314c29fa5a6Sopenharmony_ci    }
315c29fa5a6Sopenharmony_ci    auto fileSize = GetFileSize(realPath);
316c29fa5a6Sopenharmony_ci    if ((fileSize == INVALID_FILE_SIZE) || (fileSize >= MAX_PRO_FILE_SIZE)) {
317c29fa5a6Sopenharmony_ci        MMI_HILOGE("The configuration file size is incorrect");
318c29fa5a6Sopenharmony_ci        return;
319c29fa5a6Sopenharmony_ci    }
320c29fa5a6Sopenharmony_ci    ReadProConfigFile(realPath, deviceId, configMap);
321c29fa5a6Sopenharmony_ci}
322c29fa5a6Sopenharmony_ci
323c29fa5a6Sopenharmony_cistatic inline bool IsNum(const std::string &str)
324c29fa5a6Sopenharmony_ci{
325c29fa5a6Sopenharmony_ci    std::istringstream sin(str);
326c29fa5a6Sopenharmony_ci    double num;
327c29fa5a6Sopenharmony_ci    return (sin >> num) && sin.eof();
328c29fa5a6Sopenharmony_ci}
329c29fa5a6Sopenharmony_ci
330c29fa5a6Sopenharmony_civoid ReadProConfigFile(const std::string &realPath, int32_t deviceId,
331c29fa5a6Sopenharmony_ci    std::map<int32_t, std::map<int32_t, int32_t>> &configKey)
332c29fa5a6Sopenharmony_ci{
333c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
334c29fa5a6Sopenharmony_ci    std::ifstream reader(realPath);
335c29fa5a6Sopenharmony_ci    if (!reader.is_open()) {
336c29fa5a6Sopenharmony_ci        MMI_HILOGE("Failed to open config file");
337c29fa5a6Sopenharmony_ci        return;
338c29fa5a6Sopenharmony_ci    }
339c29fa5a6Sopenharmony_ci    std::string strLine;
340c29fa5a6Sopenharmony_ci    int32_t sysKeyValue;
341c29fa5a6Sopenharmony_ci    int32_t nativeKeyValue;
342c29fa5a6Sopenharmony_ci    int32_t elementKey = 0;
343c29fa5a6Sopenharmony_ci    int32_t elementValue = 0;
344c29fa5a6Sopenharmony_ci    std::map<int32_t, int32_t> tmpConfigKey;
345c29fa5a6Sopenharmony_ci    while (std::getline(reader, strLine)) {
346c29fa5a6Sopenharmony_ci        const char* line = strLine.c_str();
347c29fa5a6Sopenharmony_ci        int32_t len = strlen(line);
348c29fa5a6Sopenharmony_ci        char* realLine = static_cast<char*>(malloc(len + 1));
349c29fa5a6Sopenharmony_ci        CHKPV(realLine);
350c29fa5a6Sopenharmony_ci        if (strcpy_s(realLine, len + 1, line) != EOK) {
351c29fa5a6Sopenharmony_ci            MMI_HILOGE("strcpy_s error");
352c29fa5a6Sopenharmony_ci            free(realLine);
353c29fa5a6Sopenharmony_ci            realLine = nullptr;
354c29fa5a6Sopenharmony_ci            return;
355c29fa5a6Sopenharmony_ci        }
356c29fa5a6Sopenharmony_ci        *(realLine + len + 1) = '\0';
357c29fa5a6Sopenharmony_ci        int32_t ret = ReadConfigInfo(realLine, len, &elementKey, &elementValue);
358c29fa5a6Sopenharmony_ci        free(realLine);
359c29fa5a6Sopenharmony_ci        realLine = nullptr;
360c29fa5a6Sopenharmony_ci        if (ret != RET_OK) {
361c29fa5a6Sopenharmony_ci            MMI_HILOGE("Failed to read from line of config info");
362c29fa5a6Sopenharmony_ci            reader.close();
363c29fa5a6Sopenharmony_ci            return;
364c29fa5a6Sopenharmony_ci        }
365c29fa5a6Sopenharmony_ci        nativeKeyValue = elementKey;
366c29fa5a6Sopenharmony_ci        sysKeyValue = elementValue;
367c29fa5a6Sopenharmony_ci        MMI_HILOGD("The nativeKeyValue is:%{public}d, sysKeyValue is:%{public}d", nativeKeyValue, sysKeyValue);
368c29fa5a6Sopenharmony_ci        tmpConfigKey.insert(std::pair<int32_t, int32_t>(nativeKeyValue, sysKeyValue));
369c29fa5a6Sopenharmony_ci    }
370c29fa5a6Sopenharmony_ci    reader.close();
371c29fa5a6Sopenharmony_ci    auto iter = configKey.insert(std::make_pair(deviceId, tmpConfigKey));
372c29fa5a6Sopenharmony_ci    if (!iter.second) {
373c29fa5a6Sopenharmony_ci        MMI_HILOGE("The file name is duplicated");
374c29fa5a6Sopenharmony_ci        return;
375c29fa5a6Sopenharmony_ci    }
376c29fa5a6Sopenharmony_ci}
377c29fa5a6Sopenharmony_ci
378c29fa5a6Sopenharmony_cistd::string ReadJsonFile(const std::string &filePath)
379c29fa5a6Sopenharmony_ci{
380c29fa5a6Sopenharmony_ci    if (filePath.empty()) {
381c29fa5a6Sopenharmony_ci        MMI_HILOGE("FilePath is empty");
382c29fa5a6Sopenharmony_ci        return "";
383c29fa5a6Sopenharmony_ci    }
384c29fa5a6Sopenharmony_ci    char realPath[PATH_MAX] = {};
385c29fa5a6Sopenharmony_ci    CHKPS(realpath(filePath.c_str(), realPath));
386c29fa5a6Sopenharmony_ci    if (!IsValidJsonPath(realPath)) {
387c29fa5a6Sopenharmony_ci        MMI_HILOGE("File path is error");
388c29fa5a6Sopenharmony_ci        return "";
389c29fa5a6Sopenharmony_ci    }
390c29fa5a6Sopenharmony_ci    if (!CheckFileExtendName(realPath, "json")) {
391c29fa5a6Sopenharmony_ci        MMI_HILOGE("Unable to parse files other than json format");
392c29fa5a6Sopenharmony_ci        return "";
393c29fa5a6Sopenharmony_ci    }
394c29fa5a6Sopenharmony_ci    if (!IsFileExists(realPath)) {
395c29fa5a6Sopenharmony_ci        MMI_HILOGE("File is not existent");
396c29fa5a6Sopenharmony_ci        return "";
397c29fa5a6Sopenharmony_ci    }
398c29fa5a6Sopenharmony_ci    int32_t fileSize = GetFileSize(realPath);
399c29fa5a6Sopenharmony_ci    if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
400c29fa5a6Sopenharmony_ci        MMI_HILOGE("File size out of read range");
401c29fa5a6Sopenharmony_ci        return "";
402c29fa5a6Sopenharmony_ci    }
403c29fa5a6Sopenharmony_ci    return ReadFile(filePath);
404c29fa5a6Sopenharmony_ci}
405c29fa5a6Sopenharmony_ci
406c29fa5a6Sopenharmony_cistatic int32_t ConfigItemSwitch(const std::string &configItem, const std::string &value, DeviceConfig &devConf)
407c29fa5a6Sopenharmony_ci{
408c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
409c29fa5a6Sopenharmony_ci    if (configItem.empty() || value.empty()) {
410c29fa5a6Sopenharmony_ci        MMI_HILOGE("Get key config item is invalid");
411c29fa5a6Sopenharmony_ci        return RET_ERR;
412c29fa5a6Sopenharmony_ci    }
413c29fa5a6Sopenharmony_ci    if (!IsNum(value)) {
414c29fa5a6Sopenharmony_ci        MMI_HILOGE("Get key config item is invalid");
415c29fa5a6Sopenharmony_ci        return RET_ERR;
416c29fa5a6Sopenharmony_ci    }
417c29fa5a6Sopenharmony_ci    if (configItem == CONFIG_ITEM_REPEAT) {
418c29fa5a6Sopenharmony_ci        devConf.autoSwitch = stoi(value);
419c29fa5a6Sopenharmony_ci    } else if (configItem == CONFIG_ITEM_DELAY) {
420c29fa5a6Sopenharmony_ci        devConf.delayTime = stoi(value);
421c29fa5a6Sopenharmony_ci        if (devConf.delayTime < MIN_DELAYTIME || devConf.delayTime > MAX_DELAYTIME) {
422c29fa5a6Sopenharmony_ci            MMI_HILOGE("Unusual the delaytime");
423c29fa5a6Sopenharmony_ci            return RET_ERR;
424c29fa5a6Sopenharmony_ci        }
425c29fa5a6Sopenharmony_ci    } else if (configItem == CONFIG_ITEM_INTERVAL) {
426c29fa5a6Sopenharmony_ci        devConf.intervalTime = stoi(value);
427c29fa5a6Sopenharmony_ci        if (devConf.intervalTime < MIN_INTERVALTIME || devConf.intervalTime > MAX_INTERVALTIME) {
428c29fa5a6Sopenharmony_ci            MMI_HILOGE("Unusual the intervaltime");
429c29fa5a6Sopenharmony_ci            return RET_ERR;
430c29fa5a6Sopenharmony_ci        }
431c29fa5a6Sopenharmony_ci    } else if (configItem == CONFIG_ITEM_TYPE) {
432c29fa5a6Sopenharmony_ci        devConf.keyboardType = stoi(value);
433c29fa5a6Sopenharmony_ci    }
434c29fa5a6Sopenharmony_ci    return RET_OK;
435c29fa5a6Sopenharmony_ci}
436c29fa5a6Sopenharmony_ci
437c29fa5a6Sopenharmony_cistatic int32_t ReadConfigFile(const std::string &realPath, DeviceConfig &devConf)
438c29fa5a6Sopenharmony_ci{
439c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
440c29fa5a6Sopenharmony_ci    std::ifstream cfgFile(realPath);
441c29fa5a6Sopenharmony_ci    if (!cfgFile.is_open()) {
442c29fa5a6Sopenharmony_ci        MMI_HILOGE("Failed to open config file");
443c29fa5a6Sopenharmony_ci        return FILE_OPEN_FAIL;
444c29fa5a6Sopenharmony_ci    }
445c29fa5a6Sopenharmony_ci    std::string tmp;
446c29fa5a6Sopenharmony_ci    while (std::getline(cfgFile, tmp)) {
447c29fa5a6Sopenharmony_ci        RemoveSpace(tmp);
448c29fa5a6Sopenharmony_ci        size_t pos = tmp.find('#');
449c29fa5a6Sopenharmony_ci        if (pos != tmp.npos && pos != COMMENT_SUBSCRIPT) {
450c29fa5a6Sopenharmony_ci            MMI_HILOGE("File format is error");
451c29fa5a6Sopenharmony_ci            cfgFile.close();
452c29fa5a6Sopenharmony_ci            return RET_ERR;
453c29fa5a6Sopenharmony_ci        }
454c29fa5a6Sopenharmony_ci        if (tmp.empty() || tmp.front() == '#') {
455c29fa5a6Sopenharmony_ci            continue;
456c29fa5a6Sopenharmony_ci        }
457c29fa5a6Sopenharmony_ci        pos = tmp.find('=');
458c29fa5a6Sopenharmony_ci        if ((pos == std::string::npos) || (tmp.back() == '=')) {
459c29fa5a6Sopenharmony_ci            MMI_HILOGE("Find config item error");
460c29fa5a6Sopenharmony_ci            cfgFile.close();
461c29fa5a6Sopenharmony_ci            return RET_ERR;
462c29fa5a6Sopenharmony_ci        }
463c29fa5a6Sopenharmony_ci        std::string configItem = tmp.substr(0, pos);
464c29fa5a6Sopenharmony_ci        std::string value = tmp.substr(pos + 1);
465c29fa5a6Sopenharmony_ci        if (ConfigItemSwitch(configItem, value, devConf) == RET_ERR) {
466c29fa5a6Sopenharmony_ci            MMI_HILOGE("Configuration item error");
467c29fa5a6Sopenharmony_ci            cfgFile.close();
468c29fa5a6Sopenharmony_ci            return RET_ERR;
469c29fa5a6Sopenharmony_ci        }
470c29fa5a6Sopenharmony_ci    }
471c29fa5a6Sopenharmony_ci    cfgFile.close();
472c29fa5a6Sopenharmony_ci    return RET_OK;
473c29fa5a6Sopenharmony_ci}
474c29fa5a6Sopenharmony_ci
475c29fa5a6Sopenharmony_ciint32_t ReadTomlFile(const std::string &filePath, DeviceConfig &devConf)
476c29fa5a6Sopenharmony_ci{
477c29fa5a6Sopenharmony_ci    if (filePath.empty()) {
478c29fa5a6Sopenharmony_ci        MMI_HILOGE("FilePath is empty");
479c29fa5a6Sopenharmony_ci        return RET_ERR;
480c29fa5a6Sopenharmony_ci    }
481c29fa5a6Sopenharmony_ci    char realPath[PATH_MAX] = {};
482c29fa5a6Sopenharmony_ci    CHKPR(realpath(filePath.c_str(), realPath), RET_ERR);
483c29fa5a6Sopenharmony_ci    if (!IsValidTomlPath(realPath)) {
484c29fa5a6Sopenharmony_ci        MMI_HILOGE("File path is error");
485c29fa5a6Sopenharmony_ci        return RET_ERR;
486c29fa5a6Sopenharmony_ci    }
487c29fa5a6Sopenharmony_ci    if (!IsFileExists(realPath)) {
488c29fa5a6Sopenharmony_ci        MMI_HILOGE("File is not existent");
489c29fa5a6Sopenharmony_ci        return RET_ERR;
490c29fa5a6Sopenharmony_ci    }
491c29fa5a6Sopenharmony_ci    if (!CheckFileExtendName(realPath, "TOML")) {
492c29fa5a6Sopenharmony_ci        MMI_HILOGE("Unable to parse files other than json format");
493c29fa5a6Sopenharmony_ci        return RET_ERR;
494c29fa5a6Sopenharmony_ci    }
495c29fa5a6Sopenharmony_ci    int32_t fileSize = GetFileSize(realPath);
496c29fa5a6Sopenharmony_ci    if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
497c29fa5a6Sopenharmony_ci        MMI_HILOGE("File size out of read range");
498c29fa5a6Sopenharmony_ci        return RET_ERR;
499c29fa5a6Sopenharmony_ci    }
500c29fa5a6Sopenharmony_ci    if (ReadConfigFile(realPath, devConf) == RET_ERR) {
501c29fa5a6Sopenharmony_ci        MMI_HILOGE("Read device config file failed");
502c29fa5a6Sopenharmony_ci        return RET_ERR;
503c29fa5a6Sopenharmony_ci    }
504c29fa5a6Sopenharmony_ci    return RET_OK;
505c29fa5a6Sopenharmony_ci}
506c29fa5a6Sopenharmony_ci
507c29fa5a6Sopenharmony_ciint32_t ReadCursorStyleFile(const std::string &filePath)
508c29fa5a6Sopenharmony_ci{
509c29fa5a6Sopenharmony_ci    CALL_DEBUG_ENTER;
510c29fa5a6Sopenharmony_ci    if (filePath.empty()) {
511c29fa5a6Sopenharmony_ci        MMI_HILOGE("FilePath is empty");
512c29fa5a6Sopenharmony_ci        return RET_ERR;
513c29fa5a6Sopenharmony_ci    }
514c29fa5a6Sopenharmony_ci    if (!IsFileExists(filePath)) {
515c29fa5a6Sopenharmony_ci        MMI_HILOGE("File is not existent");
516c29fa5a6Sopenharmony_ci        return RET_ERR;
517c29fa5a6Sopenharmony_ci    }
518c29fa5a6Sopenharmony_ci    char realPath[PATH_MAX] = {};
519c29fa5a6Sopenharmony_ci    CHKPR(realpath(filePath.c_str(), realPath), RET_ERR);
520c29fa5a6Sopenharmony_ci    int32_t fileSize = GetFileSize(realPath);
521c29fa5a6Sopenharmony_ci    if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
522c29fa5a6Sopenharmony_ci        MMI_HILOGE("File size out of read range");
523c29fa5a6Sopenharmony_ci        return RET_ERR;
524c29fa5a6Sopenharmony_ci    }
525c29fa5a6Sopenharmony_ci    return RET_OK;
526c29fa5a6Sopenharmony_ci}
527c29fa5a6Sopenharmony_ci
528c29fa5a6Sopenharmony_cistd::string StringPrintf(const char *format, ...)
529c29fa5a6Sopenharmony_ci{
530c29fa5a6Sopenharmony_ci    char space[1024];
531c29fa5a6Sopenharmony_ci
532c29fa5a6Sopenharmony_ci    va_list ap;
533c29fa5a6Sopenharmony_ci    va_start(ap, format);
534c29fa5a6Sopenharmony_ci    std::string result;
535c29fa5a6Sopenharmony_ci    int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
536c29fa5a6Sopenharmony_ci    if (ret >= RET_OK && (size_t)ret < sizeof(space)) {
537c29fa5a6Sopenharmony_ci        result = space;
538c29fa5a6Sopenharmony_ci    } else {
539c29fa5a6Sopenharmony_ci        MMI_HILOGE("The buffer is overflow");
540c29fa5a6Sopenharmony_ci    }
541c29fa5a6Sopenharmony_ci    va_end(ap);
542c29fa5a6Sopenharmony_ci    return result;
543c29fa5a6Sopenharmony_ci}
544c29fa5a6Sopenharmony_ci
545c29fa5a6Sopenharmony_cistd::string FileVerification(std::string &filePath, const std::string &checkExtension)
546c29fa5a6Sopenharmony_ci{
547c29fa5a6Sopenharmony_ci    if (filePath.empty()) {
548c29fa5a6Sopenharmony_ci        MMI_HILOGE("FilePath is empty");
549c29fa5a6Sopenharmony_ci        return "";
550c29fa5a6Sopenharmony_ci    }
551c29fa5a6Sopenharmony_ci    char realPath[PATH_MAX] = {};
552c29fa5a6Sopenharmony_ci    CHKPS(realpath(filePath.c_str(), realPath));
553c29fa5a6Sopenharmony_ci    if (!IsFileExists(realPath)) {
554c29fa5a6Sopenharmony_ci        MMI_HILOGE("File is not existent");
555c29fa5a6Sopenharmony_ci        return "";
556c29fa5a6Sopenharmony_ci    }
557c29fa5a6Sopenharmony_ci    if (!CheckFileExtendName(realPath, checkExtension)) {
558c29fa5a6Sopenharmony_ci        MMI_HILOGE("Unable to parse files other than json format");
559c29fa5a6Sopenharmony_ci        return "";
560c29fa5a6Sopenharmony_ci    }
561c29fa5a6Sopenharmony_ci    int32_t fileSize = GetFileSize(realPath);
562c29fa5a6Sopenharmony_ci    if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
563c29fa5a6Sopenharmony_ci        MMI_HILOGE("File size out of read range");
564c29fa5a6Sopenharmony_ci        return "";
565c29fa5a6Sopenharmony_ci    }
566c29fa5a6Sopenharmony_ci    return realPath;
567c29fa5a6Sopenharmony_ci}
568c29fa5a6Sopenharmony_ci
569c29fa5a6Sopenharmony_ci
570c29fa5a6Sopenharmony_cibool Aggregator::Record(const LogHeader &lh, const std::string &key, const std::string &record)
571c29fa5a6Sopenharmony_ci{
572c29fa5a6Sopenharmony_ci    constexpr int32_t oneSecond = 1000;
573c29fa5a6Sopenharmony_ci    if (timerId_ != -1) {
574c29fa5a6Sopenharmony_ci        resetTimer_(timerId_);
575c29fa5a6Sopenharmony_ci    } else {
576c29fa5a6Sopenharmony_ci        timerId_ = addTimer_(oneSecond, 1, [this, lh]() {
577c29fa5a6Sopenharmony_ci            FlushRecords(lh);
578c29fa5a6Sopenharmony_ci            timerId_ = -1;
579c29fa5a6Sopenharmony_ci        });
580c29fa5a6Sopenharmony_ci    }
581c29fa5a6Sopenharmony_ci    if (key == key_) {
582c29fa5a6Sopenharmony_ci        auto now = std::chrono::system_clock::now();
583c29fa5a6Sopenharmony_ci        records_.push_back({record, now});
584c29fa5a6Sopenharmony_ci        if (records_.size() >= maxRecordCount_) {
585c29fa5a6Sopenharmony_ci            FlushRecords(lh);
586c29fa5a6Sopenharmony_ci        }
587c29fa5a6Sopenharmony_ci        return true;
588c29fa5a6Sopenharmony_ci    } else {
589c29fa5a6Sopenharmony_ci        FlushRecords(lh, key, record);
590c29fa5a6Sopenharmony_ci        key_ = key;
591c29fa5a6Sopenharmony_ci        return false;
592c29fa5a6Sopenharmony_ci    }
593c29fa5a6Sopenharmony_ci}
594c29fa5a6Sopenharmony_ci
595c29fa5a6Sopenharmony_civoid Aggregator::FlushRecords(const LogHeader &lh, const std::string &key, const std::string &extraRecord)
596c29fa5a6Sopenharmony_ci{
597c29fa5a6Sopenharmony_ci    constexpr uint32_t milliSecondWidth = 3;
598c29fa5a6Sopenharmony_ci    constexpr uint32_t microToMilli = 1000;
599c29fa5a6Sopenharmony_ci    size_t recordCount = records_.size();
600c29fa5a6Sopenharmony_ci    std::ostringstream oss;
601c29fa5a6Sopenharmony_ci    if (!records_.empty()) {
602c29fa5a6Sopenharmony_ci        oss << key_;
603c29fa5a6Sopenharmony_ci        oss << ", first: " << records_.front().record << "-(";
604c29fa5a6Sopenharmony_ci        auto firstTime = records_.front().timestamp;
605c29fa5a6Sopenharmony_ci        time_t firstTimeT = std::chrono::system_clock::to_time_t(firstTime);
606c29fa5a6Sopenharmony_ci        std::tm *bt = std::localtime(&firstTimeT);
607c29fa5a6Sopenharmony_ci        if (bt == nullptr) {
608c29fa5a6Sopenharmony_ci            MMI_HILOGE("bt is nullptr, this is a invalid time");
609c29fa5a6Sopenharmony_ci            return;
610c29fa5a6Sopenharmony_ci        }
611c29fa5a6Sopenharmony_ci        oss << std::put_time(bt, "%Y-%m-%d %H:%M:%S");
612c29fa5a6Sopenharmony_ci        auto since_epoch = firstTime.time_since_epoch();
613c29fa5a6Sopenharmony_ci        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch).count() % microToMilli;
614c29fa5a6Sopenharmony_ci        oss << '.' << std::setfill('0') << std::setw(milliSecondWidth) << millis << "ms)";
615c29fa5a6Sopenharmony_ci
616c29fa5a6Sopenharmony_ci        if (records_.size() > 1) {
617c29fa5a6Sopenharmony_ci            size_t i = records_.size() - 1;
618c29fa5a6Sopenharmony_ci            const auto &recordInfo = records_[i];
619c29fa5a6Sopenharmony_ci            oss << ", " << recordInfo.record;
620c29fa5a6Sopenharmony_ci        }
621c29fa5a6Sopenharmony_ci        records_.clear();
622c29fa5a6Sopenharmony_ci        oss << ", count: " << recordCount;
623c29fa5a6Sopenharmony_ci    }
624c29fa5a6Sopenharmony_ci    if (!extraRecord.empty()) {
625c29fa5a6Sopenharmony_ci        if (!oss.str().empty()) {
626c29fa5a6Sopenharmony_ci            oss << ", last: ";
627c29fa5a6Sopenharmony_ci        }
628c29fa5a6Sopenharmony_ci        oss << key << ": " << extraRecord;
629c29fa5a6Sopenharmony_ci    }
630c29fa5a6Sopenharmony_ci    if (!oss.str().empty()) {
631c29fa5a6Sopenharmony_ci        MMI_HILOG_HEADER(LOG_INFO, lh, "%{public}s", oss.str().c_str());
632c29fa5a6Sopenharmony_ci    }
633c29fa5a6Sopenharmony_ci}
634c29fa5a6Sopenharmony_ci
635c29fa5a6Sopenharmony_ciAggregator::~Aggregator()
636c29fa5a6Sopenharmony_ci{
637c29fa5a6Sopenharmony_ci    FlushRecords(MMI_LOG_HEADER);
638c29fa5a6Sopenharmony_ci}
639c29fa5a6Sopenharmony_ci
640c29fa5a6Sopenharmony_ci} // namespace MMI
641c29fa5a6Sopenharmony_ci} // namespace OHOS
642