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 "input_hub.h"
17
18#include <algorithm>
19#include <cinttypes>
20#include <cstring>
21#include <fcntl.h>
22#include <filesystem>
23#include <regex>
24#include <securec.h>
25#include <sstream>
26#include <sys/stat.h>
27#include <sys/types.h>
28#include <thread>
29#include <unistd.h>
30#include <utility>
31
32#include "constants_dinput.h"
33#include "dinput_context.h"
34#include "dinput_errcode.h"
35#include "dinput_log.h"
36#include "dinput_sink_state.h"
37#include "dinput_utils_tool.h"
38
39namespace OHOS {
40namespace DistributedHardware {
41namespace DistributedInput {
42namespace {
43const uint32_t SLEEP_TIME_US = 100 * 1000;
44const std::string MOUSE_NODE_KEY = "mouse";
45const uint32_t SPACELENGTH = 1024;
46}
47
48InputHub::InputHub(bool isPluginMonitor) : epollFd_(-1), iNotifyFd_(-1), inputWd_(-1),
49    isPluginMonitor_(isPluginMonitor), needToScanDevices_(true), mPendingEventItems{},
50    pendingEventCount_(0), pendingEventIndex_(0), pendingINotify_(false), deviceChanged_(false),
51    inputTypes_(0), isStartCollectEvent_(false), isStartCollectHandler_(false)
52{
53    Initialize();
54}
55
56InputHub::~InputHub()
57{
58    Release();
59}
60
61int32_t InputHub::Initialize()
62{
63    epollFd_ = epoll_create1(EPOLL_CLOEXEC);
64    if (epollFd_ < 0) {
65        DHLOGE("Could not create epoll instance: %{public}s", ConvertErrNo().c_str());
66        return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
67    }
68
69    if (isPluginMonitor_) {
70        DHLOGI("Init InputHub for device plugin monitor");
71        iNotifyFd_ = inotify_init();
72        inputWd_ = inotify_add_watch(iNotifyFd_, DEVICE_PATH, IN_DELETE | IN_CREATE);
73        if (inputWd_ < 0) {
74            DHLOGE("Could not register INotify for %{public}s: %{public}s", DEVICE_PATH, ConvertErrNo().c_str());
75            return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
76        }
77
78        struct epoll_event eventItem = {};
79        eventItem.events = EPOLLIN;
80        eventItem.data.fd = iNotifyFd_;
81        int result = epoll_ctl(epollFd_, EPOLL_CTL_ADD, iNotifyFd_, &eventItem);
82        if (result != 0) {
83            DHLOGE("Could not add INotify to epoll instance.  errno=%{public}d", errno);
84            return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
85        }
86    } else {
87        DHLOGI("Init InputHub for read device events");
88    }
89
90    return DH_SUCCESS;
91}
92
93int32_t InputHub::Release()
94{
95    CloseAllDevicesLocked();
96    if (epollFd_ != -1) {
97        ::close(epollFd_);
98        epollFd_ = -1;
99    }
100
101    if (iNotifyFd_ != -1) {
102        ::close(iNotifyFd_);
103        iNotifyFd_ = -1;
104    }
105
106    if (isPluginMonitor_) {
107        StopCollectInputHandler();
108    } else {
109        StopCollectInputEvents();
110    }
111
112    sharedDHIds_.clear();
113    logTimesMap_.clear();
114    return DH_SUCCESS;
115}
116
117bool InputHub::IsInputNodeNoNeedScan(const std::string &path)
118{
119    {
120        std::lock_guard<std::mutex> deviceLock(devicesMutex_);
121        auto iter = devices_.find(path);
122        if (iter != devices_.end()) {
123            return true;
124        }
125    }
126
127    if (path.find(MOUSE_NODE_KEY) != std::string::npos) {
128        return true;
129    }
130
131    return IsSkipDevicePath(path);
132}
133
134void InputHub::ScanAndRecordInputDevices()
135{
136    ScanInputDevices(DEVICE_PATH);
137
138    {
139        std::lock_guard<std::mutex> deviceLock(devicesMutex_);
140        while (!openingDevices_.empty()) {
141            std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
142            openingDevices_.pop_back();
143            DHLOGI("Reporting device opened: path=%{public}s, name=%{public}s\n",
144                device->path.c_str(), device->identifier.name.c_str());
145            std::string devPath = device->path;
146            auto [dev_it, inserted] = devices_.insert_or_assign(device->path, std::move(device));
147            if (!inserted) {
148                DHLOGI("Device with this path %{public}s exists, replaced. \n", devPath.c_str());
149            }
150        }
151    }
152}
153
154size_t InputHub::StartCollectInputEvents(RawEvent *buffer, size_t bufferSize)
155{
156    size_t count = 0;
157    isStartCollectEvent_ = true;
158    while (isStartCollectEvent_) {
159        ScanAndRecordInputDevices();
160        count = GetEvents(buffer, bufferSize);
161        if (count > 0) {
162            break;
163        }
164
165        if (RefreshEpollItem(false) < 0) {
166            break;
167        }
168    }
169
170    // All done, return the number of events we read.
171    return count;
172}
173
174void InputHub::StopCollectInputEvents()
175{
176    DHLOGI("Stop Collect Input Events Thread");
177    isStartCollectEvent_ = false;
178}
179
180size_t InputHub::GetEvents(RawEvent *buffer, size_t bufferSize)
181{
182    RawEvent* event = buffer;
183    size_t capacity = bufferSize;
184    while (pendingEventIndex_ < pendingEventCount_) {
185        std::lock_guard<std::mutex> my_lock(operationMutex_);
186        const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
187        if (eventItem.data.fd == iNotifyFd_) {
188            continue;
189        }
190        struct input_event readBuffer[bufferSize];
191        int32_t readSize = read(eventItem.data.fd, readBuffer, sizeof(struct input_event) * capacity);
192        Device* deviceByFd = GetDeviceByFdLocked(eventItem.data.fd);
193        if (!deviceByFd) {
194            DHLOGE("Find device by fd: %{public}d failed", eventItem.data.fd);
195            continue;
196        }
197        size_t count = ReadInputEvent(readSize, *deviceByFd);
198        Device* device = GetSupportDeviceByFd(eventItem.data.fd);
199        if (!device) {
200            DHLOGE("Can not find device by fd: %{public}d", eventItem.data.fd);
201            continue;
202        }
203        if (!sharedDHIds_[device->identifier.descriptor]) {
204            RecordDeviceChangeStates(device, readBuffer, count);
205            DHLOGD("Not in sharing stat, device descriptor: %{public}s",
206                GetAnonyString(device->identifier.descriptor).c_str());
207            continue;
208        }
209        if (eventItem.events & EPOLLIN) {
210            event += CollectEvent(event, capacity, device, readBuffer, count);
211
212            if (capacity == 0) {
213                pendingEventIndex_ -= 1;
214                break;
215            }
216        } else if (eventItem.events & EPOLLHUP) {
217            DHLOGI("Removing device %{public}s due to epoll hang-up event.", device->identifier.name.c_str());
218            CloseDeviceLocked(*device);
219        }
220    }
221    return event - buffer;
222}
223
224bool InputHub::IsCuror(Device *device)
225{
226    return device->classes & INPUT_DEVICE_CLASS_CURSOR;
227}
228
229bool InputHub::IsTouchPad(Device *device)
230{
231    return ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) &&
232        IsTouchPad(device->identifier);
233}
234
235bool InputHub::IsTouchPad(const InputDevice &inputDevice)
236{
237    std::string dhName = inputDevice.name;
238    transform(dhName.begin(), dhName.end(), dhName.begin(), ::tolower);
239    if (dhName.find(DH_TOUCH_PAD) == std::string::npos) {
240        return false;
241    }
242    return true;
243}
244
245void InputHub::MatchAndDealEvent(Device *device, const RawEvent &event)
246{
247    bool isTouchPad = IsTouchPad(device);
248    if (!isTouchPad) {
249        // Deal Normal key state, such as keys of keyboard or mouse
250        DealNormalKeyEvent(device, event);
251    } else {
252        // Deal TouchPad events
253        DealTouchPadEvent(event);
254    }
255}
256
257void InputHub::DealTouchPadEvent(const RawEvent &event)
258{
259    auto ret = DInputSinkState::GetInstance().GetTouchPadEventFragMgr()->PushEvent(event.descriptor, event);
260    if (ret.first) {
261        DInputSinkState::GetInstance().SimulateTouchPadStateReset(ret.second);
262    }
263}
264
265void InputHub::DealNormalKeyEvent(Device *device, const RawEvent &event)
266{
267    if (event.type == EV_KEY && event.value == KEY_DOWN_STATE) {
268        DInputSinkState::GetInstance().AddKeyDownState(event);
269        RecordChangeEventLog(event);
270    }
271    if (event.type == EV_KEY && event.value == KEY_UP_STATE) {
272        // Deal mouse left keydown reset
273        if (IsCuror(device) && event.code == BTN_MOUSE &&
274            !DInputSinkState::GetInstance().IsDhIdDown(event.descriptor)) {
275            DHLOGI("Find mouse BTN_MOUSE UP state that not down effective at sink side, dhId: %{public}s",
276                GetAnonyString(event.descriptor).c_str());
277            DInputSinkState::GetInstance().SimulateMouseBtnMouseUpState(event.descriptor, event);
278        }
279        DInputSinkState::GetInstance().RemoveKeyDownState(event);
280        RecordChangeEventLog(event);
281    }
282    if (event.type == EV_KEY && event.value == KEY_REPEAT) {
283        DInputSinkState::GetInstance().CheckAndSetLongPressedKeyOrder(event);
284    }
285}
286
287void InputHub::RecordDeviceChangeStates(Device *device, struct input_event readBuffer[], const size_t count)
288{
289    bool isTouchEvent = false;
290    if ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
291        if (!IsTouchPad(device->identifier)) {
292            isTouchEvent = true;
293        }
294    }
295
296    for (size_t i = 0; i < count; i++) {
297        const struct input_event& iev = readBuffer[i];
298        RawEvent event;
299        event.when = ProcessEventTimestamp(iev);
300        event.type = iev.type;
301        event.code = iev.code;
302        event.value = iev.value;
303        event.path = device->path;
304        event.descriptor = isTouchEvent ? touchDescriptor : device->identifier.descriptor;
305        MatchAndDealEvent(device, event);
306    }
307}
308
309size_t InputHub::CollectEvent(RawEvent *buffer, size_t &capacity, Device *device, struct input_event readBuffer[],
310    const size_t count)
311{
312    std::vector<bool> needFilted(capacity, false);
313    bool isTouchEvent = false;
314    if ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
315        if (!IsTouchPad(device->identifier)) {
316            isTouchEvent = true;
317            HandleTouchScreenEvent(readBuffer, count, needFilted);
318        }
319    }
320
321    RawEvent* event = buffer;
322    for (size_t i = 0; i < count; i++) {
323        if (needFilted[i]) {
324            continue;
325        }
326        const struct input_event& iev = readBuffer[i];
327        event->when = ProcessEventTimestamp(iev);
328        event->type = iev.type;
329        event->code = iev.code;
330        event->value = iev.value;
331        event->path = device->path;
332        event->descriptor = isTouchEvent ? touchDescriptor : device->identifier.descriptor;
333        RecordEventLog(event);
334        event += 1;
335        capacity -= 1;
336        if (capacity == 0) {
337            break;
338        }
339    }
340    return event - buffer;
341}
342
343size_t InputHub::ReadInputEvent(int32_t readSize, Device &device)
344{
345    size_t count = 0;
346    if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
347        // Device was removed before INotify noticed.
348        DHLOGE("could not get event, removed? (fd: %{public}d size: %{public}d, errno: %{public}d)\n",
349            device.fd, readSize, errno);
350        CloseDeviceLocked(device);
351    } else if (readSize < 0) {
352        if (errno != EAGAIN && errno != EINTR) {
353            DHLOGW("could not get event (errno=%{public}d)", errno);
354        }
355    } else if ((readSize % sizeof(struct input_event)) != 0) {
356        DHLOGW("could not get event (wrong size: %{public}d)", readSize);
357    } else {
358        count = size_t(readSize) / sizeof(struct input_event);
359        return count;
360    }
361    return count;
362}
363
364size_t InputHub::DeviceIsExists(InputDeviceEvent *buffer, size_t bufferSize)
365{
366    InputDeviceEvent* event = buffer;
367    size_t capacity = bufferSize;
368    // Report any devices that had last been added/removed.
369    {
370        std::lock_guard<std::mutex> deviceLock(devicesMutex_);
371        for (auto it = closingDevices_.begin(); it != closingDevices_.end();) {
372            std::unique_ptr<Device> device = std::move(*it);
373            DHLOGI("Reporting device closed: id=%{public}s, name=%{public}s",
374                device->path.c_str(), device->identifier.name.c_str());
375            event->type = DeviceType::DEVICE_REMOVED;
376            event->deviceInfo = device->identifier;
377            event += 1;
378            it = closingDevices_.erase(it);
379            if (capacity == 0) {
380                break;
381            }
382            capacity--;
383        }
384    }
385
386    if (needToScanDevices_) {
387        needToScanDevices_ = false;
388        ScanInputDevices(DEVICE_PATH);
389    }
390
391    {
392        std::lock_guard<std::mutex> deviceLock(devicesMutex_);
393        while (!openingDevices_.empty()) {
394            std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
395            openingDevices_.pop_back();
396            DHLOGI("Reporting device opened: id=%{public}s, name=%{public}s",
397                device->path.c_str(), device->identifier.name.c_str());
398            event->type = DeviceType::DEVICE_ADDED;
399            event->deviceInfo = device->identifier;
400            event += 1;
401
402            std::string devPath = device->path;
403            auto [dev_it, inserted] = devices_.insert_or_assign(device->path, std::move(device));
404            if (!inserted) {
405                DHLOGI("Device path %{public}s exists, replaced.", devPath.c_str());
406            }
407            if (capacity == 0) {
408                break;
409            }
410            capacity--;
411        }
412    }
413    return event - buffer;
414}
415
416size_t InputHub::StartCollectInputHandler(InputDeviceEvent *buffer, size_t bufferSize)
417{
418    size_t count = 0;
419    isStartCollectHandler_ = true;
420    while (isStartCollectHandler_) {
421        count = DeviceIsExists(buffer, bufferSize);
422        deviceChanged_ = false;
423        GetDeviceHandler();
424
425        if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
426            pendingINotify_ = false;
427            ReadNotifyLocked();
428            deviceChanged_ = true;
429        }
430
431        // Report added or removed devices immediately.
432        if (deviceChanged_) {
433            continue;
434        }
435        if (count > 0) {
436            break;
437        }
438        if (RefreshEpollItem(true) < 0) {
439            break;
440        }
441    }
442
443    // All done, return the number of events we read.
444    return count;
445}
446
447void InputHub::StopCollectInputHandler()
448{
449    DHLOGI("Stop Collect Input Handler Thread");
450    isStartCollectHandler_ = false;
451}
452
453void InputHub::GetDeviceHandler()
454{
455    while (pendingEventIndex_ < pendingEventCount_) {
456        std::lock_guard<std::mutex> my_lock(operationMutex_);
457        const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
458        if (eventItem.data.fd == iNotifyFd_) {
459            if (eventItem.events & EPOLLIN) {
460                pendingINotify_ = true;
461            } else {
462                DHLOGI("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
463            }
464            continue;
465        }
466
467        if (eventItem.events & EPOLLHUP) {
468            Device* device = GetDeviceByFdLocked(eventItem.data.fd);
469            if (!device) {
470                DHLOGE("Received unexpected epoll event 0x%{public}08x for unknown fd %{public}d.",
471                    eventItem.events, eventItem.data.fd);
472                continue;
473            }
474            DHLOGI("Removing device %{public}s due to epoll hang-up event.", device->identifier.name.c_str());
475            deviceChanged_ = true;
476            CloseDeviceLocked(*device);
477        }
478    }
479}
480
481int32_t InputHub::RefreshEpollItem(bool isSleep)
482{
483    pendingEventIndex_ = 0;
484    int pollResult = epoll_wait(epollFd_, mPendingEventItems, EPOLL_MAX_EVENTS, EPOLL_WAITTIME);
485    if (pollResult == 0) {
486        // Timed out.
487        pendingEventCount_ = 0;
488        return ERR_DH_INPUT_HUB_EPOLL_WAIT_TIMEOUT;
489    }
490
491    if (pollResult < 0) {
492        // An error occurred.
493        pendingEventCount_ = 0;
494
495        // Sleep after errors to avoid locking up the system.
496        // Hopefully the error is transient.
497        if (errno != EINTR) {
498            DHLOGE("poll failed (errno=%{public}d)\n", errno);
499            usleep(SLEEP_TIME_US);
500        }
501    } else {
502        // Some events occurred.
503        pendingEventCount_ = pollResult;
504    }
505    if (isSleep) {
506        usleep(SLEEP_TIME_US);
507    }
508    return DH_SUCCESS;
509}
510
511std::vector<InputDevice> InputHub::GetAllInputDevices()
512{
513    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
514    std::vector<InputDevice> vecDevice;
515    for (const auto &[id, device] : devices_) {
516        vecDevice.push_back(device->identifier);
517    }
518    return vecDevice;
519}
520
521void InputHub::ScanInputDevices(const std::string &dirName)
522{
523    std::vector<std::string> inputDevPaths;
524    ScanInputDevicesPath(dirName, inputDevPaths);
525    for (const auto &tempPath: inputDevPaths) {
526        if (IsInputNodeNoNeedScan(tempPath)) {
527            continue;
528        }
529        OpenInputDeviceLocked(tempPath);
530    }
531}
532
533bool InputHub::IsDeviceRegistered(const std::string &devicePath)
534{
535    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
536    for (const auto &[deviceId, device] : devices_) {
537        if (device->path == devicePath) {
538            DHLOGI("Device node already registered, node path: %{public}s", device->path.c_str());
539            return true; // device was already registered
540        }
541    }
542    return false;
543}
544
545int32_t InputHub::OpenInputDeviceLocked(const std::string &devicePath)
546{
547    if (IsDeviceRegistered(devicePath)) {
548        return DH_SUCCESS;
549    }
550
551    std::lock_guard<std::mutex> my_lock(operationMutex_);
552    DHLOGD("Opening device start: %{public}s", devicePath.c_str());
553    int fd = OpenInputDeviceFdByPath(devicePath);
554    if (fd == UN_INIT_FD_VALUE) {
555        DHLOGE("The fd open failed, devicePath %{public}s.", devicePath.c_str());
556        return ERR_DH_INPUT_HUB_OPEN_DEVICEPATH_FAIL;
557    }
558
559    // Allocate device. (The device object takes ownership of the fd at this point.)
560    std::unique_ptr<Device> device = std::make_unique<Device>(fd, devicePath);
561
562    if (QueryInputDeviceInfo(fd, device) < 0) {
563        CloseFd(fd);
564        return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
565    }
566    GenerateDescriptor(device->identifier);
567    IncreaseLogTimes(device->identifier.descriptor);
568    RecordDeviceLog(devicePath, device->identifier);
569    std::string descriptor = device->identifier.descriptor;
570    if (MakeDevice(fd, std::move(device)) < 0) {
571        CloseFd(fd);
572        if (IsNeedPrintLog(descriptor)) {
573            DHLOGI("Opening device error: %{public}s", devicePath.c_str());
574        }
575        return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
576    }
577
578    DHLOGI("Opening device finish: %{public}s", devicePath.c_str());
579    return DH_SUCCESS;
580}
581
582void InputHub::RecordSkipDevicePath(std::string path)
583{
584    std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
585    skipDevicePaths_.insert(path);
586}
587
588bool InputHub::IsSkipDevicePath(const std::string &path)
589{
590    std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
591    return skipDevicePaths_.find(path) != skipDevicePaths_.end();
592}
593
594void InputHub::IncreaseLogTimes(const std::string& dhId)
595{
596    if (logTimesMap_.find(dhId) != logTimesMap_.end() && logTimesMap_[dhId] >= INT32_MAX - 1) {
597        logTimesMap_[dhId] = 0;
598    } else {
599        logTimesMap_[dhId]++;
600    }
601}
602
603bool InputHub::IsNeedPrintLog(const std::string& dhId) const
604{
605    return logTimesMap_.find(dhId) == logTimesMap_.end() || logTimesMap_.at(dhId) <= MAX_LOG_TIMES;
606}
607
608int32_t InputHub::QueryInputDeviceInfo(int fd, std::unique_ptr<Device> &device)
609{
610    char buffer[INPUT_EVENT_BUFFER_SIZE] = {0};
611    // Get device name.
612    if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
613        DHLOGE("Could not get device name for %{public}s", ConvertErrNo().c_str());
614    } else {
615        buffer[sizeof(buffer) - 1] = '\0';
616        device->identifier.name = buffer;
617    }
618    DHLOGD("QueryInputDeviceInfo deviceName: %{public}s", buffer);
619    // If the device is already a virtual device, don't monitor it.
620    if (device->identifier.name.find(VIRTUAL_DEVICE_NAME) != std::string::npos) {
621        DHLOGE("this is a virtual driver, skip it.");
622        RecordSkipDevicePath(device->path);
623        return ERR_DH_INPUT_HUB_IS_VIRTUAL_DEVICE;
624    }
625    // Get device driver version.
626    int driverVersion;
627    if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
628        DHLOGE("could not get driver version for %{public}s\n", ConvertErrNo().c_str());
629        RecordSkipDevicePath(device->path);
630        return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
631    }
632    // Get device identifier.
633    struct input_id inputId;
634    if (ioctl(fd, EVIOCGID, &inputId)) {
635        DHLOGE("could not get device input id for %{public}s\n", ConvertErrNo().c_str());
636        RecordSkipDevicePath(device->path);
637        return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
638    }
639    device->identifier.bus = inputId.bustype;
640    device->identifier.product = inputId.product;
641    device->identifier.vendor = inputId.vendor;
642    device->identifier.version = inputId.version;
643    // Get device physical physicalPath.
644    if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
645        DHLOGE("could not get physicalPath for %{public}s\n", ConvertErrNo().c_str());
646    } else {
647        buffer[sizeof(buffer) - 1] = '\0';
648        device->identifier.physicalPath = buffer;
649    }
650    // Get device unique id.
651    if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
652        DHLOGE("could not get idstring for %{public}s\n", ConvertErrNo().c_str());
653    } else {
654        buffer[sizeof(buffer) - 1] = '\0';
655        device->identifier.uniqueId = buffer;
656    }
657
658    QueryEventInfo(fd, device);
659    return DH_SUCCESS;
660}
661
662void InputHub::QueryEventInfo(int fd, std::unique_ptr<Device> &device)
663{
664    if (device == nullptr) {
665        DHLOGE("device is nullptr!");
666        return;
667    }
668    if (IsNeedPrintLog(device->identifier.descriptor)) {
669        DHLOGI("QueryEventInfo: devName: %{public}s, dhId: %{public}s!", device->identifier.name.c_str(),
670            GetAnonyString(device->identifier.descriptor).c_str());
671    }
672    struct libevdev *dev = GetLibEvDev(fd);
673    if (dev == nullptr) {
674        if (IsNeedPrintLog(device->identifier.descriptor)) {
675            DHLOGE("dev is nullptr");
676        }
677        return;
678    }
679    GetEventTypes(dev, device->identifier);
680    GetEventKeys(dev, device->identifier);
681    GetABSInfo(dev, device->identifier);
682    GetRELTypes(dev, device->identifier);
683    GetProperties(dev, device->identifier);
684
685    GetMSCBits(fd, device);
686    GetLEDBits(fd, device);
687    GetSwitchBits(fd, device);
688    GetRepeatBits(fd, device);
689
690    libevdev_free(dev);
691}
692
693void InputHub::GetEventMask(int fd, const std::string &eventName, uint32_t type,
694    std::size_t arrayLength, uint8_t *whichBitMask) const
695{
696    int32_t rc = ioctl(fd, EVIOCGBIT(type, arrayLength), whichBitMask);
697    if (rc < 0) {
698        DHLOGE("Could not get events %{public}s mask: %{public}s", eventName.c_str(), strerror(errno));
699    }
700}
701
702void InputHub::GetMSCBits(int fd, std::unique_ptr<Device> &device)
703{
704    uint8_t mscBitmask[NBYTES(MSC_MAX)] {};
705    GetEventMask(fd, "msc", EV_MSC, sizeof(mscBitmask), mscBitmask);
706
707    for (uint32_t msc = MSC_SERIAL; msc < MSC_MAX; ++msc) {
708        if (TestBit(EV_MSC, device->evBitmask) && TestBit(msc, mscBitmask)) {
709            DHLOGI("Get MSC event: %{public}d", msc);
710            device->identifier.miscellaneous.push_back(msc);
711        }
712    }
713}
714
715void InputHub::GetLEDBits(int fd, std::unique_ptr<Device> &device)
716{
717    uint8_t ledBitmask[NBYTES(LED_MAX)] {};
718    GetEventMask(fd, "led", EV_LED, sizeof(ledBitmask), ledBitmask);
719    for (uint32_t led = LED_NUML; led < LED_MAX; ++led) {
720        if (TestBit(EV_LED, device->evBitmask) && TestBit(led, ledBitmask)) {
721            DHLOGI("Get LED event: %{public}d", led);
722            device->identifier.leds.push_back(led);
723        }
724    }
725}
726
727void InputHub::GetSwitchBits(int fd, std::unique_ptr<Device> &device)
728{
729    uint8_t switchBitmask[NBYTES(SW_MAX)] {};
730    GetEventMask(fd, "switch", EV_SW, sizeof(switchBitmask), switchBitmask);
731
732    for (uint32_t sw = SW_LID; sw < SW_MAX; ++sw) {
733        if (TestBit(EV_SW, device->evBitmask) && TestBit(sw, switchBitmask)) {
734            DHLOGI("Get Switch event: %{public}d", sw);
735            device->identifier.switchs.push_back(sw);
736        }
737    }
738}
739
740void InputHub::GetRepeatBits(int fd, std::unique_ptr<Device> &device)
741{
742    uint8_t repBitmask[NBYTES(REP_MAX)] {};
743    GetEventMask(fd, "repeat", EV_REP, sizeof(repBitmask), repBitmask);
744
745    for (uint32_t rep = REP_DELAY; rep < REP_MAX; ++rep) {
746        if (TestBit(EV_REP, device->evBitmask) && TestBit(rep, repBitmask)) {
747            DHLOGI("Get Repeat event: %{public}d", rep);
748            device->identifier.repeats.push_back(rep);
749        }
750    }
751}
752
753struct libevdev* InputHub::GetLibEvDev(int fd)
754{
755    struct libevdev *dev = nullptr;
756    int rc = 1;
757    rc = libevdev_new_from_fd(fd, &dev);
758    if (rc < 0) {
759        DHLOGE("Failed to init libevdev (%{public}s)", strerror(-rc));
760        return nullptr;
761    }
762    return dev;
763}
764
765void InputHub::GetEventTypes(struct libevdev *dev, InputDevice &identifier)
766{
767    for (uint32_t eventType = 0; eventType < EV_CNT; eventType++) {
768        if (!libevdev_has_event_type(dev, eventType)) {
769            DHLOGD("The device is not support eventType: %{public}d", eventType);
770            continue;
771        }
772        identifier.eventTypes.push_back(eventType);
773    }
774}
775
776int32_t InputHub::GetEventKeys(struct libevdev *dev, InputDevice &identifier)
777{
778    if (!libevdev_has_event_type(dev, EV_KEY)) {
779        if (IsNeedPrintLog(identifier.descriptor)) {
780            DHLOGE("The device doesn't has EV_KEY type!");
781        }
782        return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
783    }
784    for (uint32_t eventKey = 0; eventKey < KEY_CNT; eventKey++) {
785        if (!libevdev_has_event_code(dev, EV_KEY, eventKey)) {
786            DHLOGD("The device is not support eventKey: %{public}d", eventKey);
787            continue;
788        }
789        identifier.eventKeys.push_back(eventKey);
790    }
791    return DH_SUCCESS;
792}
793
794int32_t InputHub::GetABSInfo(struct libevdev *dev, InputDevice &identifier)
795{
796    if (!libevdev_has_event_type(dev, EV_ABS)) {
797        if (IsNeedPrintLog(identifier.descriptor)) {
798            DHLOGE("The device doesn't has EV_ABS type!");
799        }
800        return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
801    }
802    DHLOGI("The device has abs info, devName: %{public}s, dhId: %{public}s!",
803        identifier.name.c_str(), GetAnonyString(identifier.descriptor).c_str());
804    for (uint32_t absType = 0; absType < ABS_CNT; absType++) {
805        if (!libevdev_has_event_code(dev, EV_ABS, absType)) {
806            DHLOGD("The device is not support absType: %{public}d", absType);
807            continue;
808        }
809        identifier.absTypes.push_back(absType);
810        const struct input_absinfo *abs = libevdev_get_abs_info(dev, absType);
811        if (abs == nullptr) {
812            DHLOGE("absInfo is nullptr!");
813            continue;
814        }
815        identifier.absInfos[absType].push_back(abs->value);
816        identifier.absInfos[absType].push_back(abs->minimum);
817        identifier.absInfos[absType].push_back(abs->maximum);
818        identifier.absInfos[absType].push_back(abs->fuzz);
819        identifier.absInfos[absType].push_back(abs->flat);
820        identifier.absInfos[absType].push_back(abs->resolution);
821    }
822    return DH_SUCCESS;
823}
824
825int32_t InputHub::GetRELTypes(struct libevdev *dev, InputDevice &identifier)
826{
827    if (!libevdev_has_event_type(dev, EV_REL)) {
828        if (IsNeedPrintLog(identifier.descriptor)) {
829            DHLOGE("The device doesn't has EV_REL type!");
830        }
831        return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
832    }
833    for (uint32_t code = 0; code < REL_CNT; code++) {
834        if (!libevdev_has_event_code(dev, EV_REL, code)) {
835            DHLOGD("The device is not support rel code: %{public}d", code);
836            continue;
837        }
838        identifier.relTypes.push_back(code);
839    }
840    return DH_SUCCESS;
841}
842
843void InputHub::GetProperties(struct libevdev *dev, InputDevice &identifier)
844{
845    for (uint32_t prop = 0; prop < INPUT_PROP_CNT; prop++) {
846        if (libevdev_has_property(dev, prop)) {
847            DHLOGI("QueryInputDeviceInfo rel prop: %{public}d", prop);
848            identifier.properties.push_back(prop);
849        }
850    }
851}
852
853int32_t InputHub::MakeDevice(int fd, std::unique_ptr<Device> device)
854{
855    // See if this is a multi-touch touchscreen device.
856    if (TestBit(BTN_TOUCH, device->keyBitmask) &&
857        TestBit(ABS_MT_POSITION_X, device->absBitmask) &&
858        TestBit(ABS_MT_POSITION_Y, device->absBitmask)) {
859        QueryLocalTouchScreenInfo(fd, device);
860        device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
861    } else if (TestBit(BTN_TOUCH, device->keyBitmask) &&
862        TestBit(ABS_X, device->absBitmask) &&
863        TestBit(ABS_Y, device->absBitmask)) {
864        QueryLocalTouchScreenInfo(fd, device);
865        device->classes |= INPUT_DEVICE_CLASS_TOUCH;
866    }
867
868    // See if this is a cursor device such as a trackball or mouse.
869    if (TestBit(BTN_MOUSE, device->keyBitmask)
870        && TestBit(REL_X, device->relBitmask)
871        && TestBit(REL_Y, device->relBitmask)) {
872        device->classes |= INPUT_DEVICE_CLASS_CURSOR;
873    }
874
875    // for Linux version 4.14.116, touchpad recognized as mouse and keyboard at same time,
876    // need to avoid device->classes to be 0x09, which mmi can't handler.
877    // See if this is a keyboard.
878    if (device->classes == 0) {
879        bool haveKeyboardKeys = ContainsNonZeroByte(device->keyBitmask, 0, SizeofBitArray(BTN_MISC));
880        if (haveKeyboardKeys) {
881            device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
882        }
883    }
884
885    // If the device isn't recognized as something we handle, don't monitor it.
886    if (device->classes == 0) {
887        if (IsNeedPrintLog(device->identifier.descriptor)) {
888            DHLOGI("Dropping device: name='%{public}s'", device->identifier.name.c_str());
889        }
890        return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
891    }
892
893    if (RegisterDeviceForEpollLocked(*device) != DH_SUCCESS) {
894        return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
895    }
896
897    device->identifier.classes = device->classes;
898
899    DHLOGI("inputType=%{public}d", inputTypes_.load());
900    DHLOGI("New device: fd=%{public}d, name='%{public}s', classes=0x%{public}x", fd, device->identifier.name.c_str(),
901        device->classes);
902
903    AddDeviceLocked(std::move(device));
904    return DH_SUCCESS;
905}
906
907int32_t InputHub::QueryLocalTouchScreenInfo(int fd, std::unique_ptr<Device> &device)
908{
909    LocalTouchScreenInfo info = DInputContext::GetInstance().GetLocalTouchScreenInfo();
910    device->identifier.classes |= INPUT_DEVICE_CLASS_TOUCH_MT;
911    info.localAbsInfo.deviceInfo = device->identifier;
912
913    struct input_absinfo absInfo;
914    ioctl(fd, EVIOCGABS(ABS_MT_POSITION_X), &absInfo);
915    info.localAbsInfo.absXMin = absInfo.minimum;
916    info.localAbsInfo.absXMax = absInfo.maximum;
917    info.localAbsInfo.absMtPositionXMin = absInfo.minimum;
918    info.localAbsInfo.absMtPositionXMax = absInfo.maximum;
919    info.sinkPhyWidth = static_cast<uint32_t>(absInfo.maximum + 1);
920
921    ioctl(fd, EVIOCGABS(ABS_MT_POSITION_Y), &absInfo);
922    info.localAbsInfo.absYMin = absInfo.minimum;
923    info.localAbsInfo.absYMax = absInfo.maximum;
924    info.localAbsInfo.absMtPositionYMin = absInfo.minimum;
925    info.localAbsInfo.absMtPositionYMax = absInfo.maximum;
926    info.sinkPhyHeight = static_cast<uint32_t>(absInfo.maximum + 1);
927
928    ioctl(fd, EVIOCGABS(ABS_PRESSURE), &absInfo);
929    info.localAbsInfo.absPressureMin = absInfo.minimum;
930    info.localAbsInfo.absPressureMax = absInfo.maximum;
931    info.localAbsInfo.absMtPressureMin = absInfo.minimum;
932    info.localAbsInfo.absMtPressureMax = absInfo.maximum;
933
934    ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MAJOR), &absInfo);
935    info.localAbsInfo.absMtTouchMajorMin = absInfo.minimum;
936    info.localAbsInfo.absMtTouchMajorMax = absInfo.maximum;
937
938    ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MINOR), &absInfo);
939    info.localAbsInfo.absMtTouchMinorMin = absInfo.minimum;
940    info.localAbsInfo.absMtTouchMinorMax = absInfo.maximum;
941
942    ioctl(fd, EVIOCGABS(ABS_MT_ORIENTATION), &absInfo);
943    info.localAbsInfo.absMtOrientationMin = absInfo.minimum;
944    info.localAbsInfo.absMtOrientationMax = absInfo.maximum;
945
946    ioctl(fd, EVIOCGABS(ABS_MT_BLOB_ID), &absInfo);
947    info.localAbsInfo.absMtBlobIdMin = absInfo.minimum;
948    info.localAbsInfo.absMtBlobIdMax = absInfo.maximum;
949
950    ioctl(fd, EVIOCGABS(ABS_MT_TRACKING_ID), &absInfo);
951    info.localAbsInfo.absMtTrackingIdMin = absInfo.minimum;
952    info.localAbsInfo.absMtTrackingIdMax = absInfo.maximum;
953
954    DInputContext::GetInstance().SetLocalTouchScreenInfo(info);
955    return DH_SUCCESS;
956}
957
958std::string InputHub::StringPrintf(const char *format, ...) const
959{
960    char space[SPACELENGTH] = {0};
961    va_list ap;
962    va_start(ap, format);
963    std::string result;
964    int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
965    if (ret >= DH_SUCCESS && static_cast<size_t>(ret) < sizeof(space)) {
966        result = space;
967    } else {
968        va_end(ap);
969        return "the buffer is overflow!";
970    }
971    va_end(ap);
972    return result;
973}
974
975void InputHub::GenerateDescriptor(InputDevice &identifier) const
976{
977    std::string rawDescriptor;
978    rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
979        identifier.product);
980    // add handling for USB devices to not uniqueify kbs that show up twice
981    if (!identifier.uniqueId.empty()) {
982        rawDescriptor += "uniqueId:";
983        rawDescriptor += identifier.uniqueId;
984    }
985    if (!identifier.physicalPath.empty()) {
986        rawDescriptor += "physicalPath:";
987        rawDescriptor += identifier.physicalPath;
988    }
989    if (!identifier.name.empty()) {
990        rawDescriptor += "name:";
991        std::string name = identifier.name;
992        rawDescriptor += regex_replace(name, std::regex(" "), "");
993    }
994
995    identifier.descriptor = DH_ID_PREFIX + Sha256(rawDescriptor);
996    if (IsNeedPrintLog(identifier.descriptor)) {
997        DHLOGI("Created descriptor: raw=%{public}s, cooked=%{public}s", rawDescriptor.c_str(),
998            GetAnonyString(identifier.descriptor).c_str());
999    }
1000}
1001
1002int32_t InputHub::RegisterDeviceForEpollLocked(const Device &device)
1003{
1004    int32_t result = RegisterFdForEpoll(device.fd);
1005    if (result != DH_SUCCESS) {
1006        DHLOGE("Could not add input device fd to epoll for device, path: %{public}s", device.path.c_str());
1007        return result;
1008    }
1009    return result;
1010}
1011
1012int32_t InputHub::RegisterFdForEpoll(int fd)
1013{
1014    struct epoll_event eventItem = {};
1015    eventItem.events = EPOLLIN | EPOLLWAKEUP;
1016    eventItem.data.fd = fd;
1017    if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &eventItem)) {
1018        DHLOGE("Could not add fd to epoll instance: %{public}s", ConvertErrNo().c_str());
1019        return -errno;
1020    }
1021    return DH_SUCCESS;
1022}
1023
1024void InputHub::AddDeviceLocked(std::unique_ptr<Device> device)
1025{
1026    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1027    openingDevices_.push_back(std::move(device));
1028}
1029
1030void InputHub::CloseDeviceLocked(Device &device)
1031{
1032    DHLOGI("Removed device: path=%{public}s name=%{public}s fd=%{public}d classes=0x%{public}x",
1033        device.path.c_str(), device.identifier.name.c_str(), device.fd, device.classes);
1034
1035    UnregisterDeviceFromEpollLocked(device);
1036    device.Close();
1037    {
1038        std::lock_guard<std::mutex> devicesLock(devicesMutex_);
1039        closingDevices_.push_back(std::move(devices_[device.path]));
1040        devices_.erase(device.path);
1041    }
1042}
1043
1044void InputHub::CloseDeviceForAllLocked(Device &device)
1045{
1046    DHLOGI("Removed device: path=%{public}s name=%{public}s fd=%{public}d classes=0x%{public}x",
1047        device.path.c_str(), device.identifier.name.c_str(), device.fd, device.classes);
1048
1049    UnregisterDeviceFromEpollLocked(device);
1050    device.Close();
1051    closingDevices_.push_back(std::move(devices_[device.path]));
1052    devices_.erase(device.path);
1053}
1054
1055int32_t InputHub::UnregisterDeviceFromEpollLocked(const Device &device) const
1056{
1057    if (device.HasValidFd()) {
1058        int32_t result = UnregisterFdFromEpoll(device.fd);
1059        if (result != DH_SUCCESS) {
1060            DHLOGE("Could not remove input device fd from epoll for device, path: %{public}s", device.path.c_str());
1061            return result;
1062        }
1063    }
1064    return DH_SUCCESS;
1065}
1066
1067int32_t InputHub::UnregisterFdFromEpoll(int fd) const
1068{
1069    if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr)) {
1070        DHLOGE("Could not remove fd from epoll instance: %{public}s", ConvertErrNo().c_str());
1071        return ERR_DH_INPUT_HUB_UNREGISTER_FD_FAIL;
1072    }
1073    return DH_SUCCESS;
1074}
1075
1076int32_t InputHub::ReadNotifyLocked()
1077{
1078    size_t res;
1079    char eventBuf[EVENT_BUFFER_MAX] = {0};
1080    struct inotify_event *event;
1081
1082    DHLOGI("readNotify nfd: %{public}d\n", iNotifyFd_);
1083    res = static_cast<size_t>(read(iNotifyFd_, eventBuf, sizeof(eventBuf)));
1084    if (res < sizeof(*event)) {
1085        if (errno == EINTR) {
1086            return DH_SUCCESS;
1087        }
1088        DHLOGE("could not get event, %{public}s\n", ConvertErrNo().c_str());
1089        return ERR_DH_INPUT_HUB_GET_EVENT_FAIL;
1090    }
1091
1092    {
1093        size_t eventSize = 0;
1094        size_t eventPos = 0;
1095        while (res >= sizeof(*event) && eventPos < static_cast<size_t>(EVENT_BUFFER_MAX)) {
1096            event = reinterpret_cast<struct inotify_event *>(eventBuf + eventPos);
1097            JudgeDeviceOpenOrClose(*event);
1098            eventSize = sizeof(*event) + event->len;
1099            res -= eventSize;
1100            eventPos += eventSize;
1101        }
1102    }
1103    return DH_SUCCESS;
1104}
1105
1106void InputHub::JudgeDeviceOpenOrClose(const inotify_event &event)
1107{
1108    if (event.len) {
1109        if (event.wd == inputWd_) {
1110            std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
1111            if (event.mask & IN_CREATE) {
1112                OpenInputDeviceLocked(filename);
1113            } else {
1114                DHLOGI("Removing device '%{public}s' due to inotify event\n", filename.c_str());
1115                CloseDeviceByPathLocked(filename);
1116            }
1117        } else {
1118            DHLOGI("Unexpected inotify event, wd = %i", event.wd);
1119        }
1120    }
1121}
1122
1123void InputHub::CloseDeviceByPathLocked(const std::string &devicePath)
1124{
1125    Device* device = GetDeviceByPathLocked(devicePath);
1126    if (device) {
1127        CloseDeviceLocked(*device);
1128        return;
1129    }
1130    DHLOGI("Remove device: %{public}s not found, device may already have been removed.", devicePath.c_str());
1131}
1132
1133void InputHub::CloseAllDevicesLocked()
1134{
1135    DHLOGI("Close All Devices");
1136    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1137    while (!devices_.empty()) {
1138        CloseDeviceForAllLocked(*(devices_.begin()->second));
1139    }
1140}
1141
1142InputHub::Device* InputHub::GetDeviceByPathLocked(const std::string &devicePath)
1143{
1144    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1145    for (const auto &[id, device] : devices_) {
1146        if (device->path == devicePath) {
1147            return device.get();
1148        }
1149    }
1150    return nullptr;
1151}
1152
1153InputHub::Device* InputHub::GetDeviceByFdLocked(int fd)
1154{
1155    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1156    for (const auto &[id, device] : devices_) {
1157        if (device->fd == fd) {
1158            return device.get();
1159        }
1160    }
1161    return nullptr;
1162}
1163
1164InputHub::Device* InputHub::GetSupportDeviceByFd(int fd)
1165{
1166    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1167    for (const auto &[id, device] : devices_) {
1168        if (device != nullptr && device->fd == fd) {
1169            return device.get();
1170        }
1171    }
1172    return nullptr;
1173}
1174
1175bool InputHub::ContainsNonZeroByte(const uint8_t *array, uint32_t startIndex, uint32_t endIndex)
1176{
1177    const uint8_t* end = array + endIndex;
1178    array += startIndex;
1179    while (array != end) {
1180        if (*(array++) != 0) {
1181            return true;
1182        }
1183    }
1184    return false;
1185}
1186
1187int64_t InputHub::ProcessEventTimestamp(const input_event &event)
1188{
1189    const int64_t inputEventTime = event.input_event_sec * 1000000000LL + event.input_event_usec * 1000LL;
1190    return inputEventTime;
1191}
1192
1193bool InputHub::TestBit(uint32_t bit, const uint8_t *array)
1194{
1195    constexpr int units = 8;
1196    return (array)[(bit) / units] & (1 << ((bit) % units));
1197}
1198
1199uint32_t InputHub::SizeofBitArray(uint32_t bit)
1200{
1201    constexpr int round = 7;
1202    constexpr int divisor = 8;
1203    return ((bit) + round) / divisor;
1204}
1205
1206void InputHub::SaveAffectDhId(bool isEnable, const std::string &dhId, AffectDhIds &affDhIds)
1207{
1208    if (isEnable) {
1209        affDhIds.sharingDhIds.push_back(dhId);
1210    } else {
1211        affDhIds.noSharingDhIds.push_back(dhId);
1212    }
1213}
1214
1215AffectDhIds InputHub::SetSupportInputType(bool enabled, const uint32_t &inputTypes)
1216{
1217    AffectDhIds affDhIds;
1218    inputTypes_ = inputTypes;
1219    DHLOGI("SetSupportInputType: inputTypes=0x%x,", inputTypes_.load());
1220    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1221    for (const auto &[id, device] : devices_) {
1222        if (device->classes & inputTypes_) {
1223            device->isShare = enabled;
1224            DHLOGW("ByType dhid:%{public}s, isshare:%{public}d",
1225                GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1226            SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1227        }
1228    }
1229
1230    return affDhIds;
1231}
1232
1233AffectDhIds InputHub::SetSharingDevices(bool enabled, std::vector<std::string> dhIds)
1234{
1235    AffectDhIds affDhIds;
1236    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1237    DHLOGI("SetSharingDevices start");
1238    for (auto dhId : dhIds) {
1239        DHLOGI("SetSharingDevices dhId: %{public}s, size: %{public}zu, enabled: %{public}d",
1240            GetAnonyString(dhId).c_str(), devices_.size(), enabled);
1241        sharedDHIds_[dhId] = enabled;
1242        for (const auto &[id, device] : devices_) {
1243            DHLOGI("deviceName %{public}s ,dhId: %{public}s ", device->identifier.name.c_str(),
1244                GetAnonyString(device->identifier.descriptor).c_str());
1245            if (device->identifier.descriptor == dhId) {
1246                device->isShare = enabled;
1247                DHLOGW("dhid:%{public}s, isshare:%{public}d",
1248                    GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1249                SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1250                break;
1251            }
1252        }
1253    }
1254    DHLOGI("SetSharingDevices end");
1255    return affDhIds;
1256}
1257
1258std::vector<std::string> InputHub::GetSharingDevices()
1259{
1260    std::vector<std::string> sharingDevices;
1261    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1262    for (const auto &[id, device] : devices_) {
1263        if (device->isShare) {
1264            DHLOGI("Find sharing dhid: %{public}s", GetAnonyString(device->identifier.descriptor).c_str());
1265            sharingDevices.push_back(device->identifier.descriptor);
1266        }
1267    }
1268    return sharingDevices;
1269}
1270
1271void InputHub::GetSharedMousePathByDhId(const std::vector<std::string> &dhIds, std::string &sharedMousePath,
1272    std::string &sharedMouseDhId)
1273{
1274    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1275    DHLOGI("GetSharedMousePathByDhId: devices_.size:%{public}zu,", devices_.size());
1276    for (const auto &dhId : dhIds) {
1277        for (const auto &[id, device] : devices_) {
1278            if (device == nullptr) {
1279                DHLOGE("device is nullptr");
1280                continue;
1281            }
1282            DHLOGI("descriptor:%{public}s, isShare[%{public}d], type[%{public}d]",
1283                GetAnonyString(device->identifier.descriptor).c_str(), device->isShare, device->classes);
1284            if ((device->identifier.descriptor == dhId) && ((device->classes & INPUT_DEVICE_CLASS_CURSOR) != 0 ||
1285                (device->classes & INPUT_DEVICE_CLASS_TOUCH) != 0 ||
1286                ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0 && IsTouchPad(device->identifier)))) {
1287                sharedMouseDhId = dhId;
1288                sharedMousePath = device->path;
1289                return; // return First shared mouse
1290            }
1291        }
1292    }
1293}
1294
1295void InputHub::GetSharedKeyboardPathsByDhIds(const std::vector<std::string> &dhIds,
1296    std::vector<std::string> &sharedKeyboardPaths, std::vector<std::string> &sharedKeyboardDhIds)
1297{
1298    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1299    DHLOGI("GetSharedKeyboardPathsByDhIds: devices_.size:%{public}zu,", devices_.size());
1300    for (const auto &dhId : dhIds) {
1301        for (const auto &[id, device] : devices_) {
1302            if (device == nullptr) {
1303                DHLOGE("device is nullptr");
1304                continue;
1305            }
1306            DHLOGI("descriptor:%{public}s, isShare[%{public}d], type[%{public}d]",
1307                GetAnonyString(device->identifier.descriptor).c_str(), device->isShare, device->classes);
1308            if ((device->identifier.descriptor == dhId) &&
1309                ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1310                sharedKeyboardDhIds.push_back(dhId);
1311                sharedKeyboardPaths.push_back(device->path);
1312            }
1313        }
1314    }
1315}
1316
1317void InputHub::GetDevicesInfoByType(const uint32_t inputTypes, std::map<int32_t, std::string> &datas)
1318{
1319    uint32_t dhType = 0;
1320
1321    if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::MOUSE)) != 0) {
1322        dhType |= INPUT_DEVICE_CLASS_CURSOR;
1323    }
1324
1325    if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::KEYBOARD)) != 0) {
1326        dhType |= INPUT_DEVICE_CLASS_KEYBOARD;
1327    }
1328
1329    if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::TOUCHSCREEN)) != 0) {
1330        dhType |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
1331    }
1332
1333    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1334    for (const auto &[id, device] : devices_) {
1335        if (device->classes & dhType) {
1336            datas.insert(std::pair<int32_t, std::string>(device->fd, device->identifier.descriptor));
1337        }
1338    }
1339}
1340
1341void InputHub::GetDevicesInfoByDhId(std::vector<std::string> dhidsVec, std::map<int32_t, std::string> &datas)
1342{
1343    for (auto dhId : dhidsVec) {
1344        std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1345        for (const auto &[id, device] : devices_) {
1346            if (device->identifier.descriptor == dhId) {
1347                datas.insert(std::pair<int32_t, std::string>(device->fd, dhId));
1348            }
1349        }
1350    }
1351}
1352
1353bool InputHub::IsAllDevicesStoped()
1354{
1355    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1356    for (const auto &[dhId, isShared] : sharedDHIds_) {
1357        DHLOGI("the dhId: %{public}s, isShared: %{public}d", GetAnonyString(dhId).c_str(), isShared);
1358        if (isShared) {
1359            return false;
1360        }
1361    }
1362    return true;
1363}
1364
1365void InputHub::RecordDeviceLog(const std::string &devicePath, const InputDevice &identifier)
1366{
1367    if (IsNeedPrintLog(identifier.descriptor)) {
1368        DHLOGI("add device: %{public}s\n", devicePath.c_str());
1369        DHLOGI("  bus:        %{public}04x\n"
1370               "  vendor      %{public}04x\n"
1371               "  product     %{public}04x\n"
1372               "  version     %{public}04x\n",
1373               identifier.bus, identifier.vendor, identifier.product, identifier.version);
1374        DHLOGI("  name:       \"%{public}s\"\n", identifier.name.c_str());
1375        DHLOGI("  physicalPath:   \"%{public}s\"\n", identifier.physicalPath.c_str());
1376        DHLOGI("  unique id:  \"%{public}s\"\n", identifier.uniqueId.c_str());
1377        DHLOGI("  descriptor: \"%{public}s\"\n", GetAnonyString(identifier.descriptor).c_str());
1378    }
1379}
1380
1381void InputHub::RecordChangeEventLog(const RawEvent &event)
1382{
1383    std::string eventType = "";
1384    switch (event.type) {
1385        case EV_KEY:
1386            eventType = "EV_KEY";
1387            break;
1388        case EV_REL:
1389            eventType = "EV_REL";
1390            break;
1391        case EV_ABS:
1392            eventType = "EV_ABS";
1393            break;
1394        case EV_SYN:
1395            eventType = "EV_SYN";
1396            break;
1397        default:
1398            eventType = "other type " + std::to_string(event.type);
1399            break;
1400    }
1401    DHLOGI("0.E2E-Test Sink collect change event, EventType: %{public}s, Code: %{public}d, Value: %{public}d, "
1402        "Path: %{public}s, descriptor: %{public}s, When: %{public}" PRId64 "", eventType.c_str(), event.code,
1403        event.value, event.path.c_str(), GetAnonyString(event.descriptor).c_str(), event.when);
1404}
1405
1406void InputHub::RecordEventLog(const RawEvent *event)
1407{
1408    std::string eventType = "";
1409    switch (event->type) {
1410        case EV_KEY:
1411            eventType = "EV_KEY";
1412            break;
1413        case EV_REL:
1414            eventType = "EV_REL";
1415            break;
1416        case EV_ABS:
1417            eventType = "EV_ABS";
1418            break;
1419        case EV_SYN:
1420            eventType = "EV_SYN";
1421            break;
1422        default:
1423            eventType = "other type " + std::to_string(event->type);
1424            break;
1425    }
1426    DHLOGD("1.E2E-Test Sink collect event, EventType: %{public}s, Code: %{public}d, Value: %{public}d, "
1427        "Path: %{public}s, descriptor: %{public}s, When: %{public}" PRId64 "", eventType.c_str(), event->code,
1428        event->value, event->path.c_str(), GetAnonyString(event->descriptor).c_str(), event->when);
1429}
1430
1431void InputHub::HandleTouchScreenEvent(struct input_event readBuffer[], const size_t count,
1432    std::vector<bool> &needFilted)
1433{
1434    std::vector<std::pair<size_t, size_t>> absIndexs;
1435    int32_t firstIndex = -1;
1436    int32_t lastIndex = -1;
1437
1438    for (size_t i = 0; i < count; i++) {
1439        struct input_event& iev = readBuffer[i];
1440        if ((iev.type == EV_ABS) && (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X)) {
1441            firstIndex = static_cast<int32_t>(i);
1442        } else if (iev.type  == EV_SYN) {
1443            lastIndex = static_cast<int32_t>(i);
1444        }
1445        if ((firstIndex >= 0) && (lastIndex > firstIndex)) {
1446            absIndexs.emplace_back(std::make_pair((size_t)firstIndex, (size_t)lastIndex));
1447        }
1448    }
1449
1450    AbsInfo absInfo = {
1451        .absX = 0,
1452        .absY = 0,
1453        .absXIndex = -1,
1454        .absYIndex = -1,
1455    };
1456    for (auto iter : absIndexs) {
1457        absInfo.absXIndex = -1;
1458        absInfo.absYIndex = -1;
1459
1460        for (size_t j = iter.first; j <= iter.second; j++) {
1461            struct input_event &iev = readBuffer[j];
1462            if (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X) {
1463                absInfo.absX = static_cast<uint32_t>(iev.value);
1464                absInfo.absXIndex = static_cast<int32_t>(j);
1465            }
1466            if (iev.code == ABS_Y || iev.code == ABS_MT_POSITION_Y) {
1467                absInfo.absY = static_cast<uint32_t>(iev.value);
1468                absInfo.absYIndex = static_cast<int32_t>(j);
1469            }
1470        }
1471
1472        if ((absInfo.absXIndex < 0) || (absInfo.absYIndex < 0)) {
1473            for (size_t j = iter.first; j <= iter.second; j++) {
1474                needFilted[j] = true;
1475            }
1476            continue;
1477        }
1478        if (!CheckTouchPointRegion(readBuffer, absInfo)) {
1479            for (size_t j = iter.first; j <= iter.second; j++) {
1480                needFilted[j] = true;
1481            }
1482        }
1483    }
1484}
1485
1486bool InputHub::CheckTouchPointRegion(struct input_event readBuffer[], const AbsInfo &absInfo)
1487{
1488    auto sinkInfos = DInputContext::GetInstance().GetAllSinkScreenInfo();
1489
1490    for (const auto &[id, sinkInfo] : sinkInfos) {
1491        auto info = sinkInfo.transformInfo;
1492        if ((absInfo.absX >= info.sinkWinPhyX) && (absInfo.absX <= (info.sinkWinPhyX + info.sinkProjPhyWidth))
1493            && (absInfo.absY >= info.sinkWinPhyY) && (absInfo.absY <= (info.sinkWinPhyY + info.sinkProjPhyHeight))) {
1494            touchDescriptor = sinkInfo.srcScreenInfo.sourcePhyId;
1495            readBuffer[absInfo.absXIndex].value = (absInfo.absX - info.sinkWinPhyX) * info.coeffWidth;
1496            readBuffer[absInfo.absYIndex].value = (absInfo.absY - info.sinkWinPhyY) * info.coeffHeight;
1497            return true;
1498        }
1499    }
1500    return false;
1501}
1502
1503std::vector<InputHub::Device*> InputHub::CollectTargetDevices()
1504{
1505    std::lock_guard<std::mutex> deviceLock(devicesMutex_);
1506    std::vector<InputHub::Device*> tarVec;
1507    for (const auto &dev : devices_) {
1508        if (((dev.second->classes & INPUT_DEVICE_CLASS_TOUCH) != 0) ||
1509            ((dev.second->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0) ||
1510            ((dev.second->classes & INPUT_DEVICE_CLASS_CURSOR) != 0) ||
1511            ((dev.second->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1512            DHLOGI("Find target devs need check stat, path: %{public}s, name: %{public}s",
1513                dev.first.c_str(), dev.second->identifier.name.c_str());
1514            tarVec.push_back(dev.second.get());
1515        }
1516    }
1517
1518    return tarVec;
1519}
1520
1521void InputHub::SavePressedKeyState(const InputHub::Device *dev, int32_t keyCode)
1522{
1523    struct RawEvent event = {
1524        .type = EV_KEY,
1525        .code = keyCode,
1526        .value = KEY_DOWN_STATE,
1527        .descriptor = dev->identifier.descriptor,
1528        .path = dev->path
1529    };
1530    DInputSinkState::GetInstance().AddKeyDownState(event);
1531    DHLOGI("Find Pressed key: %{public}d, device path: %{public}s, dhId: %{public}s", keyCode, dev->path.c_str(),
1532        GetAnonyString(dev->identifier.descriptor).c_str());
1533}
1534
1535bool InputHub::IsLengthExceeds(const unsigned long *keyState, const unsigned long len, int keyIndex)
1536{
1537    if (len < (keyIndex / LONG_BITS) + 1) {
1538        DHLOGE("Length exceeds for key index: %{public}d", keyIndex);
1539        return true;
1540    }
1541    return false;
1542}
1543
1544void InputHub::CheckTargetKeyState(const InputHub::Device *dev, const unsigned long *keyState, const unsigned long len)
1545{
1546    // If device is a mouse, record the mouse pressed key.
1547    if ((dev->classes & INPUT_DEVICE_CLASS_CURSOR) != 0) {
1548        if (IsLengthExceeds(keyState, len, BTN_LEFT)) {
1549            return;
1550        }
1551        int mouseLeftBtnState = BitIsSet(keyState, BTN_LEFT);
1552        if (mouseLeftBtnState != 0) {
1553            SavePressedKeyState(dev, BTN_LEFT);
1554        }
1555        if (IsLengthExceeds(keyState, len, BTN_RIGHT)) {
1556            return;
1557        }
1558        int mouseRightBtnState = BitIsSet(keyState, BTN_RIGHT);
1559        if (mouseRightBtnState != 0) {
1560            SavePressedKeyState(dev, BTN_RIGHT);
1561        }
1562        if (IsLengthExceeds(keyState, len, BTN_MIDDLE)) {
1563            return;
1564        }
1565        int mouseMidBtnState = BitIsSet(keyState, BTN_MIDDLE);
1566        if (mouseMidBtnState != 0) {
1567            SavePressedKeyState(dev, BTN_MIDDLE);
1568        }
1569    }
1570
1571    // If device is a keyboard, record all the pressed keys.
1572    if ((dev->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
1573        for (int32_t keyIndex = 0; keyIndex < KEY_MAX; keyIndex++) {
1574            if (IsLengthExceeds(keyState, len, keyIndex)) {
1575                return;
1576            }
1577            if (BitIsSet(keyState, keyIndex) != 0) {
1578                SavePressedKeyState(dev, keyIndex);
1579            }
1580        }
1581    }
1582
1583    // If device is a touchscreen or touchpad, record the touch event.
1584    if ((dev->classes & INPUT_DEVICE_CLASS_TOUCH) != 0 || (dev->classes & INPUT_DEVICE_CLASS_TOUCH_MT) != 0) {
1585        if (IsLengthExceeds(keyState, len, BTN_TOUCH)) {
1586            return;
1587        }
1588        int btnTouchState = BitIsSet(keyState, BTN_TOUCH);
1589        if (btnTouchState != 0) {
1590            SavePressedKeyState(dev, BTN_TOUCH);
1591        }
1592    }
1593}
1594
1595
1596void InputHub::CheckTargetDevicesState(std::vector<InputHub::Device*> targetDevices)
1597{
1598    uint32_t count = 0;
1599    unsigned long keyState[NLONGS(KEY_CNT)] = { 0 };
1600    for (const auto *dev : targetDevices) {
1601        while (true) {
1602            if (count > READ_RETRY_MAX) {
1603                break;
1604            }
1605            // Query all key state
1606            int rc = ioctl(dev->fd, EVIOCGKEY(sizeof(keyState)), keyState);
1607            if (rc < 0) {
1608                DHLOGE("read all key state failed, rc=%{public}d", rc);
1609                count += 1;
1610                std::this_thread::sleep_for(std::chrono::milliseconds(READ_SLEEP_TIME_MS));
1611                continue;
1612            }
1613            CheckTargetKeyState(dev, keyState, NLONGS(KEY_CNT));
1614            break;
1615        }
1616    }
1617}
1618
1619void InputHub::RecordDeviceStates()
1620{
1621    DHLOGI("Start Record keys states");
1622    ScanAndRecordInputDevices();
1623    std::vector<InputHub::Device*> tarDevices = CollectTargetDevices();
1624    DHLOGI("Check target states device num: %{public}zu", tarDevices.size());
1625    CheckTargetDevicesState(tarDevices);
1626    DHLOGI("Finish Record Keys states");
1627}
1628
1629void InputHub::ClearDeviceStates()
1630{
1631    DHLOGI("Clear Device state");
1632    DInputSinkState::GetInstance().ClearDeviceStates();
1633}
1634
1635void InputHub::ClearSkipDevicePaths()
1636{
1637    DHLOGI("Clear Skip device path");
1638    std::lock_guard<std::mutex> lock(skipDevicePathsMutex_);
1639    skipDevicePaths_.clear();
1640}
1641
1642InputHub::Device::Device(int fd, const std::string &path)
1643    : next(nullptr), fd(fd), path(path), identifier({}), classes(0), enabled(false),
1644      isShare(false), isVirtual(fd < 0) {
1645    // Figure out the kinds of events the device reports.
1646    DHLOGI("Ctor Device for get event mask, fd: %{public}d, path: %{public}s", fd, path.c_str());
1647    ioctl(fd, EVIOCGBIT(0, sizeof(evBitmask)), evBitmask);
1648    ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keyBitmask)), keyBitmask);
1649    ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absBitmask)), absBitmask);
1650    ioctl(fd, EVIOCGBIT(EV_REL, sizeof(relBitmask)), relBitmask);
1651}
1652
1653InputHub::Device::~Device()
1654{
1655    Close();
1656}
1657
1658void InputHub::Device::Close()
1659{
1660    if (fd >= 0) {
1661        ::close(fd);
1662        fd = UN_INIT_FD_VALUE;
1663    }
1664}
1665
1666int32_t InputHub::Device::Enable()
1667{
1668    char canonicalPath[PATH_MAX + 1] = {0x00};
1669
1670    if (path.length() == 0 || path.length() > PATH_MAX || realpath(path.c_str(), canonicalPath) == nullptr) {
1671        DHLOGE("path check fail, error path: %{public}s", path.c_str());
1672        return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1673    }
1674    fd = open(canonicalPath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
1675    if (fd < 0) {
1676        DHLOGE("could not open %{public}s, %{public}s\n", path.c_str(), ConvertErrNo().c_str());
1677        return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1678    }
1679    enabled = true;
1680    return DH_SUCCESS;
1681}
1682
1683int32_t InputHub::Device::Disable()
1684{
1685    Close();
1686    enabled = false;
1687    return DH_SUCCESS;
1688}
1689
1690bool InputHub::Device::HasValidFd() const
1691{
1692    return !isVirtual && enabled;
1693}
1694} // namespace DistributedInput
1695} // namespace DistributedHardware
1696} // namespace OHOS
1697