• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "dinput_state.h"
17 
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <pthread.h>
21 #include <thread>
22 #include <unistd.h>
23 #include <vector>
24 
25 #include "constants_dinput.h"
26 #include "dinput_errcode.h"
27 #include "dinput_log.h"
28 #include "dinput_utils_tool.h"
29 #include "distributed_input_collector.h"
30 #include "distributed_input_inject.h"
31 #include "distributed_input_sink_transport.h"
32 
33 namespace OHOS {
34 namespace DistributedHardware {
35 namespace DistributedInput {
~DInputState()36 DInputState::~DInputState()
37 {
38     Release();
39 }
40 
Init()41 int32_t DInputState::Init()
42 {
43     DHLOGI("DInputState Init.");
44     return DH_SUCCESS;
45 }
46 
Release()47 int32_t DInputState::Release()
48 {
49     DHLOGI("DInputState Release.");
50     std::unique_lock<std::mutex> mapLock(operationMutex_);
51     dhidStateMap_.clear();
52     return DH_SUCCESS;
53 }
54 
RecordDhids(const std::vector<std::string> & dhids,DhidState state,const int32_t & sessionId)55 int32_t DInputState::RecordDhids(const std::vector<std::string> &dhids, DhidState state, const int32_t &sessionId)
56 {
57     DHLOGI("RecordDhids dhids size = %zu", dhids.size());
58     std::unique_lock<std::mutex> mapLock(operationMutex_);
59     for (auto &dhid : dhids) {
60         DHLOGD("add dhid : %s, state : %d.", GetAnonyString(dhid).c_str(), state);
61         dhidStateMap_[dhid] = state;
62     }
63 
64     if (state == DhidState::THROUGH_OUT) {
65         CreateSpecialEventInjectThread(sessionId, dhids);
66     }
67     return DH_SUCCESS;
68 }
69 
RemoveDhids(const std::vector<std::string> & dhids)70 int32_t DInputState::RemoveDhids(const std::vector<std::string> &dhids)
71 {
72     DHLOGI("RemoveDhids dhids size = %zu", dhids.size());
73     std::unique_lock<std::mutex> mapLock(operationMutex_);
74     for (auto &dhid : dhids) {
75         DHLOGD("delete dhid : %s", GetAnonyString(dhid).c_str());
76         dhidStateMap_.erase(dhid);
77     }
78     return DH_SUCCESS;
79 }
80 
GetStateByDhid(std::string & dhid)81 DhidState DInputState::GetStateByDhid(std::string &dhid)
82 {
83     std::unique_lock<std::mutex> mapLock(operationMutex_);
84     if (dhidStateMap_.find(dhid) == dhidStateMap_.end()) {
85         DHLOGE("dhid : %s not exist.", GetAnonyString(dhid).c_str());
86         return DhidState::THROUGH_IN;
87     }
88     return dhidStateMap_[dhid];
89 }
90 
CreateSpecialEventInjectThread(const int32_t & sessionId,const std::vector<std::string> & dhids)91 void DInputState::CreateSpecialEventInjectThread(const int32_t &sessionId, const std::vector<std::string> &dhids)
92 {
93     DHLOGI("CreateSpecialEventInjectThread enter, dhids.size = %d, sessionId = %d.", dhids.size(), sessionId);
94     std::thread specEventInjectThread =
95         std::thread(&DInputState::SpecEventInject, this, sessionId, dhids);
96     int32_t ret = pthread_setname_np(specEventInjectThread.native_handle(), CHECK_KEY_STATUS_THREAD_NAME);
97     if (ret != 0) {
98         DHLOGE("specEventInjectThread setname failed.");
99     }
100     specEventInjectThread.detach();
101 }
102 
RecordEventLog(const input_event & event)103 void DInputState::RecordEventLog(const input_event &event)
104 {
105     std::string eventType = "";
106     switch (event.type) {
107         case EV_KEY:
108             eventType = "EV_KEY";
109             break;
110         case EV_SYN:
111             eventType = "EV_SYN";
112             break;
113         default:
114             eventType = "other type";
115             break;
116     }
117     DHLOGD("5.E2E-Test Source write event into input driver, EventType: %s, Code: %d, Value: %d",
118         eventType.c_str(), event.code, event.value);
119 }
120 
WriteEventToDev(int & fd,const input_event & event)121 void DInputState::WriteEventToDev(int &fd, const input_event &event)
122 {
123     if (write(fd, &event, sizeof(event)) < static_cast<ssize_t>(sizeof(event))) {
124         DHLOGE("could not inject event, removed? (fd: %d)", fd);
125         return;
126     }
127     RecordEventLog(event);
128 }
129 
SpecEventInject(const int32_t & sessionId,std::vector<std::string> dhids)130 void DInputState::SpecEventInject(const int32_t &sessionId, std::vector<std::string> dhids)
131 {
132     DHLOGI("SpecEveInject enter");
133     // mouse event send to remote device
134     if (sessionId != -1) {
135         std::string mouseNodePath;
136         std::string mouseNodeDhId;
137         DistributedInputCollector::GetInstance().GetMouseNodePath(dhids, mouseNodePath, mouseNodeDhId);
138         CheckMouseKeyState(sessionId, mouseNodePath, mouseNodeDhId);
139     }
140 
141     // keyboard up event inject local device
142     std::vector<std::string> keyboardNodePaths;
143     std::vector<std::string> keyboardNodeDhIds;
144     DistributedInputCollector::GetInstance().GetShareKeyboardPathsByDhIds(dhids, keyboardNodePaths, keyboardNodeDhIds);
145     DistributedInputInject::GetInstance().GetVirtualKeyboardPathsByDhIds(dhids, keyboardNodePaths, keyboardNodeDhIds);
146     size_t len = keyboardNodePaths.size();
147     for (size_t i = 0; i < len; ++i) {
148         std::vector<uint32_t> keyboardPressedKeys;
149         int fd = UN_INIT_FD_VALUE;
150         CheckKeyboardState(keyboardNodeDhIds[i], keyboardNodePaths[i], keyboardPressedKeys, fd);
151         for (auto &code : keyboardPressedKeys) {
152             struct input_event event = {
153                 .type = EV_KEY,
154                 .code = code,
155                 .value = KEY_UP_STATE
156             };
157             WriteEventToDev(fd, event);
158             event.type = EV_SYN;
159             event.code = 0;
160             WriteEventToDev(fd, event);
161         }
162         CloseFd(fd);
163     }
164 }
165 
CheckKeyboardState(std::string & dhid,std::string & keyboardNodePath,std::vector<uint32_t> & keyboardPressedKeys,int & fd)166 void DInputState::CheckKeyboardState(std::string &dhid, std::string &keyboardNodePath,
167     std::vector<uint32_t> &keyboardPressedKeys, int &fd)
168 {
169     DHLOGI("CheckKeyboardState enter,  dhid %s, keyboardNodePath %s.", GetAnonyString(dhid).c_str(),
170         keyboardNodePath.c_str());
171     char canonicalPath[PATH_MAX] = {0x00};
172     if (keyboardNodePath.length() == 0 || keyboardNodePath.length() >= PATH_MAX ||
173         realpath(keyboardNodePath.c_str(), canonicalPath) == nullptr) {
174         DHLOGE("keyboard Nodepath check fail, error path: %s", keyboardNodePath.c_str());
175         return;
176     }
177     fd = open(canonicalPath, O_WRONLY | O_NONBLOCK);
178     if (fd < 0) {
179         DHLOGE("open keyboard Node Path error:", errno);
180         return;
181     }
182 
183     uint32_t count = 0;
184     unsigned long keystate[NLONGS(KEY_CNT)] = { 0 };
185     while (true) {
186         if (count > READ_RETRY_MAX) {
187             break;
188         }
189         int rc = ioctl(fd, EVIOCGKEY(sizeof(keystate)), keystate);
190         if (rc < 0) {
191             DHLOGE("read all key state failed, rc=%d ", rc);
192             count += 1;
193             std::this_thread::sleep_for(std::chrono::milliseconds(READ_SLEEP_TIME_MS));
194             continue;
195         }
196         for (int32_t yalv = 0; yalv < KEY_MAX; yalv++) {
197             if (BitIsSet(keystate, yalv)) {
198                 DHLOGD("yalv = %d, not up.", yalv);
199                 keyboardPressedKeys.push_back(yalv);
200             }
201         }
202         break;
203     }
204 }
205 
CheckMouseKeyState(const int32_t & sessionId,const std::string & mouseNodePath,const std::string & mouseNodeDhId)206 void DInputState::CheckMouseKeyState(const int32_t &sessionId, const std::string &mouseNodePath,
207     const std::string &mouseNodeDhId)
208 {
209     DHLOGI("CheckMouseKeyState enter, mouseNodePath %s, mouseNodeDhId %s, sessionId %d.", mouseNodePath.c_str(),
210         GetAnonyString(mouseNodeDhId).c_str(), sessionId);
211     char canonicalPath[PATH_MAX] = {0x00};
212     if (mouseNodePath.length() == 0 || mouseNodePath.length() >= PATH_MAX ||
213         realpath(mouseNodePath.c_str(), canonicalPath) == nullptr) {
214         DHLOGE("mouse Nodepath check fail, error path: %s", mouseNodePath.c_str());
215         return;
216     }
217     int fd = open(canonicalPath, O_RDONLY | O_NONBLOCK);
218     if (fd < 0) {
219         DHLOGE("open mouse Node Path error:", errno);
220         return;
221     }
222 
223     uint32_t count = 0;
224     int leftKeyVal = 0;
225     int rightKeyVal = 0;
226     int midKeyVal = 0;
227     unsigned long keystate[NLONGS(KEY_CNT)] = { 0 };
228     while (true) {
229         if (count > READ_RETRY_MAX) {
230             break;
231         }
232         // Query all key state
233         int rc = ioctl(fd, EVIOCGKEY(sizeof(keystate)), keystate);
234         if (rc < 0) {
235             DHLOGE("read all key state failed, rc=%d ", rc);
236             count += 1;
237             std::this_thread::sleep_for(std::chrono::milliseconds(READ_SLEEP_TIME_MS));
238             continue;
239         }
240         leftKeyVal = BitIsSet(keystate, BTN_LEFT);
241         if (leftKeyVal != 0) {
242             DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsg(sessionId, mouseNodeDhId, BTN_LEFT);
243         }
244         rightKeyVal = BitIsSet(keystate, BTN_RIGHT);
245         if (rightKeyVal != 0) {
246             DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsg(sessionId, mouseNodeDhId, BTN_RIGHT);
247         }
248         midKeyVal = BitIsSet(keystate, BTN_MIDDLE);
249         if (midKeyVal != 0) {
250             DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsg(sessionId, mouseNodeDhId, BTN_MIDDLE);
251         }
252         break;
253     }
254     CloseFd(fd);
255 }
256 } // namespace DistributedInput
257 } // namespace DistributedHardware
258 } // namespace OHOSs