• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 <unistd.h>
29 #include <utility>
30 
31 #include "constants_dinput.h"
32 #include "dinput_context.h"
33 #include "dinput_errcode.h"
34 #include "dinput_log.h"
35 #include "dinput_utils_tool.h"
36 
37 namespace OHOS {
38 namespace DistributedHardware {
39 namespace DistributedInput {
40 namespace {
41 const uint32_t SLEEP_TIME_US = 100 * 1000;
42 }
43 
InputHub()44 InputHub::InputHub() : epollFd_(0), iNotifyFd_(0), inputWd_(0), needToScanDevices_(true), nextDeviceId_(1),
45     mPendingEventItems{}, pendingEventCount_(0), pendingEventIndex_(0), pendingINotify_(false), deviceChanged_(false),
46     inputTypes_(0), isStartCollectEvent_(false), isStartCollectHandler_(false)
47 {
48     Initialize();
49 }
50 
~InputHub()51 InputHub::~InputHub()
52 {
53     Release();
54 }
55 
Initialize()56 int32_t InputHub::Initialize()
57 {
58     epollFd_ = epoll_create1(EPOLL_CLOEXEC);
59     if (epollFd_ < 0) {
60         DHLOGE("Could not create epoll instance: %s", ConvertErrNo().c_str());
61         return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
62     }
63 
64     iNotifyFd_ = inotify_init();
65     inputWd_ = inotify_add_watch(iNotifyFd_, DEVICE_PATH, IN_DELETE | IN_CREATE);
66     if (inputWd_ < 0) {
67         DHLOGE(
68             "Could not register INotify for %s: %s", DEVICE_PATH, ConvertErrNo().c_str());
69         return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
70     }
71 
72     struct epoll_event eventItem = {};
73     eventItem.events = EPOLLIN;
74     eventItem.data.fd = iNotifyFd_;
75     int result = epoll_ctl(epollFd_, EPOLL_CTL_ADD, iNotifyFd_, &eventItem);
76     if (result != 0) {
77         DHLOGE("Could not add INotify to epoll instance.  errno=%d", errno);
78         return ERR_DH_INPUT_HUB_EPOLL_INIT_FAIL;
79     }
80 
81     return DH_SUCCESS;
82 }
83 
Release()84 int32_t InputHub::Release()
85 {
86     CloseAllDevicesLocked();
87 
88     ::close(epollFd_);
89     ::close(iNotifyFd_);
90     StopCollectInputEvents();
91     StopCollectInputHandler();
92     sharedDHIds_.clear();
93     return DH_SUCCESS;
94 }
95 
StartCollectInputEvents(RawEvent * buffer,size_t bufferSize)96 size_t InputHub::StartCollectInputEvents(RawEvent *buffer, size_t bufferSize)
97 {
98     size_t count = 0;
99     isStartCollectEvent_ = true;
100     while (isStartCollectEvent_) {
101         if (needToScanDevices_) {
102             needToScanDevices_ = false;
103             ScanInputDevices(DEVICE_PATH);
104         }
105         {
106             std::unique_lock<std::mutex> deviceLock(devicesMutex_);
107             while (!openingDevices_.empty()) {
108                 std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
109                 openingDevices_.pop_back();
110                 DHLOGI("Reporting device opened: id=%s, name=%s\n",
111                     GetAnonyInt32(device->id).c_str(), device->path.c_str());
112                 auto [dev_it, inserted] = devices_.insert_or_assign(device->id, std::move(device));
113                 if (!inserted) {
114                     DHLOGI("Device id %s exists, replaced. \n", GetAnonyInt32(device->id).c_str());
115                 }
116             }
117         }
118 
119         deviceChanged_ = false;
120         count = GetEvents(buffer, bufferSize);
121         // readNotify() will modify the list of devices so this must be done after
122         // processing all other events to ensure that we read all remaining events
123         // before closing the devices.
124         if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
125             pendingINotify_ = false;
126             ReadNotifyLocked();
127             deviceChanged_ = true;
128         }
129 
130         // Report added or removed devices immediately.
131         if (deviceChanged_) {
132             continue;
133         }
134 
135         if (count > 0) {
136             break;
137         }
138 
139         if (RefreshEpollItem(false) < 0) {
140             break;
141         }
142     }
143 
144     // All done, return the number of events we read.
145     return count;
146 }
147 
StopCollectInputEvents()148 void InputHub::StopCollectInputEvents()
149 {
150     DHLOGI("Stop Collect Input Events Thread");
151     isStartCollectEvent_ = false;
152 }
153 
GetEvents(RawEvent * buffer,size_t bufferSize)154 size_t InputHub::GetEvents(RawEvent *buffer, size_t bufferSize)
155 {
156     RawEvent* event = buffer;
157     size_t capacity = bufferSize;
158     while (pendingEventIndex_ < pendingEventCount_) {
159         std::unique_lock<std::mutex> my_lock(operationMutex_);
160         const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
161         if (eventItem.data.fd == iNotifyFd_) {
162             if (eventItem.events & EPOLLIN) {
163                 pendingINotify_ = true;
164             } else {
165                 DHLOGI("Received no epoll event 0x%08x.", eventItem.events);
166             }
167             continue;
168         }
169         struct input_event readBuffer[bufferSize];
170         int32_t readSize = read(eventItem.data.fd, readBuffer, sizeof(struct input_event) * capacity);
171         size_t count = ReadInputEvent(readSize, *GetDeviceByFdLocked(eventItem.data.fd));
172         Device* device = GetSupportDeviceByFd(eventItem.data.fd);
173         if (!device) {
174             continue;
175         }
176         if (!sharedDHIds_[device->identifier.descriptor]) {
177             continue;
178         }
179         DHLOGD("shared device dhId: %s, name: %s", GetAnonyString(device->identifier.descriptor).c_str(),
180             device->identifier.name.c_str());
181         if (eventItem.events & EPOLLIN) {
182             event += CollectEvent(event, capacity, device, readBuffer, count);
183 
184             if (capacity == 0) {
185                 pendingEventIndex_ -= 1;
186                 break;
187             }
188         } else if (eventItem.events & EPOLLHUP) {
189             DHLOGI("Removing device %s due to epoll hang-up event.", device->identifier.name.c_str());
190             deviceChanged_ = true;
191             CloseDeviceLocked(*device);
192         }
193     }
194     return event - buffer;
195 }
196 
IsTouchPad(const InputDevice & inputDevice)197 bool InputHub::IsTouchPad(const InputDevice &inputDevice)
198 {
199     std::string dhName = inputDevice.name;
200     DHLOGI("device name is %s.", dhName.c_str());
201     transform(dhName.begin(), dhName.end(), dhName.begin(), ::tolower);
202     if (dhName.find(DH_TOUCH_PAD) == std::string::npos) {
203         return false;
204     }
205     return true;
206 }
207 
CollectEvent(RawEvent * buffer,size_t & capacity,Device * device,struct input_event readBuffer[],const size_t count)208 size_t InputHub::CollectEvent(RawEvent *buffer, size_t &capacity, Device *device, struct input_event readBuffer[],
209     const size_t count)
210 {
211     std::vector<bool> needFilted(capacity, false);
212     bool isTouchEvent = false;
213     if ((device->classes & INPUT_DEVICE_CLASS_TOUCH_MT) || (device->classes & INPUT_DEVICE_CLASS_TOUCH)) {
214         if (!IsTouchPad(device->identifier)) {
215             isTouchEvent = true;
216             HandleTouchScreenEvent(readBuffer, count, needFilted);
217         }
218     }
219 
220     RawEvent* event = buffer;
221     for (size_t i = 0; i < count; i++) {
222         if (needFilted[i]) {
223             continue;
224         }
225         const struct input_event& iev = readBuffer[i];
226         event->when = ProcessEventTimestamp(iev);
227         event->type = iev.type;
228         event->code = iev.code;
229         event->value = iev.value;
230         event->path = device->path;
231         event->descriptor = isTouchEvent ? touchDescriptor : device->identifier.descriptor;
232         RecordEventLog(event);
233         event += 1;
234         capacity -= 1;
235     }
236     return event - buffer;
237 }
238 
ReadInputEvent(int32_t readSize,Device & device)239 size_t InputHub::ReadInputEvent(int32_t readSize, Device &device)
240 {
241     size_t count = 0;
242     if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
243         // Device was removed before INotify noticed.
244         DHLOGE("could not get event, removed? (fd: %d size: %d"
245             " errno: %d)\n",
246             device.fd, readSize, errno);
247         deviceChanged_ = true;
248         CloseDeviceLocked(device);
249     } else if (readSize < 0) {
250         if (errno != EAGAIN && errno != EINTR) {
251             DHLOGW("could not get event (errno=%d)", errno);
252         }
253     } else if ((readSize % sizeof(struct input_event)) != 0) {
254         DHLOGW("could not get event (wrong size: %d)", readSize);
255     } else {
256         count = size_t(readSize) / sizeof(struct input_event);
257         return count;
258     }
259     return count;
260 }
261 
DeviceIsExists(InputDeviceEvent * buffer,size_t bufferSize)262 size_t InputHub::DeviceIsExists(InputDeviceEvent *buffer, size_t bufferSize)
263 {
264     InputDeviceEvent* event = buffer;
265     size_t capacity = bufferSize;
266     // Report any devices that had last been added/removed.
267     {
268         std::unique_lock<std::mutex> deviceLock(devicesMutex_);
269         for (auto it = closingDevices_.begin(); it != closingDevices_.end();) {
270             std::unique_ptr<Device> device = std::move(*it);
271             DHLOGI("Reporting device closed: id=%s, name=%s\n",
272                 GetAnonyInt32(device->id).c_str(), device->path.c_str());
273             event->type = DeviceType::DEVICE_REMOVED;
274             event->deviceInfo = device->identifier;
275             event += 1;
276             it = closingDevices_.erase(it);
277             if (capacity == 0) {
278                 break;
279             }
280             capacity--;
281         }
282     }
283 
284     if (needToScanDevices_) {
285         needToScanDevices_ = false;
286         ScanInputDevices(DEVICE_PATH);
287     }
288 
289     {
290         std::unique_lock<std::mutex> deviceLock(devicesMutex_);
291         while (!openingDevices_.empty()) {
292             std::unique_ptr<Device> device = std::move(*openingDevices_.rbegin());
293             openingDevices_.pop_back();
294             DHLOGI("Reporting device opened: id=%s, name=%s\n",
295                 GetAnonyInt32(device->id).c_str(), device->path.c_str());
296             event->type = DeviceType::DEVICE_ADDED;
297             event->deviceInfo = device->identifier;
298             event += 1;
299 
300             auto [dev_it, inserted] = devices_.insert_or_assign(device->id, std::move(device));
301             if (!inserted) {
302                 DHLOGI("Device id %s exists, replaced. \n", GetAnonyInt32(device->id).c_str());
303             }
304             if (capacity == 0) {
305                 break;
306             }
307             capacity--;
308         }
309     }
310     return event - buffer;
311 }
312 
StartCollectInputHandler(InputDeviceEvent * buffer,size_t bufferSize)313 size_t InputHub::StartCollectInputHandler(InputDeviceEvent *buffer, size_t bufferSize)
314 {
315     size_t count = 0;
316     isStartCollectHandler_ = true;
317     while (isStartCollectHandler_) {
318         count = DeviceIsExists(buffer, bufferSize);
319         deviceChanged_ = false;
320         GetDeviceHandler();
321 
322         if (pendingINotify_ && pendingEventIndex_ >= pendingEventCount_) {
323             pendingINotify_ = false;
324             ReadNotifyLocked();
325             deviceChanged_ = true;
326         }
327 
328         // Report added or removed devices immediately.
329         if (deviceChanged_) {
330             continue;
331         }
332         if (count > 0) {
333             break;
334         }
335         if (RefreshEpollItem(true) < 0) {
336             break;
337         }
338     }
339 
340     // All done, return the number of events we read.
341     return count;
342 }
343 
StopCollectInputHandler()344 void InputHub::StopCollectInputHandler()
345 {
346     DHLOGI("Stop Collect Input Handler Thread");
347     isStartCollectHandler_ = false;
348 }
349 
GetDeviceHandler()350 void InputHub::GetDeviceHandler()
351 {
352     while (pendingEventIndex_ < pendingEventCount_) {
353         std::unique_lock<std::mutex> my_lock(operationMutex_);
354         const struct epoll_event& eventItem = mPendingEventItems[pendingEventIndex_++];
355         if (eventItem.data.fd == iNotifyFd_) {
356             if (eventItem.events & EPOLLIN) {
357                 pendingINotify_ = true;
358             } else {
359                 DHLOGI(
360                     "Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
361             }
362             continue;
363         }
364 
365         Device* device = GetDeviceByFdLocked(eventItem.data.fd);
366         if (!device) {
367             DHLOGE(
368                 "Received unexpected epoll event 0x%08x for unknown fd %d.",
369                 eventItem.events, eventItem.data.fd);
370             continue;
371         }
372 
373         if (eventItem.events & EPOLLHUP) {
374             DHLOGI("Removing device %s due to epoll hang-up event.",
375                 device->identifier.name.c_str());
376             deviceChanged_ = true;
377             CloseDeviceLocked(*device);
378         }
379     }
380 }
381 
RefreshEpollItem(bool isSleep)382 int32_t InputHub::RefreshEpollItem(bool isSleep)
383 {
384     pendingEventIndex_ = 0;
385     int pollResult = epoll_wait(epollFd_, mPendingEventItems, EPOLL_MAX_EVENTS, EPOLL_WAITTIME);
386     if (pollResult == 0) {
387         // Timed out.
388         pendingEventCount_ = 0;
389         return ERR_DH_INPUT_HUB_EPOLL_WAIT_TIMEOUT;
390     }
391 
392     if (pollResult < 0) {
393         // An error occurred.
394         pendingEventCount_ = 0;
395 
396         // Sleep after errors to avoid locking up the system.
397         // Hopefully the error is transient.
398         if (errno != EINTR) {
399             DHLOGE("poll failed (errno=%d)\n", errno);
400             usleep(SLEEP_TIME_US);
401         }
402     } else {
403         // Some events occurred.
404         pendingEventCount_ = pollResult;
405     }
406     if (isSleep) {
407         usleep(SLEEP_TIME_US);
408     }
409     return DH_SUCCESS;
410 }
411 
GetAllInputDevices()412 std::vector<InputDevice> InputHub::GetAllInputDevices()
413 {
414     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
415     std::vector<InputDevice> vecDevice;
416     for (const auto& [id, device] : devices_) {
417         vecDevice.push_back(device->identifier);
418     }
419     return vecDevice;
420 }
421 
ScanInputDevices(const std::string & dirName)422 void InputHub::ScanInputDevices(const std::string &dirName)
423 {
424     DHLOGI("ScanInputDevices enter, dirName %s.", dirName.c_str());
425     std::vector<std::string> vecInputDevPath;
426     ScanInputDevicesPath(dirName, vecInputDevPath);
427     for (const auto &tempPath: vecInputDevPath) {
428         OpenInputDeviceLocked(tempPath);
429     }
430 }
431 
IsDeviceRegistered(const std::string & devicePath)432 bool InputHub::IsDeviceRegistered(const std::string &devicePath)
433 {
434     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
435     for (const auto& [deviceId, device] : devices_) {
436         if (device->path == devicePath) {
437             return true; // device was already registered
438         }
439     }
440     return false;
441 }
442 
OpenInputDeviceLocked(const std::string & devicePath)443 int32_t InputHub::OpenInputDeviceLocked(const std::string &devicePath)
444 {
445     if (IsDeviceRegistered(devicePath)) {
446         return DH_SUCCESS;
447     }
448 
449     std::unique_lock<std::mutex> my_lock(operationMutex_);
450     DHLOGI("Opening device: %s", devicePath.c_str());
451     int fd = OpenInputDeviceFdByPath(devicePath);
452     if (fd == UN_INIT_FD_VALUE) {
453         DHLOGE("The fd open failed, devicePath %s.", devicePath.c_str());
454         return ERR_DH_INPUT_HUB_OPEN_DEVICEPATH_FAIL;
455     }
456 
457     InputDevice identifier;
458     if (QueryInputDeviceInfo(fd, identifier) < 0) {
459         CloseFd(fd);
460         return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
461     }
462     GenerateDescriptor(identifier);
463 
464     // Allocate device. (The device object takes ownership of the fd at this point.)
465     int32_t deviceId = nextDeviceId_++;
466     std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
467     RecordDeviceLog(deviceId, devicePath, identifier);
468 
469     if (MakeDevice(fd, std::move(device)) < 0) {
470         CloseFd(fd);
471         return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
472     }
473 
474     return DH_SUCCESS;
475 }
476 
QueryInputDeviceInfo(int fd,InputDevice & identifier)477 int32_t InputHub::QueryInputDeviceInfo(int fd, InputDevice &identifier)
478 {
479     char buffer[INPUT_EVENT_BUFFER_SIZE] = {0};
480     // Get device name.
481     if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
482         DHLOGE(
483             "Could not get device name for %s", ConvertErrNo().c_str());
484     } else {
485         buffer[sizeof(buffer) - 1] = '\0';
486         identifier.name = buffer;
487     }
488     DHLOGD("QueryInputDeviceInfo deviceName: %s", buffer);
489     // If the device is already a virtual device, don't monitor it.
490     if (identifier.name.find(VIRTUAL_DEVICE_NAME) != std::string::npos) {
491         return ERR_DH_INPUT_HUB_IS_VIRTUAL_DEVICE;
492     }
493     // Get device driver version.
494     int driverVersion;
495     if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
496         DHLOGE("could not get driver version for %s\n", ConvertErrNo().c_str());
497         return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
498     }
499     // Get device identifier.
500     struct input_id inputId;
501     if (ioctl(fd, EVIOCGID, &inputId)) {
502         DHLOGE("could not get device input id for %s\n", ConvertErrNo().c_str());
503         return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
504     }
505     identifier.bus = inputId.bustype;
506     identifier.product = inputId.product;
507     identifier.vendor = inputId.vendor;
508     identifier.version = inputId.version;
509     // Get device physical physicalPath.
510     if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
511         DHLOGE("could not get physicalPath for %s\n", ConvertErrNo().c_str());
512     } else {
513         buffer[sizeof(buffer) - 1] = '\0';
514         identifier.physicalPath = buffer;
515     }
516     // Get device unique id.
517     if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
518         DHLOGE("could not get idstring for %s\n", ConvertErrNo().c_str());
519     } else {
520         buffer[sizeof(buffer) - 1] = '\0';
521         identifier.uniqueId = buffer;
522     }
523 
524     QueryEventInfo(fd, identifier);
525     return DH_SUCCESS;
526 }
527 
QueryEventInfo(int fd,InputDevice & identifier)528 void InputHub::QueryEventInfo(int fd, InputDevice &identifier)
529 {
530     DHLOGI("QueryEventInfo: devName: %s, dhId: %s!", identifier.name.c_str(),
531         GetAnonyString(identifier.descriptor).c_str());
532     struct libevdev *dev = GetLibEvDev(fd);
533     if (dev == nullptr) {
534         DHLOGE("dev is nullptr");
535         return;
536     }
537     GetEventTypes(dev, identifier);
538     GetEventKeys(dev, identifier);
539     GetABSInfo(dev, identifier);
540     GetRELTypes(dev, identifier);
541     GetProperties(dev, identifier);
542     libevdev_free(dev);
543 }
544 
GetLibEvDev(int fd)545 struct libevdev* InputHub::GetLibEvDev(int fd)
546 {
547     struct libevdev *dev = nullptr;
548     int rc = 1;
549     rc = libevdev_new_from_fd(fd, &dev);
550     if (rc < 0) {
551         DHLOGE("Failed to init libevdev (%s)", strerror(-rc));
552         return nullptr;
553     }
554     return dev;
555 }
556 
GetEventTypes(struct libevdev * dev,InputDevice & identifier)557 void InputHub::GetEventTypes(struct libevdev *dev, InputDevice &identifier)
558 {
559     for (uint32_t eventType = 0; eventType < EV_CNT; eventType++) {
560         if (!libevdev_has_event_type(dev, eventType)) {
561             DHLOGD("The device is not support eventType: %d", eventType);
562             continue;
563         }
564         DHLOGI("QueryInputDeviceInfo eventType: %d", eventType);
565         identifier.eventTypes.push_back(eventType);
566     }
567 }
568 
GetEventKeys(struct libevdev * dev,InputDevice & identifier)569 int32_t InputHub::GetEventKeys(struct libevdev *dev, InputDevice &identifier)
570 {
571     if (!libevdev_has_event_type(dev, EV_KEY)) {
572         DHLOGE("The device doesn't has EV_KEY type!");
573         return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
574     }
575     for (uint32_t eventKey = 0; eventKey < KEY_CNT; eventKey++) {
576         if (!libevdev_has_event_code(dev, EV_KEY, eventKey)) {
577             DHLOGD("The device is not support eventKey: %d", eventKey);
578             continue;
579         }
580         DHLOGI("QueryInputDeviceInfo eventKey: %d", eventKey);
581         identifier.eventKeys.push_back(eventKey);
582     }
583     return DH_SUCCESS;
584 }
585 
GetABSInfo(struct libevdev * dev,InputDevice & identifier)586 int32_t InputHub::GetABSInfo(struct libevdev *dev, InputDevice &identifier)
587 {
588     if (!libevdev_has_event_type(dev, EV_ABS)) {
589         DHLOGE("The device doesn't has EV_ABS type!");
590         return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
591     }
592     DHLOGI("The device has abs info, devName: %s, dhId: %s!", identifier.name.c_str(),
593         GetAnonyString(identifier.descriptor).c_str());
594     for (uint32_t absType = 0; absType < ABS_CNT; absType++) {
595         if (!libevdev_has_event_code(dev, EV_ABS, absType)) {
596             DHLOGD("The device is not support absType: %d", absType);
597             continue;
598         }
599         DHLOGI("QueryInputDeviceInfo abs type: %d", absType);
600         identifier.absTypes.push_back(absType);
601         const struct input_absinfo *abs = libevdev_get_abs_info(dev, absType);
602         if (abs == nullptr) {
603             DHLOGE("absInfo is nullptr!");
604             continue;
605         }
606         DHLOGI("QueryInputDeviceInfo abs info value: %d, min: %d, max: %d, fuzz: %d, flat: %d, res: %d", abs->value,
607             abs->minimum, abs->maximum, abs->fuzz, abs->flat, abs->resolution);
608         identifier.absInfos[absType].push_back(abs->value);
609         identifier.absInfos[absType].push_back(abs->minimum);
610         identifier.absInfos[absType].push_back(abs->maximum);
611         identifier.absInfos[absType].push_back(abs->fuzz);
612         identifier.absInfos[absType].push_back(abs->flat);
613         identifier.absInfos[absType].push_back(abs->resolution);
614     }
615     return DH_SUCCESS;
616 }
617 
GetRELTypes(struct libevdev * dev,InputDevice & identifier)618 int32_t InputHub::GetRELTypes(struct libevdev *dev, InputDevice &identifier)
619 {
620     if (!libevdev_has_event_type(dev, EV_REL)) {
621         DHLOGE("The device doesn't has EV_REL type!");
622         return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
623     }
624     for (uint32_t code = 0; code < REL_CNT; code++) {
625         if (!libevdev_has_event_code(dev, EV_REL, code)) {
626             DHLOGD("The device is not support eventCode: %d", code);
627             continue;
628         }
629         DHLOGI("QueryInputDeviceInfo rel types: %d", code);
630         identifier.relTypes.push_back(code);
631     }
632     return DH_SUCCESS;
633 }
634 
GetProperties(struct libevdev * dev,InputDevice & identifier)635 void InputHub::GetProperties(struct libevdev *dev, InputDevice &identifier)
636 {
637     for (uint32_t prop = 0; prop < INPUT_PROP_CNT; prop++) {
638         if (libevdev_has_property(dev, prop)) {
639             DHLOGI("QueryInputDeviceInfo rel prop: %d", prop);
640             identifier.properties.push_back(prop);
641         }
642     }
643 }
644 
MakeDevice(int fd,std::unique_ptr<Device> device)645 int32_t InputHub::MakeDevice(int fd, std::unique_ptr<Device> device)
646 {
647     // Figure out the kinds of events the device reports.
648     ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(device->keyBitmask)), device->keyBitmask);
649     ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(device->absBitmask)), device->absBitmask);
650     ioctl(fd, EVIOCGBIT(EV_REL, sizeof(device->relBitmask)), device->relBitmask);
651 
652     // See if this is a multi-touch touchscreen device.
653     if (TestBit(BTN_TOUCH, device->keyBitmask) &&
654         TestBit(ABS_MT_POSITION_X, device->absBitmask) &&
655         TestBit(ABS_MT_POSITION_Y, device->absBitmask)) {
656         QueryLocalTouchScreenInfo(fd);
657         device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
658     } else if (TestBit(BTN_TOUCH, device->keyBitmask) &&
659         TestBit(ABS_X, device->absBitmask) &&
660         TestBit(ABS_Y, device->absBitmask)) {
661         QueryLocalTouchScreenInfo(fd);
662         device->classes |= INPUT_DEVICE_CLASS_TOUCH;
663     }
664 
665     // See if this is a cursor device such as a trackball or mouse.
666     if (TestBit(BTN_MOUSE, device->keyBitmask)
667         && TestBit(REL_X, device->relBitmask)
668         && TestBit(REL_Y, device->relBitmask)) {
669         device->classes |= INPUT_DEVICE_CLASS_CURSOR;
670     }
671 
672     // for Linux version 4.14.116, touchpad recognized as mouse and keyboard at same time,
673     // need to avoid device->classes to be 0x09, which mmi can't handler.
674     // See if this is a keyboard.
675     if (device->classes == 0) {
676         bool haveKeyboardKeys = ContainsNonZeroByte(device->keyBitmask, 0, SizeofBitArray(BTN_MISC));
677         if (haveKeyboardKeys) {
678             device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;
679         }
680     }
681 
682     // If the device isn't recognized as something we handle, don't monitor it.
683     if (device->classes == 0) {
684         DHLOGI("Dropping device: name='%s'", device->identifier.name.c_str());
685         return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
686     }
687 
688     if (RegisterDeviceForEpollLocked(*device) != DH_SUCCESS) {
689         return ERR_DH_INPUT_HUB_MAKE_DEVICE_FAIL;
690     }
691 
692     device->identifier.classes = device->classes;
693 
694     DHLOGI("inputType=%d", inputTypes_.load());
695     DHLOGI("New device: fd=%d, name='%s', classes=0x%x", fd, device->identifier.name.c_str(),
696         device->classes);
697 
698     AddDeviceLocked(std::move(device));
699     return DH_SUCCESS;
700 }
701 
QueryLocalTouchScreenInfo(int fd)702 int32_t InputHub::QueryLocalTouchScreenInfo(int fd)
703 {
704     LocalTouchScreenInfo info = DInputContext::GetInstance().GetLocalTouchScreenInfo();
705 
706     InputDevice identifier;
707     if (QueryInputDeviceInfo(fd, identifier) < 0) {
708         return ERR_DH_INPUT_HUB_QUERY_INPUT_DEVICE_INFO_FAIL;
709     }
710     identifier.classes |= INPUT_DEVICE_CLASS_TOUCH_MT;
711     info.localAbsInfo.deviceInfo = identifier;
712 
713     struct input_absinfo absInfo;
714     ioctl(fd, EVIOCGABS(ABS_MT_POSITION_X), &absInfo);
715     info.localAbsInfo.absXMin = absInfo.minimum;
716     info.localAbsInfo.absXMax = absInfo.maximum;
717     info.localAbsInfo.absMtPositionXMin = absInfo.minimum;
718     info.localAbsInfo.absMtPositionXMax = absInfo.maximum;
719     info.sinkPhyWidth = static_cast<uint32_t>(absInfo.maximum + 1);
720 
721     ioctl(fd, EVIOCGABS(ABS_MT_POSITION_Y), &absInfo);
722     info.localAbsInfo.absYMin = absInfo.minimum;
723     info.localAbsInfo.absYMax = absInfo.maximum;
724     info.localAbsInfo.absMtPositionYMin = absInfo.minimum;
725     info.localAbsInfo.absMtPositionYMax = absInfo.maximum;
726     info.sinkPhyHeight = static_cast<uint32_t>(absInfo.maximum + 1);
727 
728     ioctl(fd, EVIOCGABS(ABS_PRESSURE), &absInfo);
729     info.localAbsInfo.absPressureMin = absInfo.minimum;
730     info.localAbsInfo.absPressureMax = absInfo.maximum;
731     info.localAbsInfo.absMtPressureMin = absInfo.minimum;
732     info.localAbsInfo.absMtPressureMax = absInfo.maximum;
733 
734     ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MAJOR), &absInfo);
735     info.localAbsInfo.absMtTouchMajorMin = absInfo.minimum;
736     info.localAbsInfo.absMtTouchMajorMax = absInfo.maximum;
737 
738     ioctl(fd, EVIOCGABS(ABS_MT_TOUCH_MINOR), &absInfo);
739     info.localAbsInfo.absMtTouchMinorMin = absInfo.minimum;
740     info.localAbsInfo.absMtTouchMinorMax = absInfo.maximum;
741 
742     ioctl(fd, EVIOCGABS(ABS_MT_ORIENTATION), &absInfo);
743     info.localAbsInfo.absMtOrientationMin = absInfo.minimum;
744     info.localAbsInfo.absMtOrientationMax = absInfo.maximum;
745 
746     ioctl(fd, EVIOCGABS(ABS_MT_BLOB_ID), &absInfo);
747     info.localAbsInfo.absMtBlobIdMin = absInfo.minimum;
748     info.localAbsInfo.absMtBlobIdMax = absInfo.maximum;
749 
750     ioctl(fd, EVIOCGABS(ABS_MT_TRACKING_ID), &absInfo);
751     info.localAbsInfo.absMtTrackingIdMin = absInfo.minimum;
752     info.localAbsInfo.absMtTrackingIdMax = absInfo.maximum;
753 
754     DInputContext::GetInstance().SetLocalTouchScreenInfo(info);
755     return DH_SUCCESS;
756 }
757 
StringPrintf(const char * format,...) const758 std::string InputHub::StringPrintf(const char *format, ...) const
759 {
760     static const int kSpaceLength = 1024;
761     char space[kSpaceLength];
762 
763     va_list ap;
764     va_start(ap, format);
765     std::string result;
766     int32_t ret = vsnprintf_s(space, sizeof(space), sizeof(space) - 1, format, ap);
767     if (ret >= DH_SUCCESS && static_cast<size_t>(ret) < sizeof(space)) {
768         result = space;
769     } else {
770         va_end(ap);
771         return "the buffer is overflow!";
772     }
773     va_end(ap);
774     return result;
775 }
776 
GenerateDescriptor(InputDevice & identifier) const777 void InputHub::GenerateDescriptor(InputDevice &identifier) const
778 {
779     std::string rawDescriptor;
780     rawDescriptor += StringPrintf(":%04x:%04x:", identifier.vendor,
781         identifier.product);
782     // add handling for USB devices to not uniqueify kbs that show up twice
783     if (!identifier.uniqueId.empty()) {
784         rawDescriptor += "uniqueId:";
785         rawDescriptor += identifier.uniqueId;
786     }
787     if (!identifier.physicalPath.empty()) {
788         rawDescriptor += "physicalPath:";
789         rawDescriptor += identifier.physicalPath;
790     }
791     if (!identifier.name.empty()) {
792         rawDescriptor += "name:";
793         std::string name = identifier.name;
794         rawDescriptor += regex_replace(name, std::regex(" "), "");
795     }
796 
797     identifier.descriptor = DH_ID_PREFIX + Sha256(rawDescriptor);
798     DHLOGI("Created descriptor: raw=%s, cooked=%s", rawDescriptor.c_str(),
799         GetAnonyString(identifier.descriptor).c_str());
800 }
801 
RegisterDeviceForEpollLocked(const Device & device)802 int32_t InputHub::RegisterDeviceForEpollLocked(const Device &device)
803 {
804     int32_t result = RegisterFdForEpoll(device.fd);
805     if (result != DH_SUCCESS) {
806         DHLOGE("Could not add input device fd to epoll for device %d", device.id);
807         return result;
808     }
809     return result;
810 }
811 
RegisterFdForEpoll(int fd)812 int32_t InputHub::RegisterFdForEpoll(int fd)
813 {
814     struct epoll_event eventItem = {};
815     eventItem.events = EPOLLIN | EPOLLWAKEUP;
816     eventItem.data.fd = fd;
817     if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &eventItem)) {
818         DHLOGE("Could not add fd to epoll instance: %s", ConvertErrNo().c_str());
819         return -errno;
820     }
821     return DH_SUCCESS;
822 }
823 
AddDeviceLocked(std::unique_ptr<Device> device)824 void InputHub::AddDeviceLocked(std::unique_ptr<Device> device)
825 {
826     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
827     openingDevices_.push_back(std::move(device));
828 }
829 
CloseDeviceLocked(Device & device)830 void InputHub::CloseDeviceLocked(Device &device)
831 {
832     DHLOGI("Removed device: path=%s name=%s id=%s fd=%d classes=0x%x",
833         device.path.c_str(), device.identifier.name.c_str(), GetAnonyInt32(device.id).c_str(),
834         device.fd, device.classes);
835 
836     UnregisterDeviceFromEpollLocked(device);
837     device.Close();
838     {
839         std::unique_lock<std::mutex> devicesLock(devicesMutex_);
840         closingDevices_.push_back(std::move(devices_[device.id]));
841         devices_.erase(device.id);
842     }
843 }
844 
CloseDeviceForAllLocked(Device & device)845 void InputHub::CloseDeviceForAllLocked(Device &device)
846 {
847     DHLOGI("Removed device: path=%s name=%s id=%s fd=%d classes=0x%x",
848         device.path.c_str(), device.identifier.name.c_str(), GetAnonyInt32(device.id).c_str(),
849         device.fd, device.classes);
850 
851     UnregisterDeviceFromEpollLocked(device);
852     device.Close();
853     closingDevices_.push_back(std::move(devices_[device.id]));
854     devices_.erase(device.id);
855 }
856 
UnregisterDeviceFromEpollLocked(const Device & device) const857 int32_t InputHub::UnregisterDeviceFromEpollLocked(const Device &device) const
858 {
859     if (device.HasValidFd()) {
860         int32_t result = UnregisterFdFromEpoll(device.fd);
861         if (result != DH_SUCCESS) {
862             DHLOGE("Could not remove input device fd from epoll for device %s",
863                 GetAnonyInt32(device.id).c_str());
864             return result;
865         }
866     }
867     return DH_SUCCESS;
868 }
869 
UnregisterFdFromEpoll(int fd) const870 int32_t InputHub::UnregisterFdFromEpoll(int fd) const
871 {
872     if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, nullptr)) {
873         DHLOGE("Could not remove fd from epoll instance: %s", ConvertErrNo().c_str());
874         return ERR_DH_INPUT_HUB_UNREGISTER_FD_FAIL;
875     }
876     return DH_SUCCESS;
877 }
878 
ReadNotifyLocked()879 int32_t InputHub::ReadNotifyLocked()
880 {
881     size_t res;
882     char eventBuf[512];
883     struct inotify_event *event;
884 
885     DHLOGI("readNotify nfd: %d\n", iNotifyFd_);
886     res = static_cast<size_t>(read(iNotifyFd_, eventBuf, sizeof(eventBuf)));
887     if (res < sizeof(*event)) {
888         if (errno == EINTR) {
889             return DH_SUCCESS;
890         }
891         DHLOGE("could not get event, %s\n", ConvertErrNo().c_str());
892         return ERR_DH_INPUT_HUB_GET_EVENT_FAIL;
893     }
894 
895     {
896         size_t eventSize = 0;
897         size_t eventPos = 0;
898         while (res >= sizeof(*event)) {
899             event = reinterpret_cast<struct inotify_event *>(eventBuf + eventPos);
900             JudgeDeviceOpenOrClose(*event);
901             eventSize = sizeof(*event) + event->len;
902             res -= eventSize;
903             eventPos += eventSize;
904         }
905     }
906     return DH_SUCCESS;
907 }
908 
JudgeDeviceOpenOrClose(const inotify_event & event)909 void InputHub::JudgeDeviceOpenOrClose(const inotify_event &event)
910 {
911     if (event.len) {
912         if (event.wd == inputWd_) {
913             std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
914             if (event.mask & IN_CREATE) {
915                 OpenInputDeviceLocked(filename);
916             } else {
917                 DHLOGI("Removing device '%s' due to inotify event\n", filename.c_str());
918                 CloseDeviceByPathLocked(filename);
919             }
920         } else {
921             DHLOGI("Unexpected inotify event, wd = %i", event.wd);
922         }
923     }
924 }
925 
CloseDeviceByPathLocked(const std::string & devicePath)926 void InputHub::CloseDeviceByPathLocked(const std::string &devicePath)
927 {
928     Device* device = GetDeviceByPathLocked(devicePath);
929     if (device) {
930         CloseDeviceLocked(*device);
931         return;
932     }
933     DHLOGI("Remove device: %s not found, device may already have been removed.", devicePath.c_str());
934 }
935 
CloseAllDevicesLocked()936 void InputHub::CloseAllDevicesLocked()
937 {
938     DHLOGI("Close All Devices");
939     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
940     while (!devices_.empty()) {
941         CloseDeviceForAllLocked(*(devices_.begin()->second));
942     }
943 }
944 
GetDeviceByPathLocked(const std::string & devicePath)945 InputHub::Device* InputHub::GetDeviceByPathLocked(const std::string &devicePath)
946 {
947     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
948     for (const auto& [id, device] : devices_) {
949         if (device->path == devicePath) {
950             return device.get();
951         }
952     }
953     return nullptr;
954 }
955 
GetDeviceByFdLocked(int fd)956 InputHub::Device* InputHub::GetDeviceByFdLocked(int fd)
957 {
958     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
959     for (const auto& [id, device] : devices_) {
960         if (device->fd == fd) {
961             return device.get();
962         }
963     }
964     return nullptr;
965 }
966 
GetSupportDeviceByFd(int fd)967 InputHub::Device* InputHub::GetSupportDeviceByFd(int fd)
968 {
969     DHLOGI("GetSupportDeviceByFd fd: %d", fd);
970     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
971     for (const auto& [id, device] : devices_) {
972         if (device != nullptr && device->fd == fd) {
973             DHLOGI("GetSupportDeviceByFd device: %d, fd: %d, path: %s, dhId: %s, classes=0x%x", id, device->fd,
974                 device->path.c_str(), GetAnonyString(device->identifier.descriptor).c_str(), device->classes);
975             return device.get();
976         }
977     }
978     return nullptr;
979 }
980 
ContainsNonZeroByte(const uint8_t * array,uint32_t startIndex,uint32_t endIndex)981 bool InputHub::ContainsNonZeroByte(const uint8_t *array, uint32_t startIndex, uint32_t endIndex)
982 {
983     const uint8_t* end = array + endIndex;
984     array += startIndex;
985     while (array != end) {
986         if (*(array++) != 0) {
987             return true;
988         }
989     }
990     return false;
991 }
992 
ProcessEventTimestamp(const input_event & event)993 int64_t InputHub::ProcessEventTimestamp(const input_event &event)
994 {
995     const int64_t inputEventTime = event.input_event_sec * 1000000000LL + event.input_event_usec * 1000LL;
996     return inputEventTime;
997 }
998 
TestBit(uint32_t bit,const uint8_t * array)999 bool InputHub::TestBit(uint32_t bit, const uint8_t *array)
1000 {
1001     constexpr int units = 8;
1002     return (array)[(bit) / units] & (1 << ((bit) % units));
1003 }
1004 
SizeofBitArray(uint32_t bit)1005 uint32_t InputHub::SizeofBitArray(uint32_t bit)
1006 {
1007     constexpr int round = 7;
1008     constexpr int divisor = 8;
1009     return ((bit) + round) / divisor;
1010 }
1011 
SaveAffectDhId(bool isEnable,const std::string & dhId,AffectDhIds & affDhIds)1012 void InputHub::SaveAffectDhId(bool isEnable, const std::string &dhId, AffectDhIds &affDhIds)
1013 {
1014     if (isEnable) {
1015         affDhIds.sharingDhIds.push_back(dhId);
1016     } else {
1017         affDhIds.noSharingDhIds.push_back(dhId);
1018     }
1019 }
1020 
SetSupportInputType(bool enabled,const uint32_t & inputTypes)1021 AffectDhIds InputHub::SetSupportInputType(bool enabled, const uint32_t &inputTypes)
1022 {
1023     AffectDhIds affDhIds;
1024     inputTypes_ = inputTypes;
1025     DHLOGI("SetSupportInputType: inputTypes=0x%x,", inputTypes_.load());
1026     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1027     for (const auto &[id, device] : devices_) {
1028         if (device->classes & inputTypes_) {
1029             device->isShare = enabled;
1030             DHLOGW("ByType dhid:%s, isshare:%d", GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1031             SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1032         }
1033     }
1034 
1035     return affDhIds;
1036 }
1037 
SetSharingDevices(bool enabled,std::vector<std::string> dhIds)1038 AffectDhIds InputHub::SetSharingDevices(bool enabled, std::vector<std::string> dhIds)
1039 {
1040     AffectDhIds affDhIds;
1041     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1042     DHLOGI("SetSharingDevices start");
1043     for (auto dhId : dhIds) {
1044         DHLOGI("SetSharingDevices dhId: %s, size: %d, enabled: %d", GetAnonyString(dhId).c_str(), devices_.size(),
1045             enabled);
1046         sharedDHIds_[dhId] = enabled;
1047         for (const auto &[id, device] : devices_) {
1048             DHLOGI("deviceName %s ,dhId: %s ", device->identifier.name.c_str(),
1049                 GetAnonyString(device->identifier.descriptor).c_str());
1050             if (device->identifier.descriptor == dhId) {
1051                 device->isShare = enabled;
1052                 DHLOGW("dhid:%s, isshare:%d", GetAnonyString(device->identifier.descriptor).c_str(), enabled);
1053                 SaveAffectDhId(enabled, device->identifier.descriptor, affDhIds);
1054                 break;
1055             }
1056         }
1057     }
1058     DHLOGI("SetSharingDevices end");
1059     return affDhIds;
1060 }
1061 
GetShareMousePathByDhId(std::vector<std::string> dhIds,std::string & path,std::string & dhId)1062 void InputHub::GetShareMousePathByDhId(std::vector<std::string> dhIds, std::string &path, std::string &dhId)
1063 {
1064     DHLOGI("GetShareMousePathByDhId: devices_.size:%d,", devices_.size());
1065     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1066     for (auto dhId_ : dhIds) {
1067         for (const auto &[id, device] : devices_) {
1068             if (device == nullptr) {
1069                 DHLOGE("device is nullptr");
1070                 continue;
1071             }
1072             DHLOGI("descriptor:%s, isShare[%d], type[%d]", GetAnonyString(device->identifier.descriptor).c_str(),
1073                    device->isShare, device->classes);
1074             if ((device->identifier.descriptor == dhId_) &&
1075                 ((device->classes & INPUT_DEVICE_CLASS_CURSOR) != 0)) {
1076                 dhId = dhId_;
1077                 path = device->path;
1078                 return; // return First shared mouse
1079             }
1080         }
1081     }
1082 }
1083 
GetShareKeyboardPathsByDhIds(std::vector<std::string> dhIds,std::vector<std::string> & shareDhidsPaths,std::vector<std::string> & shareDhIds)1084 void InputHub::GetShareKeyboardPathsByDhIds(std::vector<std::string> dhIds, std::vector<std::string> &shareDhidsPaths,
1085     std::vector<std::string> &shareDhIds)
1086 {
1087     DHLOGI("GetShareKeyboardPathsByDhIds: devices_.size:%d,", devices_.size());
1088     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1089     for (auto dhId_ : dhIds) {
1090         for (const auto &[id, device] : devices_) {
1091             if (device == nullptr) {
1092                 DHLOGE("device is nullptr");
1093                 continue;
1094             }
1095             DHLOGI("descriptor:%s, isShare[%d], type[%d]", GetAnonyString(device->identifier.descriptor).c_str(),
1096                    device->isShare, device->classes);
1097             if ((device->identifier.descriptor == dhId_) &&
1098                 ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0)) {
1099                 shareDhIds.push_back(dhId_);
1100                 shareDhidsPaths.push_back(device->path);
1101             }
1102         }
1103     }
1104 }
1105 
GetDevicesInfoByType(const uint32_t inputTypes,std::map<int32_t,std::string> & datas)1106 void InputHub::GetDevicesInfoByType(const uint32_t inputTypes, std::map<int32_t, std::string> &datas)
1107 {
1108     uint32_t dhType = 0;
1109 
1110     if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::MOUSE)) != 0) {
1111         dhType |= INPUT_DEVICE_CLASS_CURSOR;
1112     }
1113 
1114     if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::KEYBOARD)) != 0) {
1115         dhType |= INPUT_DEVICE_CLASS_KEYBOARD;
1116     }
1117 
1118     if ((inputTypes & static_cast<uint32_t>(DInputDeviceType::TOUCHSCREEN)) != 0) {
1119         dhType |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;
1120     }
1121 
1122     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1123     for (const auto &[id, device] : devices_) {
1124         if (device->classes & dhType) {
1125             datas.insert(std::pair<int32_t, std::string>(device->fd, device->identifier.descriptor));
1126         }
1127     }
1128 }
1129 
GetDevicesInfoByDhId(std::vector<std::string> dhidsVec,std::map<int32_t,std::string> & datas)1130 void InputHub::GetDevicesInfoByDhId(std::vector<std::string> dhidsVec, std::map<int32_t, std::string> &datas)
1131 {
1132     for (auto dhId : dhidsVec) {
1133         std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1134         for (const auto &[id, device] : devices_) {
1135             if (device->identifier.descriptor == dhId) {
1136                 datas.insert(std::pair<int32_t, std::string>(device->fd, dhId));
1137             }
1138         }
1139     }
1140 }
1141 
IsAllDevicesStoped()1142 bool InputHub::IsAllDevicesStoped()
1143 {
1144     std::unique_lock<std::mutex> deviceLock(devicesMutex_);
1145     for (const auto &[dhId, isShared] : sharedDHIds_) {
1146         DHLOGI("the dhId: %s, isShared: %d", GetAnonyString(dhId).c_str(), isShared);
1147         if (isShared) {
1148             return false;
1149         }
1150     }
1151     return true;
1152 }
1153 
RecordDeviceLog(const int32_t deviceId,const std::string & devicePath,const InputDevice & identifier)1154 void InputHub::RecordDeviceLog(const int32_t deviceId, const std::string &devicePath, const InputDevice &identifier)
1155 {
1156     DHLOGI("add device %d: %s\n", deviceId, devicePath.c_str());
1157     DHLOGI("  bus:        %04x\n"
1158            "  vendor      %04x\n"
1159            "  product     %04x\n"
1160            "  version     %04x\n",
1161         identifier.bus, identifier.vendor, identifier.product, identifier.version);
1162     DHLOGI("  name:       \"%s\"\n", identifier.name.c_str());
1163     DHLOGI("  physicalPath:   \"%s\"\n", identifier.physicalPath.c_str());
1164     DHLOGI("  unique id:  \"%s\"\n", identifier.uniqueId.c_str());
1165     DHLOGI("  descriptor: \"%s\"\n", GetAnonyString(identifier.descriptor).c_str());
1166 }
1167 
RecordEventLog(const RawEvent * event)1168 void InputHub::RecordEventLog(const RawEvent *event)
1169 {
1170     std::string eventType = "";
1171     switch (event->type) {
1172         case EV_KEY:
1173             eventType = "EV_KEY";
1174             break;
1175         case EV_REL:
1176             eventType = "EV_REL";
1177             break;
1178         case EV_ABS:
1179             eventType = "EV_ABS";
1180             break;
1181         case EV_SYN:
1182             eventType = "EV_SYN";
1183             break;
1184         default:
1185             eventType = "other type " + std::to_string(event->type);
1186             break;
1187     }
1188     DHLOGD("1.E2E-Test Sink collect event, EventType: %s, Code: %d, Value: %d, Path: %s, descriptor: %s,"
1189         "When:%" PRId64 "", eventType.c_str(), event->code, event->value, event->path.c_str(),
1190         GetAnonyString(event->descriptor).c_str(), event->when);
1191 }
1192 
HandleTouchScreenEvent(struct input_event readBuffer[],const size_t count,std::vector<bool> & needFilted)1193 void InputHub::HandleTouchScreenEvent(struct input_event readBuffer[], const size_t count,
1194     std::vector<bool> &needFilted)
1195 {
1196     std::vector<std::pair<size_t, size_t>> absIndexs;
1197     int32_t firstIndex = -1;
1198     int32_t lastIndex = -1;
1199 
1200     for (size_t i = 0; i < count; i++) {
1201         struct input_event& iev = readBuffer[i];
1202         if ((iev.type == EV_ABS) && (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X)) {
1203             firstIndex = static_cast<int32_t>(i);
1204         } else if (iev.type  == EV_SYN) {
1205             lastIndex = static_cast<int32_t>(i);
1206         }
1207         if ((firstIndex >= 0) && (lastIndex > firstIndex)) {
1208             absIndexs.emplace_back(std::make_pair((size_t)firstIndex, (size_t)lastIndex));
1209         }
1210     }
1211 
1212     AbsInfo absInfo = {
1213         .absX = 0,
1214         .absY = 0,
1215         .absXIndex = -1,
1216         .absYIndex = -1,
1217     };
1218     for (auto iter : absIndexs) {
1219         absInfo.absXIndex = -1;
1220         absInfo.absYIndex = -1;
1221 
1222         for (size_t j = iter.first; j <= iter.second; j++) {
1223             struct input_event &iev = readBuffer[j];
1224             if (iev.code == ABS_X || iev.code == ABS_MT_POSITION_X) {
1225                 absInfo.absX = static_cast<uint32_t>(iev.value);
1226                 absInfo.absXIndex = static_cast<int32_t>(j);
1227             }
1228             if (iev.code == ABS_Y || iev.code == ABS_MT_POSITION_Y) {
1229                 absInfo.absY = static_cast<uint32_t>(iev.value);
1230                 absInfo.absYIndex = static_cast<int32_t>(j);
1231             }
1232         }
1233 
1234         if ((absInfo.absXIndex < 0) || (absInfo.absYIndex < 0)) {
1235             for (size_t j = iter.first; j <= iter.second; j++) {
1236                 needFilted[j] = true;
1237             }
1238             continue;
1239         }
1240         if (!CheckTouchPointRegion(readBuffer, absInfo)) {
1241             for (size_t j = iter.first; j <= iter.second; j++) {
1242                 needFilted[j] = true;
1243             }
1244         }
1245     }
1246 }
1247 
CheckTouchPointRegion(struct input_event readBuffer[],const AbsInfo & absInfo)1248 bool InputHub::CheckTouchPointRegion(struct input_event readBuffer[], const AbsInfo &absInfo)
1249 {
1250     auto sinkInfos = DInputContext::GetInstance().GetAllSinkScreenInfo();
1251 
1252     for (const auto& [id, sinkInfo] : sinkInfos) {
1253         auto info = sinkInfo.transformInfo;
1254         if ((absInfo.absX >= info.sinkWinPhyX) && (absInfo.absX <= (info.sinkWinPhyX + info.sinkProjPhyWidth))
1255             && (absInfo.absY >= info.sinkWinPhyY) && (absInfo.absY <= (info.sinkWinPhyY + info.sinkProjPhyHeight))) {
1256             touchDescriptor = sinkInfo.srcScreenInfo.sourcePhyId;
1257             readBuffer[absInfo.absXIndex].value = (absInfo.absX - info.sinkWinPhyX) * info.coeffWidth;
1258             readBuffer[absInfo.absYIndex].value = (absInfo.absY - info.sinkWinPhyY) * info.coeffHeight;
1259             return true;
1260         }
1261     }
1262     return false;
1263 }
1264 
Device(int fd,int32_t id,const std::string & path,const InputDevice & identifier)1265 InputHub::Device::Device(int fd, int32_t id, const std::string &path,
1266     const InputDevice &identifier) : next(nullptr), fd(fd), id(id), path(path), identifier(identifier),
1267     classes(0), enabled(false), isShare(false), isVirtual(fd < 0) {
1268     memset_s(keyBitmask, sizeof(keyBitmask), 0, sizeof(keyBitmask));
1269     memset_s(absBitmask, sizeof(absBitmask), 0, sizeof(absBitmask));
1270     memset_s(relBitmask, sizeof(relBitmask), 0, sizeof(relBitmask));
1271 }
1272 
~Device()1273 InputHub::Device::~Device()
1274 {
1275     Close();
1276 }
1277 
Close()1278 void InputHub::Device::Close()
1279 {
1280     if (fd >= 0) {
1281         ::close(fd);
1282         fd = UN_INIT_FD_VALUE;
1283     }
1284 }
1285 
Enable()1286 int32_t InputHub::Device::Enable()
1287 {
1288     char canonicalPath[PATH_MAX + 1] = {0x00};
1289 
1290     if (path.length() == 0 || path.length() > PATH_MAX || realpath(path.c_str(), canonicalPath) == nullptr) {
1291         DHLOGE("path check fail, error path: %s", path.c_str());
1292         return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1293     }
1294     fd = open(canonicalPath, O_RDWR | O_CLOEXEC | O_NONBLOCK);
1295     if (fd < 0) {
1296         DHLOGE("could not open %s, %s\n", path.c_str(), ConvertErrNo().c_str());
1297         return ERR_DH_INPUT_HUB_DEVICE_ENABLE_FAIL;
1298     }
1299     enabled = true;
1300     return DH_SUCCESS;
1301 }
1302 
Disable()1303 int32_t InputHub::Device::Disable()
1304 {
1305     Close();
1306     enabled = false;
1307     return DH_SUCCESS;
1308 }
1309 
HasValidFd() const1310 bool InputHub::Device::HasValidFd() const
1311 {
1312     return !isVirtual && enabled;
1313 }
1314 } // namespace DistributedInput
1315 } // namespace DistributedHardware
1316 } // namespace OHOS
1317