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