1 /*
2  * Copyright (c) 2021-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 "distributed_input_node_manager.h"
17 
18 #include <cinttypes>
19 #include <cstring>
20 
21 #include <pthread.h>
22 
23 #include "softbus_bus_center.h"
24 
25 #include "dinput_context.h"
26 #include "dinput_errcode.h"
27 #include "dinput_log.h"
28 #include "dinput_softbus_define.h"
29 #include "dinput_utils_tool.h"
30 
31 namespace OHOS {
32 namespace DistributedHardware {
33 namespace DistributedInput {
34 namespace {
35     constexpr int32_t RETRY_MAX_TIMES = 3;
36     constexpr uint32_t SLEEP_TIME_US = 10 * 1000;
37 }
DistributedInputNodeManager()38 DistributedInputNodeManager::DistributedInputNodeManager() : isInjectThreadCreated_(false),
39     isInjectThreadRunning_(false), virtualTouchScreenFd_(UN_INIT_FD_VALUE)
40 {
41     DHLOGI("DistributedInputNodeManager ctor");
42     std::shared_ptr<AppExecFwk::EventRunner> runner = AppExecFwk::EventRunner::Create(true);
43     callBackHandler_ = std::make_shared<DistributedInputNodeManager::DInputNodeManagerEventHandler>(runner, this);
44 }
45 
~DistributedInputNodeManager()46 DistributedInputNodeManager::~DistributedInputNodeManager()
47 {
48     DHLOGI("DistributedInputNodeManager dtor");
49     isInjectThreadCreated_.store(false);
50     isInjectThreadRunning_.store(false);
51     if (eventInjectThread_.joinable()) {
52         eventInjectThread_.join();
53     }
54     {
55         std::lock_guard<std::mutex> lock(virtualDeviceMapMutex_);
56         virtualDeviceMap_.clear();
57     }
58     DHLOGI("destructor end");
59 }
60 
OpenDevicesNode(const std::string & devId,const std::string & dhId,const std::string & parameters)61 int32_t DistributedInputNodeManager::OpenDevicesNode(const std::string &devId, const std::string &dhId,
62     const std::string &parameters)
63 {
64     if (devId.size() > DEV_ID_LENGTH_MAX || devId.empty() || dhId.size() > DH_ID_LENGTH_MAX || dhId.empty() ||
65         parameters.size() > STRING_MAX_SIZE || parameters.empty()) {
66         DHLOGE("Params is invalid!");
67         return ERR_DH_INPUT_SERVER_SOURCE_OPEN_DEVICE_NODE_FAIL;
68     }
69     InputDevice event;
70     ParseInputDeviceJson(parameters, event);
71     if (CreateHandle(event, devId, dhId) < 0) {
72         DHLOGE("Can not create virtual node!");
73         return ERR_DH_INPUT_SERVER_SOURCE_OPEN_DEVICE_NODE_FAIL;
74     }
75     return DH_SUCCESS;
76 }
77 
ParseInputDeviceJson(const std::string & str,InputDevice & pBuf)78 void DistributedInputNodeManager::ParseInputDeviceJson(const std::string &str, InputDevice &pBuf)
79 {
80     nlohmann::json inputDeviceJson = nlohmann::json::parse(str, nullptr, false);
81     if (inputDeviceJson.is_discarded()) {
82         DHLOGE("recMsg parse failed!");
83         return;
84     }
85     ParseInputDevice(inputDeviceJson, pBuf);
86 }
87 
ParseInputDevice(const nlohmann::json & inputDeviceJson,InputDevice & pBuf)88 void DistributedInputNodeManager::ParseInputDevice(const nlohmann::json &inputDeviceJson, InputDevice &pBuf)
89 {
90     ParseInputDeviceBasicInfo(inputDeviceJson, pBuf);
91     ParseInputDeviceEvents(inputDeviceJson, pBuf);
92 }
93 
ParseInputDeviceBasicInfo(const nlohmann::json & inputDeviceJson,InputDevice & pBuf)94 void DistributedInputNodeManager::ParseInputDeviceBasicInfo(const nlohmann::json &inputDeviceJson, InputDevice &pBuf)
95 {
96     if (IsString(inputDeviceJson, DEVICE_NAME)) {
97         pBuf.name = inputDeviceJson[DEVICE_NAME].get<std::string>();
98     }
99     if (IsString(inputDeviceJson, PHYSICAL_PATH)) {
100         pBuf.physicalPath = inputDeviceJson[PHYSICAL_PATH].get<std::string>();
101     }
102     if (IsString(inputDeviceJson, UNIQUE_ID)) {
103         pBuf.uniqueId = inputDeviceJson[UNIQUE_ID].get<std::string>();
104     }
105     if (IsUInt16(inputDeviceJson, BUS)) {
106         pBuf.bus = inputDeviceJson[BUS].get<uint16_t>();
107     }
108     if (IsUInt16(inputDeviceJson, VENDOR)) {
109         pBuf.vendor = inputDeviceJson[VENDOR].get<uint16_t>();
110     }
111     if (IsUInt16(inputDeviceJson, PRODUCT)) {
112         pBuf.product = inputDeviceJson[PRODUCT].get<uint16_t>();
113     }
114     if (IsUInt16(inputDeviceJson, VERSION)) {
115         pBuf.version = inputDeviceJson[VERSION].get<uint16_t>();
116     }
117     if (IsString(inputDeviceJson, DESCRIPTOR)) {
118         pBuf.descriptor = inputDeviceJson[DESCRIPTOR].get<std::string>();
119     }
120     if (IsUInt32(inputDeviceJson, CLASSES)) {
121         pBuf.classes = inputDeviceJson[CLASSES].get<uint32_t>();
122     }
123 }
124 
ParseInputDeviceEvents(const nlohmann::json & inputDeviceJson,InputDevice & pBuf)125 void DistributedInputNodeManager::ParseInputDeviceEvents(const nlohmann::json &inputDeviceJson, InputDevice &pBuf)
126 {
127     if (IsArray(inputDeviceJson, EVENT_TYPES)) {
128         pBuf.eventTypes = inputDeviceJson[EVENT_TYPES].get<std::vector<uint32_t>>();
129     }
130     if (IsArray(inputDeviceJson, EVENT_KEYS)) {
131         pBuf.eventKeys = inputDeviceJson[EVENT_KEYS].get<std::vector<uint32_t>>();
132     }
133     if (IsArray(inputDeviceJson, ABS_TYPES)) {
134         pBuf.absTypes = inputDeviceJson[ABS_TYPES].get<std::vector<uint32_t>>();
135     }
136     if (IsArray(inputDeviceJson, ABS_INFOS)) {
137         pBuf.absInfos = inputDeviceJson[ABS_INFOS].get<std::map<uint32_t, std::vector<int32_t>>>();
138     }
139     if (IsArray(inputDeviceJson, REL_TYPES)) {
140         pBuf.relTypes = inputDeviceJson[REL_TYPES].get<std::vector<uint32_t>>();
141     }
142     if (IsArray(inputDeviceJson, PROPERTIES)) {
143         pBuf.properties = inputDeviceJson[PROPERTIES].get<std::vector<uint32_t>>();
144     }
145     if (IsArray(inputDeviceJson, MISCELLANEOUS)) {
146         pBuf.miscellaneous = inputDeviceJson[MISCELLANEOUS].get<std::vector<uint32_t>>();
147     }
148     if (IsArray(inputDeviceJson, LEDS)) {
149         pBuf.leds = inputDeviceJson[LEDS].get<std::vector<uint32_t>>();
150     }
151     if (IsArray(inputDeviceJson, REPEATS)) {
152         pBuf.repeats = inputDeviceJson[REPEATS].get<std::vector<uint32_t>>();
153     }
154     if (IsArray(inputDeviceJson, SWITCHS)) {
155         pBuf.switchs = inputDeviceJson[SWITCHS].get<std::vector<uint32_t>>();
156     }
157 }
158 
ScanSinkInputDevices(const std::string & devId,const std::string & dhId)159 void DistributedInputNodeManager::ScanSinkInputDevices(const std::string &devId, const std::string &dhId)
160 {
161     DHLOGI("ScanSinkInputDevices enter, deviceId: %{public}s, dhId: %{public}s.",
162         GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
163     std::vector<std::string> vecInputDevPath;
164     ScanInputDevicesPath(DEVICE_PATH, vecInputDevPath);
165     for (auto &tempPath: vecInputDevPath) {
166         if (MatchAndSavePhysicalPath(tempPath, devId, dhId)) {
167             DHLOGI("Set physical path success");
168             break;
169         }
170     }
171 }
172 
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)173 void DistributedInputNodeManager::DInputNodeManagerEventHandler::ProcessEvent(
174     const AppExecFwk::InnerEvent::Pointer &event)
175 {
176     DHLOGI("ProcessEvent enter.");
177     auto iter = eventFuncMap_.find(event->GetInnerEventId());
178     if (iter == eventFuncMap_.end()) {
179         DHLOGE("Event Id %{public}d is undefined.", event->GetInnerEventId());
180         return;
181     }
182     nodeMgrFunc &func = iter->second;
183     (this->*func)(event);
184 }
185 
DInputNodeManagerEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,DistributedInputNodeManager * manager)186 DistributedInputNodeManager::DInputNodeManagerEventHandler::DInputNodeManagerEventHandler(
187     const std::shared_ptr<AppExecFwk::EventRunner> &runner, DistributedInputNodeManager *manager)
188     : AppExecFwk::EventHandler(runner)
189 {
190     eventFuncMap_[DINPUT_NODE_MANAGER_SCAN_ALL_NODE] = &DInputNodeManagerEventHandler::ScanAllNode;
191 
192     nodeManagerObj_ = manager;
193 }
194 
~DInputNodeManagerEventHandler()195 DistributedInputNodeManager::DInputNodeManagerEventHandler::~DInputNodeManagerEventHandler()
196 {
197     eventFuncMap_.clear();
198     nodeManagerObj_ = nullptr;
199 }
200 
ScanAllNode(const AppExecFwk::InnerEvent::Pointer & event)201 void DistributedInputNodeManager::DInputNodeManagerEventHandler::ScanAllNode(
202     const AppExecFwk::InnerEvent::Pointer &event)
203 {
204     DHLOGI("ScanAllNode enter.");
205     if (event == nullptr) {
206         DHLOGE("event is null.");
207         return;
208     }
209     std::shared_ptr<nlohmann::json> dataMsg = event->GetSharedObject<nlohmann::json>();
210     if (dataMsg == nullptr) {
211         DHLOGE("dataMsg is null.");
212         return;
213     }
214     auto it = dataMsg->begin();
215     nlohmann::json innerMsg = *(it);
216     std::string devId = innerMsg[INPUT_NODE_DEVID];
217     std::string devicedhId = innerMsg[INPUT_NODE_DHID];
218     nodeManagerObj_->ScanSinkInputDevices(devId, devicedhId);
219 }
220 
NotifyNodeMgrScanVirNode(const std::string & devId,const std::string & dhId)221 void DistributedInputNodeManager::NotifyNodeMgrScanVirNode(const std::string &devId, const std::string &dhId)
222 {
223     DHLOGI("NotifyNodeMgrScanVirNode enter.");
224     std::shared_ptr<nlohmann::json> jsonArrayMsg = std::make_shared<nlohmann::json>();
225     nlohmann::json tmpJson;
226     tmpJson[INPUT_NODE_DEVID] = devId;
227     tmpJson[INPUT_NODE_DHID] = dhId;
228     jsonArrayMsg->push_back(tmpJson);
229     AppExecFwk::InnerEvent::Pointer msgEvent = AppExecFwk::InnerEvent::Get(
230         DINPUT_NODE_MANAGER_SCAN_ALL_NODE, jsonArrayMsg, 0);
231     callBackHandler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE);
232 }
233 
IsVirtualDev(int fd)234 bool DistributedInputNodeManager::IsVirtualDev(int fd)
235 {
236     char buffer[INPUT_EVENT_BUFFER_SIZE] = {0};
237     std::string deviceName;
238     if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
239         DHLOGE("Could not get device name for %{public}s.", ConvertErrNo().c_str());
240         return false;
241     }
242     buffer[sizeof(buffer) - 1] = '\0';
243     deviceName = buffer;
244 
245     DHLOGD("IsVirtualDev deviceName: %{public}s", buffer);
246     if (deviceName.find(VIRTUAL_DEVICE_NAME) == std::string::npos) {
247         DHLOGD("This is not a virtual device, fd %{public}d, deviceName: %{public}s.", fd, deviceName.c_str());
248         return false;
249     }
250     return true;
251 }
252 
GetDevDhUniqueIdByFd(int fd,DhUniqueID & dhUnqueId,std::string & physicalPath)253 bool DistributedInputNodeManager::GetDevDhUniqueIdByFd(int fd, DhUniqueID &dhUnqueId, std::string &physicalPath)
254 {
255     char buffer[INPUT_EVENT_BUFFER_SIZE] = {0};
256     if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
257         DHLOGE("Could not get device physicalPath for %{public}s.", ConvertErrNo().c_str());
258         return false;
259     }
260     buffer[sizeof(buffer) - 1] = '\0';
261     physicalPath = buffer;
262 
263     DHLOGD("GetDevDhUniqueIdByFd physicalPath %{public}s.", physicalPath.c_str());
264     std::vector<std::string> phyPathVec;
265     SplitStringToVector(physicalPath, VIR_NODE_SPLIT_CHAR, phyPathVec);
266     if (phyPathVec.size() != VIR_NODE_PHY_LEN) {
267         DHLOGE("The physical path is invalid");
268         return false;
269     }
270     std::string devId = phyPathVec[VIR_NODE_PHY_DEVID_IDX];
271     std::string dhId = phyPathVec[VIR_NODE_PHY_DHID_IDX];
272     if (devId.empty() || dhId.empty()) {
273         DHLOGE("Get dev deviceid and dhid failed.");
274         return false;
275     }
276     dhUnqueId.first = devId;
277     dhUnqueId.second = dhId;
278     DHLOGD("Device deviceid: %{public}s, dhId %{public}s.", GetAnonyString(devId).c_str(),
279         GetAnonyString(dhId).c_str());
280     return true;
281 }
282 
SetPathForVirDev(const DhUniqueID & dhUniqueId,const std::string & devicePath)283 void DistributedInputNodeManager::SetPathForVirDev(const DhUniqueID &dhUniqueId, const std::string &devicePath)
284 {
285     std::lock_guard<std::mutex> lock(virtualDeviceMapMutex_);
286     auto iter = virtualDeviceMap_.begin();
287     while (iter != virtualDeviceMap_.end()) {
288         DHLOGD("Check Virtual device, deviceId %{public}s, dhid %{public}s.", GetAnonyString(iter->first.first).c_str(),
289             GetAnonyString(iter->first.second).c_str());
290         if (iter->first == dhUniqueId) {
291             DHLOGD("Found the virtual device, set path :%{public}s", devicePath.c_str());
292             iter->second->SetPath(devicePath);
293             break;
294         }
295         iter++;
296     }
297 }
298 
MatchAndSavePhysicalPath(const std::string & devicePath,const std::string & devId,const std::string & dhId)299 bool DistributedInputNodeManager::MatchAndSavePhysicalPath(const std::string &devicePath,
300     const std::string &devId, const std::string &dhId)
301 {
302     DHLOGI("Opening input device path: %{public}s", devicePath.c_str());
303     DhUniqueID curDhUniqueId;
304     std::string physicalPath;
305     int fd = OpenInputDeviceFdByPath(devicePath);
306     if (fd == UN_INIT_FD_VALUE) {
307         DHLOGE("The fd open failed, devicePath %{public}s.", devicePath.c_str());
308         return false;
309     }
310     if (!IsVirtualDev(fd)) {
311         DHLOGE("The dev not virtual, devicePath %{public}s.", devicePath.c_str());
312         CloseFd(fd);
313         return false;
314     }
315     if (!GetDevDhUniqueIdByFd(fd, curDhUniqueId, physicalPath)) {
316         DHLOGE("Get unique id failed, device path %{public}s.", devicePath.c_str());
317         CloseFd(fd);
318         return false;
319     }
320 
321     DHLOGD("This opening node deviceId: %{public}s, dhId: %{public}s, to match node deviceId: %{public}s, "
322         "dhId: %{public}s", GetAnonyString(curDhUniqueId.first).c_str(), GetAnonyString(curDhUniqueId.second).c_str(),
323         GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
324 
325     if (curDhUniqueId.first != devId || curDhUniqueId.second != dhId) {
326         DHLOGW("It is not the target vir node, skip it.");
327         CloseFd(fd);
328         return false;
329     }
330 
331     SetPathForVirDev(curDhUniqueId, devicePath);
332     CloseFd(fd);
333     return true;
334 }
335 
GetVirtualKeyboardPaths(const std::vector<DhUniqueID> & dhUniqueIds,std::vector<std::string> & virKeyboardPaths)336 void DistributedInputNodeManager::GetVirtualKeyboardPaths(const std::vector<DhUniqueID> &dhUniqueIds,
337     std::vector<std::string> &virKeyboardPaths)
338 {
339     std::lock_guard<std::mutex> lock(virtualDeviceMapMutex_);
340     for (const auto &dhUniqueId : dhUniqueIds) {
341         auto iter = virtualDeviceMap_.begin();
342         while (iter != virtualDeviceMap_.end()) {
343             if (iter->second == nullptr) {
344                 DHLOGE("device is nullptr");
345                 continue;
346             }
347             if ((iter->first == dhUniqueId) &&
348                 ((iter->second->GetClasses() & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
349                 DHLOGI("Found vir keyboard path %{public}s, deviceId %{public}s, dhid %{public}s",
350                     iter->second->GetPath().c_str(), GetAnonyString(dhUniqueId.first).c_str(),
351                     GetAnonyString(dhUniqueId.second).c_str());
352                 virKeyboardPaths.push_back(iter->second->GetPath());
353             }
354             iter++;
355         }
356     }
357 }
358 
CreateHandle(const InputDevice & inputDevice,const std::string & devId,const std::string & dhId)359 int32_t DistributedInputNodeManager::CreateHandle(const InputDevice &inputDevice, const std::string &devId,
360     const std::string &dhId)
361 {
362     std::unique_lock<std::mutex> my_lock(operationMutex_);
363     std::unique_ptr<VirtualDevice> virtualDevice = std::make_unique<VirtualDevice>(inputDevice);
364 
365     virtualDevice->SetNetWorkId(devId);
366 
367     if (!virtualDevice->SetUp(inputDevice, devId, dhId)) {
368         DHLOGE("could not create new virtual device\n");
369         for (int32_t i = 0; i < RETRY_MAX_TIMES; ++i) {
370             if (virtualDevice->SetUp(inputDevice, devId, dhId)) {
371                 DHLOGI("Create new virtual success");
372                 AddDeviceLocked(devId, inputDevice.descriptor, std::move(virtualDevice));
373                 return DH_SUCCESS;
374             }
375             usleep(SLEEP_TIME_US);
376         }
377         return ERR_DH_INPUT_SERVER_SOURCE_CREATE_HANDLE_FAIL;
378     }
379     AddDeviceLocked(devId, inputDevice.descriptor, std::move(virtualDevice));
380     return DH_SUCCESS;
381 }
382 
CreateVirtualTouchScreenNode(const std::string & devId,const std::string & dhId,const uint64_t srcWinId,const uint32_t sourcePhyWidth,const uint32_t sourcePhyHeight)383 int32_t DistributedInputNodeManager::CreateVirtualTouchScreenNode(const std::string &devId, const std::string &dhId,
384     const uint64_t srcWinId, const uint32_t sourcePhyWidth, const uint32_t sourcePhyHeight)
385 {
386     std::unique_lock<std::mutex> my_lock(operationMutex_);
387     std::unique_ptr<VirtualDevice> device;
388     LocalAbsInfo info = DInputContext::GetInstance().GetLocalTouchScreenInfo().localAbsInfo;
389     DHLOGI("CreateVirtualTouchScreenNode, dhId: %{public}s, sourcePhyWidth: %{public}d, sourcePhyHeight: %{public}d",
390         GetAnonyString(dhId).c_str(), sourcePhyWidth, sourcePhyHeight);
391     device = std::make_unique<VirtualDevice>(info.deviceInfo);
392     if (!device->SetUp(info.deviceInfo, devId, dhId)) {
393         DHLOGE("Virtual touch Screen setUp fail, devId: %{public}s, dhId: %{public}s", GetAnonyString(devId).c_str(),
394             GetAnonyString(dhId).c_str());
395         return ERR_DH_INPUT_SERVER_SOURCE_CREATE_HANDLE_FAIL;
396     }
397     virtualTouchScreenFd_ = device->GetDeviceFd();
398     AddDeviceLocked(devId, dhId, std::move(device));
399     DHLOGI("CreateVirtualTouchScreenNode end, dhId: %{public}s", GetAnonyString(dhId).c_str());
400     return DH_SUCCESS;
401 }
402 
RemoveVirtualTouchScreenNode(const std::string & devId,const std::string & dhId)403 int32_t DistributedInputNodeManager::RemoveVirtualTouchScreenNode(const std::string &devId, const std::string &dhId)
404 {
405     return CloseDeviceLocked(devId, dhId);
406 }
407 
GetVirtualTouchScreenFd()408 int32_t DistributedInputNodeManager::GetVirtualTouchScreenFd()
409 {
410     return virtualTouchScreenFd_;
411 }
412 
AddDeviceLocked(const std::string & networkId,const std::string & dhId,std::unique_ptr<VirtualDevice> device)413 void DistributedInputNodeManager::AddDeviceLocked(const std::string &networkId, const std::string &dhId,
414     std::unique_ptr<VirtualDevice> device)
415 {
416     DHLOGI("AddDeviceLocked deviceId=%{public}s, dhId=%{public}s",
417         GetAnonyString(networkId).c_str(), GetAnonyString(dhId).c_str());
418     std::lock_guard<std::mutex> lock(virtualDeviceMapMutex_);
419     auto [dev_it, inserted] = virtualDeviceMap_.insert_or_assign(
420         {networkId, dhId}, std::move(device));
421     if (!inserted) {
422         DHLOGI("Device exists, deviceId=%{public}s, dhId=%{public}s, replaced. \n",
423             GetAnonyString(networkId).c_str(), GetAnonyString(dhId).c_str());
424     }
425 }
426 
CloseDeviceLocked(const std::string & devId,const std::string & dhId)427 int32_t DistributedInputNodeManager::CloseDeviceLocked(const std::string &devId, const std::string &dhId)
428 {
429     DHLOGI("CloseDeviceLocked called, deviceId=%{public}s, dhId=%{public}s",
430         GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
431     std::lock_guard<std::mutex> lock(virtualDeviceMapMutex_);
432     DhUniqueID dhUniqueId = {devId, dhId};
433     std::map<DhUniqueID, std::unique_ptr<VirtualDevice>>::iterator iter = virtualDeviceMap_.find(dhUniqueId);
434     if (iter != virtualDeviceMap_.end()) {
435         DHLOGI("CloseDeviceLocked called success, deviceId=%{public}s, dhId=%{public}s",
436             GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
437         virtualDeviceMap_.erase(iter);
438         return DH_SUCCESS;
439     }
440     DHLOGE("CloseDeviceLocked called failure, deviceId=%{public}s, dhId=%{public}s",
441         GetAnonyString(devId).c_str(), GetAnonyString(dhId).c_str());
442     return ERR_DH_INPUT_SERVER_SOURCE_CLOSE_DEVICE_FAIL;
443 }
444 
GetDevice(const std::string & devId,const std::string & dhId,VirtualDevice * & device)445 int32_t DistributedInputNodeManager::GetDevice(const std::string &devId, const std::string &dhId,
446     VirtualDevice *&device)
447 {
448     std::lock_guard<std::mutex> lock(virtualDeviceMapMutex_);
449     auto iter = virtualDeviceMap_.find({devId, dhId});
450     if (iter != virtualDeviceMap_.end()) {
451         device = iter->second.get();
452         return DH_SUCCESS;
453     }
454     return ERR_DH_INPUT_SERVER_SOURCE_GET_DEVICE_FAIL;
455 }
456 
StartInjectThread()457 void DistributedInputNodeManager::StartInjectThread()
458 {
459     if (isInjectThreadCreated_.load()) {
460         DHLOGI("InjectThread has been created.");
461         return;
462     }
463     DHLOGI("InjectThread does not created");
464     isInjectThreadCreated_.store(true);
465     isInjectThreadRunning_.store(true);
466     eventInjectThread_ = std::thread([this]() { this->InjectEvent(); });
467 }
468 
StopInjectThread()469 void DistributedInputNodeManager::StopInjectThread()
470 {
471     if (!isInjectThreadCreated_.load()) {
472         DHLOGI("InjectThread does not created, and not need to stop.");
473     }
474     DHLOGI("InjectThread has been created, and soon will be stopped.");
475     isInjectThreadRunning_.store(false);
476     isInjectThreadCreated_.store(false);
477     conditionVariable_.notify_all();
478     if (eventInjectThread_.joinable()) {
479         eventInjectThread_.join();
480     }
481 }
482 
ReportEvent(const std::string & devId,const std::vector<RawEvent> & events)483 void DistributedInputNodeManager::ReportEvent(const std::string &devId, const std::vector<RawEvent> &events)
484 {
485     std::lock_guard<std::mutex> lockGuard(injectThreadMutex_);
486     injectQueue_.push({devId, events});
487     conditionVariable_.notify_all();
488 }
489 
InjectEvent()490 void DistributedInputNodeManager::InjectEvent()
491 {
492     int32_t ret = pthread_setname_np(pthread_self(), EVENT_INJECT_THREAD_NAME);
493     if (ret != 0) {
494         DHLOGE("InjectEvent setname failed.");
495     }
496     DHLOGD("start");
497     while (isInjectThreadRunning_.load()) {
498         EventBatch events;
499         {
500             std::unique_lock<std::mutex> waitEventLock(injectThreadMutex_);
501             conditionVariable_.wait(waitEventLock,
502                 [this]() { return !isInjectThreadRunning_.load() || !injectQueue_.empty(); });
503             if (injectQueue_.empty()) {
504                 continue;
505             }
506             events = injectQueue_.front();
507             injectQueue_.pop();
508         }
509 
510         ProcessInjectEvent(events);
511     }
512 }
513 
RegisterInjectEventCb(sptr<ISessionStateCallback> callback)514 void DistributedInputNodeManager::RegisterInjectEventCb(sptr<ISessionStateCallback> callback)
515 {
516     DHLOGI("RegisterInjectEventCb");
517     SessionStateCallback_ = callback;
518 }
519 
UnregisterInjectEventCb()520 void DistributedInputNodeManager::UnregisterInjectEventCb()
521 {
522     DHLOGI("UnregisterInjectEventCb");
523     SessionStateCallback_ = nullptr;
524 }
525 
RunInjectEventCallback(const std::string & dhId,const uint32_t injectEvent)526 void DistributedInputNodeManager::RunInjectEventCallback(const std::string &dhId, const uint32_t injectEvent)
527 {
528     DHLOGI("RunInjectEventCallback start.");
529     if (SessionStateCallback_ == nullptr) {
530         DHLOGE("RunSessionStateCallback SessionStateCallback_ is null.");
531         return;
532     }
533     SessionStateCallback_->OnResult(dhId, DINPUT_INJECT_EVENT_FAIL);
534 }
535 
ProcessInjectEvent(const EventBatch & events)536 void DistributedInputNodeManager::ProcessInjectEvent(const EventBatch &events)
537 {
538     std::string deviceId = events.first;
539     for (const auto &rawEvent : events.second) {
540         std::string dhId = rawEvent.descriptor;
541         struct input_event event = {
542             .type = rawEvent.type,
543             .code = rawEvent.code,
544             .value = rawEvent.value
545         };
546         DHLOGI("InjectEvent deviceId: %{public}s, dhId: %{public}s, eventType: %{public}d, eventCode: %{public}d, "
547             "eventValue: %{public}d, when: %{public}" PRId64"", GetAnonyString(deviceId).c_str(),
548             GetAnonyString(dhId).c_str(), event.type, event.code, event.value, rawEvent.when);
549         VirtualDevice* device = nullptr;
550         if (GetDevice(deviceId, dhId, device) < 0) {
551             DHLOGE("could not find the device");
552             return;
553         }
554         if (device != nullptr) {
555             device->InjectInputEvent(event);
556         }
557     }
558 }
559 } // namespace DistributedInput
560 } // namespace DistributedHardware
561 } // namespace OHOS
562