1 /*
2  * Copyright (c) 2023-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 "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 = %{public}zu", dhIds.size());
61     std::lock_guard<std::mutex> mapLock(operationMutex_);
62     for (const auto &dhid : dhIds) {
63         DHLOGD("add dhid : %{public}s, state : %{public}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 = %{public}zu", dhIds.size());
77     std::lock_guard<std::mutex> mapLock(operationMutex_);
78     for (const auto &dhid : dhIds) {
79         DHLOGD("delete dhid : %{public}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 : %{public}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: %{public}s", GetAnonyString(dhId).c_str());
103     int32_t scanId = GetRandomInt32(0, INT32_MAX);
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: %{public}zu", 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 %{public}d, dhIds size %{public}zu", 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: %{public}s", GetAnonyString(dhId).c_str());
140         return;
141     }
142 
143     for (const auto &event : iter->second) {
144         DHLOGI("Simulate Key event for device path: %{public}s, dhId: %{public}s",
145             event.path.c_str(), GetAnonyString(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: %{public}s, event size: %{public}zu", GetAnonyString(dhId).c_str(),
169         events.size());
170     DistributedInputSinkTransport::GetInstance().SendKeyStateNodeMsgBatch(sessionId, events);
171 }
172 
IsDhIdDown(const std::string & dhId)173 bool DInputSinkState::IsDhIdDown(const std::string &dhId)
174 {
175     std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
176     auto iter = keyDownStateMap_.find(dhId);
177     return iter != keyDownStateMap_.end();
178 }
179 
AddKeyDownState(struct RawEvent event)180 void DInputSinkState::AddKeyDownState(struct RawEvent event)
181 {
182     std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
183     keyDownStateMap_[event.descriptor].push_back(event);
184 }
185 
RemoveKeyDownState(struct RawEvent event)186 void DInputSinkState::RemoveKeyDownState(struct RawEvent event)
187 {
188     std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
189     auto iter = keyDownStateMap_.find(event.descriptor);
190     if (iter == keyDownStateMap_.end()) {
191         return;
192     }
193 
194     auto evIter = std::find(keyDownStateMap_[event.descriptor].begin(),
195         keyDownStateMap_[event.descriptor].end(), event);
196     if (evIter == keyDownStateMap_[event.descriptor].end()) {
197         return;
198     }
199 
200     keyDownStateMap_[event.descriptor].erase(evIter);
201     if (keyDownStateMap_[event.descriptor].empty()) {
202         keyDownStateMap_.erase(event.descriptor);
203     }
204 }
205 
CheckAndSetLongPressedKeyOrder(struct RawEvent event)206 void DInputSinkState::CheckAndSetLongPressedKeyOrder(struct RawEvent event)
207 {
208     std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
209     auto iter = keyDownStateMap_.find(event.descriptor);
210     if (iter == keyDownStateMap_.end()) {
211         DHLOGI("Find new pressed key, save it, node id: %{public}s, type: %{public}d, key code: %{public}d, "
212             "value: %{public}d", GetAnonyString(event.descriptor).c_str(), event.type, event.code, event.value);
213         keyDownStateMap_[event.descriptor].push_back(event);
214         return;
215     }
216 
217     auto evIter = std::find(keyDownStateMap_[event.descriptor].begin(),
218         keyDownStateMap_[event.descriptor].end(), event);
219     // If not find the cache key on pressing, save it
220     if (evIter == keyDownStateMap_[event.descriptor].end()) {
221         DHLOGI("Find new pressed key, save it, node id: %{public}s, type: %{public}d, key code: %{public}d, "
222             "value: %{public}d", GetAnonyString(event.descriptor).c_str(), event.type, event.code, event.value);
223         keyDownStateMap_[event.descriptor].push_back(event);
224         return;
225     }
226 
227     // it is already the last one, just return
228     if (evIter == (keyDownStateMap_[event.descriptor].end() - 1)) {
229         DHLOGI("Pressed key already last one, node id: %{public}s, type: %{public}d, key code: %{public}d, "
230             "value: %{public}d", GetAnonyString(event.descriptor).c_str(), event.type, event.code, event.value);
231         return;
232     }
233 
234     // Ohterwhise, move the key to the last cached position.
235     RawEvent backEv = *evIter;
236     keyDownStateMap_[event.descriptor].erase(evIter);
237     keyDownStateMap_[event.descriptor].push_back(backEv);
238     DHLOGI("Find long pressed key: %{public}d, move the cached pressed key: %{public}d to the last position",
239         event.code, backEv.code);
240 }
241 
ClearDeviceStates()242 void DInputSinkState::ClearDeviceStates()
243 {
244     std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_);
245     keyDownStateMap_.clear();
246 }
247 } // namespace DistributedInput
248 } // namespace DistributedHardware
249 } // namespace OHOSs