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_sink_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 "dinput_errcode.h"
26 #include "dinput_log.h"
27 #include "dinput_utils_tool.h"
28 #include "distributed_input_collector.h"
29 #include "distributed_input_sink_transport.h"
30
31 namespace OHOS {
32 namespace DistributedHardware {
33 namespace DistributedInput {
34 IMPLEMENT_SINGLE_INSTANCE(DInputSinkState);
~DInputSinkState()35 DInputSinkState::~DInputSinkState()
36 {
37 Release();
38 }
39
Init()40 int32_t DInputSinkState::Init()
41 {
42 DHLOGI("DInputSinkState Init.");
43 touchPadEventFragMgr_ = std::make_shared<TouchPadEventFragmentMgr>();
44 return DH_SUCCESS;
45 }
46
Release()47 int32_t DInputSinkState::Release()
48 {
49 DHLOGI("DInputSinkState Release.");
50 {
51 std::lock_guard<std::mutex> mapLock(operationMutex_);
52 dhIdStateMap_.clear();
53 }
54 ClearDeviceStates();
55 return DH_SUCCESS;
56 }
57
RecordDhIds(const std::vector<std::string> & dhIds,DhIdState state,const int32_t sessionId)58 int32_t DInputSinkState::RecordDhIds(const std::vector<std::string> &dhIds, DhIdState state, const int32_t sessionId)
59 {
60 DHLOGI("RecordDhIds dhIds size = %zu", dhIds.size());
61 std::lock_guard<std::mutex> mapLock(operationMutex_);
62 for (const auto &dhid : dhIds) {
63 DHLOGD("add dhid : %s, state : %d.", GetAnonyString(dhid).c_str(), state);
64 dhIdStateMap_[dhid] = state;
65 }
66
67 if (state == DhIdState::THROUGH_OUT) {
68 SimulateEventInjectToSrc(sessionId, dhIds);
69 }
70 lastSessionId_ = sessionId;
71 return DH_SUCCESS;
72 }
73
RemoveDhIds(const std::vector<std::string> & dhIds)74 int32_t DInputSinkState::RemoveDhIds(const std::vector<std::string> &dhIds)
75 {
76 DHLOGI("RemoveDhIds dhIds size = %zu", dhIds.size());
77 std::lock_guard<std::mutex> mapLock(operationMutex_);
78 for (const auto &dhid : dhIds) {
79 DHLOGD("delete dhid : %s", GetAnonyString(dhid).c_str());
80 dhIdStateMap_.erase(dhid);
81 }
82 return DH_SUCCESS;
83 }
84
GetTouchPadEventFragMgr()85 std::shared_ptr<TouchPadEventFragmentMgr> DInputSinkState::GetTouchPadEventFragMgr()
86 {
87 return this->touchPadEventFragMgr_;
88 }
89
GetStateByDhid(const std::string & dhId)90 DhIdState DInputSinkState::GetStateByDhid(const std::string &dhId)
91 {
92 std::lock_guard<std::mutex> mapLock(operationMutex_);
93 if (dhIdStateMap_.find(dhId) == dhIdStateMap_.end()) {
94 DHLOGE("dhId : %s not exist.", GetAnonyString(dhId).c_str());
95 return DhIdState::THROUGH_IN;
96 }
97 return dhIdStateMap_[dhId];
98 }
99
SimulateMouseBtnMouseUpState(const std::string & dhId,const struct RawEvent & event)100 void DInputSinkState::SimulateMouseBtnMouseUpState(const std::string &dhId, const struct RawEvent &event)
101 {
102 DHLOGI("Sinmulate Mouse BTN_MOUSE UP state to source, dhId: %s", dhId.c_str());
103 int32_t scanId = GetRandomInt32();
104 RawEvent mscScanEv = { event.when, EV_MSC, MSC_SCAN, scanId, dhId, event.path };
105 RawEvent btnMouseUpEv = { event.when, EV_KEY, BTN_MOUSE, KEY_UP_STATE, dhId, event.path };
106 RawEvent sycReportEv = { event.when, EV_SYN, SYN_REPORT, 0x0, dhId, event.path };
107
108 std::vector<RawEvent> simEvents = { mscScanEv, btnMouseUpEv, sycReportEv };
109 DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsgBatch(lastSessionId_, simEvents);
110 }
111
SimulateTouchPadStateReset(const std::vector<RawEvent> & events)112 void DInputSinkState::SimulateTouchPadStateReset(const std::vector<RawEvent> &events)
113 {
114 DHLOGI("SimulateTouchPadStateReset events size: %d", events.size());
115 DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsgBatch(lastSessionId_, events);
116 }
117
SimulateEventInjectToSrc(const int32_t sessionId,const std::vector<std::string> & dhIds)118 void DInputSinkState::SimulateEventInjectToSrc(const int32_t sessionId, const std::vector<std::string> &dhIds)
119 {
120 DHLOGI("SimulateEventInject enter, sessionId %d, dhIds size %d", sessionId, dhIds.size());
121 // mouse/keyboard/touchpad/touchscreen event send to remote device if these device pass through.
122 if (sessionId == -1) {
123 DHLOGE("SimulateEventInjectToSrc SessionId invalid");
124 return;
125 }
126
127 for (const std::string &dhId : dhIds) {
128 SimulateKeyDownEvents(sessionId, dhId);
129 SimulateTouchPadEvents(sessionId, dhId);
130 }
131 }
132
SimulateKeyDownEvents(const int32_t sessionId,const std::string & dhId)133 void DInputSinkState::SimulateKeyDownEvents(const int32_t sessionId, const std::string &dhId)
134 {
135 // check if this device is key event
136 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
137 auto iter = keyDownStateMap_.find(dhId);
138 if (iter == keyDownStateMap_.end()) {
139 DHLOGI("The shared Device not has down state key, dhId: %s", dhId.c_str());
140 return;
141 }
142
143 for (const auto &event : iter->second) {
144 DHLOGI("Simulate Key event for device path: %s, dhId: %s",
145 event.path.c_str(), event.descriptor.c_str());
146 SimulateKeyDownEvent(sessionId, dhId, event);
147 }
148
149 keyDownStateMap_.erase(dhId);
150 }
151
SimulateKeyDownEvent(const int32_t sessionId,const std::string & dhId,const struct RawEvent & event)152 void DInputSinkState::SimulateKeyDownEvent(const int32_t sessionId, const std::string &dhId,
153 const struct RawEvent &event)
154 {
155 DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsg(sessionId, dhId,
156 EV_KEY, event.code, KEY_DOWN_STATE);
157 DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsg(sessionId, dhId,
158 EV_SYN, SYN_REPORT, 0x0);
159 }
160
SimulateTouchPadEvents(const int32_t sessionId,const std::string & dhId)161 void DInputSinkState::SimulateTouchPadEvents(const int32_t sessionId, const std::string &dhId)
162 {
163 std::vector<RawEvent> events = this->touchPadEventFragMgr_->GetAndClearEvents(dhId);
164 if (events.empty()) {
165 return;
166 }
167
168 DHLOGI("SimulateTouchPadEvents dhId: %s, event size: %d", dhId.c_str(), events.size());
169 DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsgBatch(sessionId, events);
170 }
171
IsDhIdDown(const std::string & dhId)172 bool DInputSinkState::IsDhIdDown(const std::string &dhId)
173 {
174 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
175 auto iter = keyDownStateMap_.find(dhId);
176 return iter != keyDownStateMap_.end();
177 }
178
AddKeyDownState(struct RawEvent event)179 void DInputSinkState::AddKeyDownState(struct RawEvent event)
180 {
181 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
182 keyDownStateMap_[event.descriptor].push_back(event);
183 }
184
RemoveKeyDownState(struct RawEvent event)185 void DInputSinkState::RemoveKeyDownState(struct RawEvent event)
186 {
187 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
188 auto iter = keyDownStateMap_.find(event.descriptor);
189 if (iter == keyDownStateMap_.end()) {
190 return;
191 }
192
193 auto evIter = std::find(keyDownStateMap_[event.descriptor].begin(),
194 keyDownStateMap_[event.descriptor].end(), event);
195 if (evIter == keyDownStateMap_[event.descriptor].end()) {
196 return;
197 }
198
199 keyDownStateMap_[event.descriptor].erase(evIter);
200 if (keyDownStateMap_[event.descriptor].empty()) {
201 keyDownStateMap_.erase(event.descriptor);
202 }
203 }
204
CheckAndSetLongPressedKeyOrder(struct RawEvent event)205 void DInputSinkState::CheckAndSetLongPressedKeyOrder(struct RawEvent event)
206 {
207 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
208 auto iter = keyDownStateMap_.find(event.descriptor);
209 if (iter == keyDownStateMap_.end()) {
210 DHLOGI("Find new pressed key, save it, node id: %s, type: %d, key code: %d, value: %d",
211 event.descriptor.c_str(), event.type, event.code, event.value);
212 keyDownStateMap_[event.descriptor].push_back(event);
213 return;
214 }
215
216 auto evIter = std::find(keyDownStateMap_[event.descriptor].begin(),
217 keyDownStateMap_[event.descriptor].end(), event);
218 // If not find the cache key on pressing, save it
219 if (evIter == keyDownStateMap_[event.descriptor].end()) {
220 DHLOGI("Find new pressed key, save it, node id: %s, type: %d, key code: %d, value: %d",
221 event.descriptor.c_str(), event.type, event.code, event.value);
222 keyDownStateMap_[event.descriptor].push_back(event);
223 return;
224 }
225
226 // it is already the last one, just return
227 if (evIter == (keyDownStateMap_[event.descriptor].end() - 1)) {
228 DHLOGI("Pressed key already last one, node id: %s, type: %d, key code: %d, value: %d",
229 event.descriptor.c_str(), event.type, event.code, event.value);
230 return;
231 }
232
233 // Ohterwhise, move the key to the last cached position.
234 RawEvent backEv = *evIter;
235 keyDownStateMap_[event.descriptor].erase(evIter);
236 keyDownStateMap_[event.descriptor].push_back(backEv);
237 DHLOGI("Find long pressed key: %d, move the cached pressed key: %d to the last position", event.code, backEv.code);
238 }
239
ClearDeviceStates()240 void DInputSinkState::ClearDeviceStates()
241 {
242 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
243 keyDownStateMap_.clear();
244 }
245 } // namespace DistributedInput
246 } // namespace DistributedHardware
247 } // namespace OHOSs