1/* 2 * Copyright (c) 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 "input_device_mgr.h" 17 18#include "device.h" 19#include "devicestatus_define.h" 20#include "utility.h" 21 22#undef LOG_TAG 23#define LOG_TAG "InputDeviceMgr" 24 25namespace OHOS { 26namespace Msdp { 27namespace DeviceStatus { 28namespace Cooperate { 29constexpr size_t MAX_INPUT_DEV_PER_DEVICE { 10 }; 30 31InputDeviceMgr::InputDeviceMgr(IContext *context) : env_(context) {} 32 33void InputDeviceMgr::Enable() 34{ 35 CALL_INFO_TRACE; 36 if (enable_) { 37 return; 38 } 39 FI_HILOGI("Enable InputDeviceMgr"); 40 enable_ = true; 41} 42 43void InputDeviceMgr::Disable() 44{ 45 CALL_INFO_TRACE; 46 if (enable_) { 47 enable_ = false; 48 } 49 FI_HILOGI("Disable InputDeviceMgr"); 50} 51 52void InputDeviceMgr::OnSoftbusSessionOpened(const DSoftbusSessionOpened ¬ice) 53{ 54 CALL_INFO_TRACE; 55 NotifyInputDeviceToRemote(notice.networkId); 56} 57 58void InputDeviceMgr::OnSoftbusSessionClosed(const DSoftbusSessionClosed ¬ice) 59{ 60 CALL_INFO_TRACE; 61 RemoveAllRemoteInputDevice(notice.networkId); 62} 63 64void InputDeviceMgr::OnLocalHotPlug(const InputHotplugEvent ¬ice) 65{ 66 CALL_INFO_TRACE; 67 BroadcastHotPlugToRemote(notice); 68} 69 70void InputDeviceMgr::OnRemoteInputDevice(const DSoftbusSyncInputDevice ¬ice) 71{ 72 CALL_INFO_TRACE; 73 std::string networkId = notice.networkId; 74 for (const auto &device : notice.devices) { 75 DispDeviceInfo(device); 76 AddRemoteInputDevice(networkId, device); 77 } 78} 79 80void InputDeviceMgr::OnRemoteHotPlug(const DSoftbusHotPlugEvent ¬ice) 81{ 82 CALL_INFO_TRACE; 83} 84 85void InputDeviceMgr::AddVirtualInputDevice(const std::string &networkId) 86{ 87 CALL_INFO_TRACE; 88 FI_HILOGI("Add virtual device from %{public}s", Utility::Anonymize(networkId).c_str()); 89 for (const auto &device : remoteDevices_[networkId]) { 90 CHKPC(device); 91 AddVirtualInputDevice(networkId, device->GetId()); 92 } 93} 94 95void InputDeviceMgr::RemoveVirtualInputDevice(const std::string &networkId) 96{ 97 CALL_INFO_TRACE; 98 FI_HILOGI("Remove virtual device from %{public}s", Utility::Anonymize(networkId).c_str()); 99 for (const auto &device : remoteDevices_[networkId]) { 100 CHKPC(device); 101 RemoveVirtualInputDevice(networkId, device->GetId()); 102 } 103} 104 105void InputDeviceMgr::HandleRemoteHotPlug(const DSoftbusHotPlugEvent ¬ice) 106{ 107 CALL_INFO_TRACE; 108 CHKPV(notice.device); 109 auto remoteDeviceId = notice.device->GetId(); 110 if (notice.type == InputHotplugType::UNPLUG) { 111 if (remote2VirtualIds_.find(remoteDeviceId) == remote2VirtualIds_.end()) { 112 FI_HILOGI("No virtual matches remote deviceId:%{public}d", remoteDeviceId); 113 return; 114 } 115 RemoveVirtualInputDevice(notice.networkId, remoteDeviceId); 116 } 117 if (notice.type == InputHotplugType::PLUG) { 118 AddVirtualInputDevice(notice.networkId, remoteDeviceId); 119 } 120} 121 122void InputDeviceMgr::NotifyInputDeviceToRemote(const std::string &remoteNetworkId) 123{ 124 CALL_INFO_TRACE; 125 if (!env_->GetDeviceManager().HasKeyboard()) { 126 FI_HILOGE("Local device have no keyboard, skip"); 127 return; 128 } 129 auto keyboards = env_->GetDeviceManager().GetKeyboard(); 130 NetPacket packet(MessageId::DSOFTBUS_INPUT_DEV_SYNC); 131 int32_t keyboardNum = static_cast<int32_t>(keyboards.size()); 132 packet << keyboardNum; 133 for (const auto &keyboard : keyboards) { 134 if (SerializeDevice(keyboard, packet) != RET_OK) { 135 FI_HILOGE("SerializeDevice failed"); 136 return; 137 } 138 DispDeviceInfo(keyboard); 139 } 140 if (int32_t ret = env_->GetDSoftbus().SendPacket(remoteNetworkId, packet); ret != RET_OK) { 141 FI_HILOGE("SenPacket to networkId:%{public}s failed, ret:%{public}d", 142 Utility::Anonymize(remoteNetworkId).c_str(), ret); 143 return; 144 } 145 FI_HILOGI("NotifyInputDeviceToRemote networkId:%{public}s", Utility::Anonymize(remoteNetworkId).c_str()); 146} 147 148void InputDeviceMgr::BroadcastHotPlugToRemote(const InputHotplugEvent ¬ice) 149{ 150 CALL_INFO_TRACE; 151 FI_HILOGI("HotplugType%{public}d deviceId:%{public}d", static_cast<int32_t>(notice.type), notice.deviceId); 152 if (!notice.isKeyboard) { 153 FI_HILOGI("Not keyboard, skip"); 154 return; 155 } 156 NetPacket packet(MessageId::DSOFTBUS_INPUT_DEV_HOT_PLUG); 157 packet << static_cast<int32_t>(notice.type); 158 if (notice.type == InputHotplugType::PLUG) { 159 auto device = env_->GetDeviceManager().GetDevice(notice.deviceId); 160 CHKPV(device); 161 DispDeviceInfo(device); 162 if (SerializeDevice(device, packet) != RET_OK) { 163 FI_HILOGE("SerializeDevice failed"); 164 return; 165 } 166 } 167 if (notice.type == InputHotplugType::UNPLUG) { 168 packet << notice.deviceId; 169 if (packet.ChkRWError()) { 170 FI_HILOGE("Write packet failed"); 171 return; 172 } 173 } 174 if (int32_t ret = env_->GetDSoftbus().BroadcastPacket(packet); ret != RET_OK) { 175 FI_HILOGE("BroadcastPacket failed"); 176 return; 177 } 178} 179 180void InputDeviceMgr::RemoveRemoteInputDevice(const std::string &networkId, std::shared_ptr<IDevice> device) 181{ 182 CALL_INFO_TRACE; 183 if (remoteDevices_.find(networkId) == remoteDevices_.end()) { 184 FI_HILOGE("NetworkId:%{public}s have no device existed", Utility::Anonymize(networkId).c_str()); 185 return; 186 } 187 DispDeviceInfo(device); 188 remoteDevices_[networkId].erase(device); 189} 190 191void InputDeviceMgr::AddRemoteInputDevice(const std::string &networkId, std::shared_ptr<IDevice> device) 192{ 193 CALL_INFO_TRACE; 194 DispDeviceInfo(device); 195 if (remoteDevices_.find(networkId) != remoteDevices_.end() && 196 remoteDevices_[networkId].size() >= MAX_INPUT_DEV_PER_DEVICE) { 197 FI_HILOGE("Input device num from networkId:%{public}s exceeds limit", Utility::Anonymize(networkId).c_str()); 198 return; 199 } 200 remoteDevices_[networkId].insert(device); 201} 202 203void InputDeviceMgr::RemoveAllRemoteInputDevice(const std::string &networkId) 204{ 205 CALL_INFO_TRACE; 206 if (remoteDevices_.find(networkId) == remoteDevices_.end()) { 207 FI_HILOGE("NetworkId:%{public}s have no device existed", Utility::Anonymize(networkId).c_str()); 208 return; 209 } 210 remoteDevices_.erase(networkId); 211} 212 213void InputDeviceMgr::DispDeviceInfo(std::shared_ptr<IDevice> device) 214{ 215 CHKPV(device); 216 FI_HILOGI(" device %{public}d:%{public}s", device->GetId(), device->GetDevPath().c_str()); 217 FI_HILOGI(" sysPath: \"%{private}s\"", device->GetSysPath().c_str()); 218 FI_HILOGI(" bus: %{public}04x", device->GetBus()); 219 FI_HILOGI(" vendor: %{public}04x", device->GetVendor()); 220 FI_HILOGI(" product: %{public}04x", device->GetProduct()); 221 FI_HILOGI(" version: %{public}04x", device->GetVersion()); 222 FI_HILOGI(" name: \"%{public}s\"", device->GetName().c_str()); 223 FI_HILOGI(" location: \"%{public}s\"", device->GetPhys().c_str()); 224 FI_HILOGI(" unique id: \"%{public}s\"", device->GetUniq().c_str()); 225 FI_HILOGI(" is pointer: %{public}s, is keyboard:%{public}s", 226 device->IsPointerDevice() ? "True" : "False", device->IsKeyboard() ? "True" : "False"); 227} 228 229void InputDeviceMgr::DumpRemoteInputDevice(const std::string &networkId) 230{ 231 CALL_INFO_TRACE; 232 if (remoteDevices_.find(networkId) == remoteDevices_.end()) { 233 FI_HILOGE("NetworkId:%{public}s have no device existed", Utility::Anonymize(networkId).c_str()); 234 return; 235 } 236 FI_HILOGI("NetworkId%{public}s, device mount:%{public}zu", Utility::Anonymize(networkId).c_str(), 237 remoteDevices_.size()); 238 for (const auto &elem : remoteDevices_[networkId]) { 239 FI_HILOGI("DeviceId:%{public}d, deviceName:%{public}s", elem->GetId(), elem->GetName().c_str()); 240 } 241} 242 243int32_t InputDeviceMgr::SerializeDevice(std::shared_ptr<IDevice> device, NetPacket &packet) 244{ 245 CALL_INFO_TRACE; 246 packet << device->GetId() << device->GetDevPath() << device->GetSysPath() << device->GetBus() << 247 device->GetVendor() << device->GetProduct() << device->GetVersion() << device->GetName() << 248 device->GetPhys() << device->GetUniq() << device->IsPointerDevice() << device->IsKeyboard() << 249 static_cast<int32_t> (device->GetKeyboardType()); 250 if (packet.ChkRWError()) { 251 FI_HILOGE("Write packet failed"); 252 return RET_ERR; 253 } 254 return RET_OK; 255} 256 257std::shared_ptr<MMI::InputDevice> InputDeviceMgr::Transform(std::shared_ptr<IDevice> device) 258{ 259 CALL_DEBUG_ENTER; 260 CHKPP(device); 261 auto inputDevice = std::make_shared<MMI::InputDevice>(); 262 inputDevice->SetId(device->GetId()); 263 inputDevice->SetName(device->GetName()); 264 inputDevice->SetBus(device->GetBus()); 265 inputDevice->SetVersion(device->GetVersion()); 266 inputDevice->SetProduct(device->GetProduct()); 267 inputDevice->SetVendor(device->GetVendor()); 268 inputDevice->SetPhys(device->GetPhys()); 269 inputDevice->SetUniq(device->GetUniq()); 270 if (device->IsKeyboard()) { 271 inputDevice->AddCapability(MMI::InputDeviceCapability::INPUT_DEV_CAP_KEYBOARD); 272 } 273 if (device->IsPointerDevice()) { 274 inputDevice->AddCapability(MMI::InputDeviceCapability::INPUT_DEV_CAP_POINTER); 275 } 276 return inputDevice; 277} 278 279void InputDeviceMgr::AddVirtualInputDevice(const std::string &networkId, int32_t remoteDeviceId) 280{ 281 CALL_INFO_TRACE; 282 if (remote2VirtualIds_.find(remoteDeviceId) != remote2VirtualIds_.end()) { 283 FI_HILOGW("Remote device:%{public}d already added as virtual device:%{public}d", 284 remoteDeviceId, remote2VirtualIds_[remoteDeviceId]); 285 return; 286 } 287 auto device = GetRemoteDeviceById(networkId, remoteDeviceId); 288 CHKPV(device); 289 int32_t virtualDeviceId = -1; 290 if (env_->GetInput().AddVirtualInputDevice(Transform(device), virtualDeviceId) != RET_OK) { 291 FI_HILOGE("Add virtual device failed, remoteDeviceId:%{public}d, name:%{public}s", remoteDeviceId, 292 device->GetName().c_str()); 293 return; 294 } 295 virtualInputDevicesAdded_[networkId].insert(virtualDeviceId); 296 remote2VirtualIds_[remoteDeviceId] = virtualDeviceId; 297 FI_HILOGI("Add virtual device success, virtualDeviceId:%{public}d", virtualDeviceId); 298} 299 300void InputDeviceMgr::RemoveVirtualInputDevice(const std::string &networkId, int32_t remoteDeviceId) 301{ 302 CALL_INFO_TRACE; 303 if (remote2VirtualIds_.find(remoteDeviceId) == remote2VirtualIds_.end()) { 304 FI_HILOGE("No remote device from networkId%{public}s with id:%{public}d", 305 Utility::Anonymize(networkId).c_str(), remoteDeviceId); 306 return; 307 } 308 auto virtualDeviceId = remote2VirtualIds_[remoteDeviceId]; 309 if (env_->GetInput().RemoveVirtualInputDevice(virtualDeviceId) != RET_OK) { 310 FI_HILOGE("Remove virtual device failed, virtualDeviceId:%{public}d", virtualDeviceId); 311 return; 312 } 313 virtualInputDevicesAdded_[networkId].erase(virtualDeviceId); 314 remote2VirtualIds_.erase(remoteDeviceId); 315 FI_HILOGI("Remove virtual device success, virtualDeviceId:%{public}d", virtualDeviceId); 316} 317 318std::shared_ptr<IDevice> InputDeviceMgr::GetRemoteDeviceById(const std::string &networkId, int32_t remoteDeviceId) 319{ 320 std::shared_ptr<IDevice> dev = std::make_shared<Device>(remoteDeviceId); 321 if (remoteDevices_.find(networkId) == remoteDevices_.end()) { 322 FI_HILOGE("No remoteDevice from networkId:%{public}s", Utility::Anonymize(networkId).c_str()); 323 return nullptr; 324 } 325 if (auto iter = remoteDevices_[networkId].find(dev); iter != remoteDevices_[networkId].end()) { 326 return *iter; 327 } 328 FI_HILOGW("No remote device with deviceId:%{public}d", remoteDeviceId); 329 return nullptr; 330} 331 332} // namespace Cooperate 333} // namespace DeviceStatus 334} // namespace Msdp 335} // namespace OHOS 336