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 31namespace OHOS { 32namespace DistributedHardware { 33namespace DistributedInput { 34IMPLEMENT_SINGLE_INSTANCE(DInputSinkState); 35DInputSinkState::~DInputSinkState() 36{ 37 Release(); 38} 39 40int32_t DInputSinkState::Init() 41{ 42 DHLOGI("DInputSinkState Init."); 43 touchPadEventFragMgr_ = std::make_shared<TouchPadEventFragmentMgr>(); 44 return DH_SUCCESS; 45} 46 47int32_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 58int32_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 74int32_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 85std::shared_ptr<TouchPadEventFragmentMgr> DInputSinkState::GetTouchPadEventFragMgr() 86{ 87 return this->touchPadEventFragMgr_; 88} 89 90DhIdState 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 100void 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 112void 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 118void 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 133void 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 152void 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 161void 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 173bool 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 180void DInputSinkState::AddKeyDownState(struct RawEvent event) 181{ 182 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_); 183 keyDownStateMap_[event.descriptor].push_back(event); 184} 185 186void 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 206void 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 242void DInputSinkState::ClearDeviceStates() 243{ 244 std::lock_guard<std::mutex> mapLock(keyDownStateMapMtx_); 245 keyDownStateMap_.clear(); 246} 247} // namespace DistributedInput 248} // namespace DistributedHardware 249} // namespace OHOSs