1 /*
2  * Copyright (c) 2022-2024 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 
16 #include "dinput_utils_tool.h"
17 
18 #include <algorithm>
19 #include <climits>
20 #include <cstdarg>
21 #include <cstdio>
22 #include <random>
23 
24 #include <dirent.h>
25 #include <fcntl.h>
26 #include <sys/time.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <openssl/sha.h>
31 
32 #include "nlohmann/json.hpp"
33 #include "securec.h"
34 
35 #include "softbus_bus_center.h"
36 
37 #include "constants_dinput.h"
38 #include "dinput_errcode.h"
39 #include "dinput_softbus_define.h"
40 
41 namespace OHOS {
42 namespace DistributedHardware {
43 namespace DistributedInput {
44 namespace {
45     constexpr int32_t HEX_TO_UINT8 = 2;
46     constexpr size_t INT32_SHORT_ID_LENGTH = 20;
47     constexpr size_t INT32_PLAINTEXT_LENGTH = 4;
48     constexpr size_t INT32_MIN_ID_LENGTH = 3;
49     constexpr int32_t WIDTH = 4;
50     constexpr unsigned char MASK = 0x0F;
51     constexpr int32_t DOUBLE_TIMES = 2;
52     constexpr int32_t INT32_STRING_LENGTH = 40;
53     constexpr uint32_t ERROR_MSG_MAX_LEN = 256;
54     constexpr int32_t MAX_RETRY_COUNT = 3;
55     constexpr uint32_t SLEEP_TIME_US = 10 * 1000;
56     constexpr char DHID_SPLIT = '.';
57 }
GetLocalDeviceInfo()58 DevInfo GetLocalDeviceInfo()
59 {
60     DevInfo devInfo{"", "", 0};
61     auto info = std::make_unique<NodeBasicInfo>();
62     auto ret = GetLocalNodeDeviceInfo(DINPUT_PKG_NAME.c_str(), info.get());
63     if (ret != 0) {
64         DHLOGE("GetLocalNodeDeviceInfo failed, errCode = %{public}d", ret);
65         return devInfo;
66     }
67 
68     devInfo.networkId = info->networkId;
69     devInfo.deviceName = info->deviceName;
70     devInfo.deviceType = info->deviceTypeId;
71 
72     return devInfo;
73 }
74 
GetLocalNetworkId()75 std::string GetLocalNetworkId()
76 {
77     std::string localNetworkId = GetLocalDeviceInfo().networkId;
78     if (localNetworkId.empty()) {
79         DHLOGE("local networkId is empty!");
80     }
81     DHLOGI("GetLocalNetworkId, device local networkId is %{public}s", GetAnonyString(localNetworkId).c_str());
82     return localNetworkId;
83 }
84 
GetUUIDBySoftBus(const std::string & networkId)85 std::string GetUUIDBySoftBus(const std::string &networkId)
86 {
87     if (networkId.empty()) {
88         return "";
89     }
90     char uuid[UUID_BUF_LEN] = {0};
91     auto ret = GetNodeKeyInfo(DINPUT_PKG_NAME.c_str(), networkId.c_str(), NodeDeviceInfoKey::NODE_KEY_UUID,
92         reinterpret_cast<uint8_t *>(uuid), UUID_BUF_LEN);
93     return (ret == DH_SUCCESS) ? std::string(uuid) : "";
94 }
95 
GetCurrentTimeUs()96 uint64_t GetCurrentTimeUs()
97 {
98     constexpr int32_t usOneSecond = 1000 * 1000;
99     struct timeval tv;
100     gettimeofday(&tv, nullptr);
101     return tv.tv_sec * usOneSecond + tv.tv_usec;
102 }
103 
SetAnonyId(const std::string & message)104 std::string SetAnonyId(const std::string &message)
105 {
106     nlohmann::json jsonObj = nlohmann::json::parse(message, nullptr, false);
107     if (jsonObj.is_discarded()) {
108         DHLOGE("jsonObj parse failed!");
109         return "";
110     }
111     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_DEVICE_ID)) {
112         jsonObj[DINPUT_SOFTBUS_KEY_DEVICE_ID] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_DEVICE_ID]);
113     }
114     if (IsString(jsonObj, DESCRIPTOR)) {
115         jsonObj[DESCRIPTOR] = GetAnonyString(jsonObj[DESCRIPTOR]);
116     }
117     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_INPUT_DATA)) {
118         jsonObj[DINPUT_SOFTBUS_KEY_INPUT_DATA] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_INPUT_DATA]);
119     }
120     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_VECTOR_DHID)) {
121         std::string dhidStr = jsonObj[DINPUT_SOFTBUS_KEY_VECTOR_DHID];
122         dhidStr.append(".");
123         size_t pos = dhidStr.find(".");
124         std::string anonyDhidStr = "";
125         while (pos != dhidStr.npos) {
126             anonyDhidStr += GetAnonyString(dhidStr.substr(0, pos)) + ".";
127             dhidStr = dhidStr.substr(pos + 1, dhidStr.size());
128             pos = dhidStr.find(".");
129         }
130         if (anonyDhidStr.length() >= 1) {
131             jsonObj[DINPUT_SOFTBUS_KEY_VECTOR_DHID] = anonyDhidStr.substr(0, anonyDhidStr.length() - 1);
132         }
133     }
134     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_SRC_DEV_ID)) {
135         jsonObj[DINPUT_SOFTBUS_KEY_SRC_DEV_ID] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_SRC_DEV_ID]);
136     }
137     if (IsString(jsonObj, DINPUT_SOFTBUS_KEY_SINK_DEV_ID)) {
138         jsonObj[DINPUT_SOFTBUS_KEY_SINK_DEV_ID] = GetAnonyString(jsonObj[DINPUT_SOFTBUS_KEY_SINK_DEV_ID]);
139     }
140     return jsonObj.dump();
141 }
142 
IsBoolean(const nlohmann::json & jsonObj,const std::string & key)143 bool IsBoolean(const nlohmann::json &jsonObj, const std::string &key)
144 {
145     return jsonObj.contains(key) && jsonObj[key].is_boolean();
146 }
147 
IsString(const nlohmann::json & jsonObj,const std::string & key)148 bool IsString(const nlohmann::json &jsonObj, const std::string &key)
149 {
150     return jsonObj.contains(key) && jsonObj[key].is_string();
151 }
152 
IsInt32(const nlohmann::json & jsonObj,const std::string & key)153 bool IsInt32(const nlohmann::json &jsonObj, const std::string &key)
154 {
155     return jsonObj.contains(key) && jsonObj[key].is_number_integer() && INT32_MIN <= jsonObj[key] &&
156         jsonObj[key] <= INT32_MAX;
157 }
158 
IsInt64(const nlohmann::json & jsonObj,const std::string & key)159 bool IsInt64(const nlohmann::json &jsonObj, const std::string &key)
160 {
161     return jsonObj.contains(key) && jsonObj[key].is_number_integer() && INT64_MIN <= jsonObj[key] &&
162         jsonObj[key] <= INT64_MAX;
163 }
164 
IsUInt16(const nlohmann::json & jsonObj,const std::string & key)165 bool IsUInt16(const nlohmann::json &jsonObj, const std::string &key)
166 {
167     return jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] <= UINT16_MAX;
168 }
169 
IsUInt32(const nlohmann::json & jsonObj,const std::string & key)170 bool IsUInt32(const nlohmann::json &jsonObj, const std::string &key)
171 {
172     return jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] <= UINT32_MAX;
173 }
174 
IsUInt64(const nlohmann::json & jsonObj,const std::string & key)175 bool IsUInt64(const nlohmann::json &jsonObj, const std::string &key)
176 {
177     return jsonObj.contains(key) && jsonObj[key].is_number_unsigned() && jsonObj[key] <= UINT64_MAX;
178 }
179 
IsArray(const nlohmann::json & jsonObj,const std::string & key)180 bool IsArray(const nlohmann::json &jsonObj, const std::string &key)
181 {
182     return jsonObj.contains(key) && jsonObj[key].is_array();
183 }
184 
GetNodeDesc(std::string parameters)185 std::string GetNodeDesc(std::string parameters)
186 {
187     nlohmann::json parObj = nlohmann::json::parse(parameters, nullptr, false);
188     if (parObj.is_discarded()) {
189         DHLOGE("parObj parse failed!");
190         return "";
191     }
192     std::string nodeName = "N/A";
193     std::string physicalPath = "N/A";
194     int32_t classes = -1;
195 
196     if (IsString(parObj, DEVICE_NAME) && IsString(parObj, PHYSICAL_PATH) && IsInt32(parObj, CLASSES)) {
197         nodeName = parObj.at(DEVICE_NAME).get<std::string>();
198         physicalPath = parObj.at(PHYSICAL_PATH).get<std::string>();
199         classes = parObj.at(CLASSES).get<int32_t>();
200     }
201 
202     return "{ nodeName: " + nodeName + ", physicalPath: " + physicalPath + ", classes: " +
203         std::to_string(classes) + " }";
204 }
205 
GetAnonyString(const std::string & value)206 std::string GetAnonyString(const std::string &value)
207 {
208     std::string res;
209     std::string tmpStr("******");
210     size_t strLen = value.length();
211     if (strLen < INT32_MIN_ID_LENGTH) {
212         return tmpStr;
213     }
214 
215     if (strLen <= INT32_SHORT_ID_LENGTH) {
216         res += value[0];
217         res += tmpStr;
218         res += value[strLen - 1];
219     } else {
220         res.append(value, 0, INT32_PLAINTEXT_LENGTH);
221         res += tmpStr;
222         res.append(value, strLen - INT32_PLAINTEXT_LENGTH, INT32_PLAINTEXT_LENGTH);
223     }
224 
225     return res;
226 }
227 
GetAnonyInt32(const int32_t value)228 std::string GetAnonyInt32(const int32_t value)
229 {
230     char tempBuffer[INT32_STRING_LENGTH] = "";
231     int32_t secRet = sprintf_s(tempBuffer, INT32_STRING_LENGTH, "%d", value);
232     if (secRet <= 0) {
233         std::string nullString("");
234         return nullString;
235     }
236     size_t length = strlen(tempBuffer);
237     if (length < 1) {
238         DHLOGE("tempBuffer length error.");
239         return "";
240     }
241     for (size_t i = 1; i <= length - 1; i++) {
242         tempBuffer[i] = '*';
243     }
244     if (length == 0x01) {
245         tempBuffer[0] = '*';
246     }
247 
248     std::string tempString(tempBuffer);
249     return tempString;
250 }
251 
Sha256(const std::string & in)252 std::string Sha256(const std::string &in)
253 {
254     unsigned char out[SHA256_DIGEST_LENGTH * HEX_TO_UINT8 + 1] = {0};
255     SHA256_CTX ctx;
256     SHA256_Init(&ctx);
257     SHA256_Update(&ctx, in.data(), in.size());
258     SHA256_Final(&out[SHA256_DIGEST_LENGTH], &ctx);
259     // here we translate sha256 hash to hexadecimal. each 8-bit char will be presented by two characters([0-9a-f])
260     const char* hexCode = "0123456789abcdef";
261     for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
262         unsigned char value = out[SHA256_DIGEST_LENGTH + i];
263         // uint8_t is 2 digits in hexadecimal.
264         out[i * DOUBLE_TIMES] = hexCode[(value >> WIDTH) & MASK];
265         out[i * DOUBLE_TIMES + 1] = hexCode[value & MASK];
266     }
267     out[SHA256_DIGEST_LENGTH * DOUBLE_TIMES] = 0;
268     return reinterpret_cast<char*>(out);
269 }
270 
CloseFd(int & fd)271 void CloseFd(int &fd)
272 {
273     if (fd < 0) {
274         DHLOGE("No fd need to beclosed.");
275         return;
276     }
277     close(fd);
278     fd = UN_INIT_FD_VALUE;
279 }
280 
BitIsSet(const unsigned long * array,int bit)281 int BitIsSet(const unsigned long *array, int bit)
282 {
283     return !!(array[bit / LONG_BITS] & (1LL << (bit % LONG_BITS)));
284 }
285 
SplitStringToVector(const std::string & str,const char split,std::vector<std::string> & vecStr)286 void SplitStringToVector(const std::string &str, const char split, std::vector<std::string> &vecStr)
287 {
288     if (str.empty()) {
289         DHLOGE("SplitStringToVector param str is error.");
290         return;
291     }
292     std::string strTmp = str + split;
293     size_t pos = strTmp.find(split);
294     while (pos != strTmp.npos) {
295         std::string matchTmp = strTmp.substr(0, pos);
296         vecStr.push_back(matchTmp);
297         strTmp = strTmp.substr(pos + 1, strTmp.size());
298         pos = strTmp.find(split);
299     }
300 }
301 
OpenInputDeviceFdByPath(const std::string & devicePath)302 int OpenInputDeviceFdByPath(const std::string &devicePath)
303 {
304     chmod(devicePath.c_str(), S_IWRITE | S_IREAD);
305     char canonicalDevicePath[PATH_MAX] = {0x00};
306     if (devicePath.length() == 0 || devicePath.length() >= PATH_MAX ||
307         realpath(devicePath.c_str(), canonicalDevicePath) == nullptr) {
308         DHLOGE("path check fail, error path: %{public}s", devicePath.c_str());
309         return -1;
310     }
311     struct stat s;
312     if ((stat(canonicalDevicePath, &s) == 0) && (s.st_mode & S_IFDIR)) {
313         DHLOGI("path: %{public}s is a dir.", devicePath.c_str());
314         return -1;
315     }
316     int fd = open(canonicalDevicePath, O_RDWR | O_CLOEXEC);
317     int32_t count = 0;
318     while ((fd < 0) && (count < MAX_RETRY_COUNT)) {
319         ++count;
320         usleep(SLEEP_TIME_US);
321         fd = open(canonicalDevicePath, O_RDWR | O_CLOEXEC);
322         DHLOGE("could not open the path: %{public}s, errno: %{public}s; retry: %{public}d", devicePath.c_str(),
323             ConvertErrNo().c_str(), count);
324     }
325     if (count >= MAX_RETRY_COUNT) {
326         DHLOGE("could not open the path: %{public}s, errno: %{public}s.", devicePath.c_str(), ConvertErrNo().c_str());
327         CloseFd(fd);
328         return -1;
329     }
330     return fd;
331 }
332 
ConvertErrNo()333 std::string ConvertErrNo()
334 {
335     char errMsg[ERROR_MSG_MAX_LEN] = {0};
336     strerror_r(errno, errMsg, ERROR_MSG_MAX_LEN);
337     std::string errNoMsg(errMsg);
338     return errNoMsg;
339 }
340 
ScanInputDevicesPath(const std::string & dirName,std::vector<std::string> & vecInputDevPath)341 void ScanInputDevicesPath(const std::string &dirName, std::vector<std::string> &vecInputDevPath)
342 {
343     DIR *dir;
344     struct dirent *de;
345     dir = opendir(dirName.c_str());
346     if (dir == nullptr) {
347         DHLOGE("error opendir /dev/input :%{public}s\n", ConvertErrNo().c_str());
348         return;
349     }
350     size_t dirNameFirstPos = 0;
351     size_t dirNameSecondPos = 1;
352     size_t dirNameThirdPos = 2;
353     while ((de = readdir(dir))) {
354         if (de->d_name[dirNameFirstPos] == '.' && (de->d_name[dirNameSecondPos] == '\0' ||
355             (de->d_name[dirNameSecondPos] == '.' && de->d_name[dirNameThirdPos] == '\0'))) {
356             continue;
357         }
358         std::string tmpDevName = dirName + "/" + std::string(de->d_name);
359         vecInputDevPath.push_back(tmpDevName);
360     }
361     closedir(dir);
362 }
363 
RecordEventLog(const input_event & event)364 void RecordEventLog(const input_event &event)
365 {
366     std::string eventType = "";
367     switch (event.type) {
368         case EV_KEY:
369             eventType = "EV_KEY";
370             break;
371         case EV_SYN:
372             eventType = "EV_SYN";
373             break;
374         default:
375             eventType = "other type " + std::to_string(event.type);
376             break;
377     }
378     DHLOGD("5.E2E-Test Source write event into input driver, EventType: %{public}s, Code: %{public}d, "
379         "Value: %{public}d", eventType.c_str(), event.code, event.value);
380 }
381 
WriteEventToDevice(const int fd,const input_event & event)382 void WriteEventToDevice(const int fd, const input_event &event)
383 {
384     if (write(fd, &event, sizeof(event)) < static_cast<ssize_t>(sizeof(event))) {
385         DHLOGE("could not inject event, fd: %{public}d", fd);
386         return;
387     }
388     RecordEventLog(event);
389 }
390 
ResetVirtualDevicePressedKeys(const std::vector<std::string> & nodePaths)391 void ResetVirtualDevicePressedKeys(const std::vector<std::string> &nodePaths)
392 {
393     unsigned long keyState[NLONGS(KEY_CNT)] = { 0 };
394     for (const auto &path : nodePaths) {
395         DHLOGI("Check and reset key state, path: %{public}s", path.c_str());
396         std::vector<uint32_t> pressedKeys;
397         int fd = OpenInputDeviceFdByPath(path);
398         if (fd == -1) {
399             DHLOGE("Open virtual keyboard node failed, path: %{public}s", path.c_str());
400             continue;
401         }
402 
403         int rc = ioctl(fd, EVIOCGKEY(sizeof(keyState)), keyState);
404         if (rc < 0) {
405             DHLOGE("Read all key state failed, rc: %{public}d, path: %{public}s", rc, path.c_str());
406             CloseFd(fd);
407             continue;
408         }
409 
410         for (int32_t keyIndex = 0; keyIndex < KEY_MAX; keyIndex++) {
411             if (BitIsSet(keyState, keyIndex)) {
412                 DHLOGI("key index: %{public}d pressed.", keyIndex);
413                 pressedKeys.push_back(keyIndex);
414             }
415         }
416 
417         if (pressedKeys.empty()) {
418             CloseFd(fd);
419             continue;
420         }
421 
422         struct input_event event = {
423             .type = EV_KEY,
424             .code = 0,
425             .value = KEY_UP_STATE
426         };
427         for (auto &code : pressedKeys) {
428             event.type = EV_KEY;
429             event.code = code;
430             WriteEventToDevice(fd, event);
431             event.type = EV_SYN;
432             event.code = 0;
433             WriteEventToDevice(fd, event);
434         }
435         CloseFd(fd);
436     }
437 }
438 
GetString(const std::vector<std::string> & vec)439 std::string GetString(const std::vector<std::string> &vec)
440 {
441     std::string retStr = "[";
442     if (vec.size() < 1) {
443         DHLOGE("vec size error.");
444         return "";
445     }
446     for (uint32_t i = 0; i < vec.size(); i++) {
447         if (i != (vec.size() - 1)) {
448             retStr += vec[i] + ", ";
449         } else {
450             retStr += vec[i];
451         }
452     }
453     retStr += "]";
454     return retStr;
455 }
456 
GetRandomInt32(int32_t randMin,int32_t randMax)457 int32_t GetRandomInt32(int32_t randMin, int32_t randMax)
458 {
459     std::default_random_engine engine(time(nullptr));
460 
461     std::uniform_int_distribution<int> distribution(randMin, randMax);
462     return distribution(engine);
463 }
464 
JointDhIds(const std::vector<std::string> & dhids)465 std::string JointDhIds(const std::vector<std::string> &dhids)
466 {
467     if (dhids.size() == 0) {
468         return "";
469     }
470     auto dotFold = [](std::string a, std::string b) {return std::move(a) + DHID_SPLIT + std::move(b);};
471     return std::accumulate(std::next(dhids.begin()), dhids.end(), dhids[0], dotFold);
472 }
473 
SplitDhIdString(const std::string & dhIdsString)474 std::vector<std::string> SplitDhIdString(const std::string &dhIdsString)
475 {
476     std::vector<std::string> dhIdsVec;
477     SplitStringToVector(dhIdsString, DHID_SPLIT, dhIdsVec);
478     return dhIdsVec;
479 }
480 } // namespace DistributedInput
481 } // namespace DistributedHardware
482 } // namespace OHOS