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
25 namespace OHOS {
26 namespace Msdp {
27 namespace DeviceStatus {
28 namespace Cooperate {
29 constexpr size_t MAX_INPUT_DEV_PER_DEVICE { 10 };
30
InputDeviceMgr(IContext * context)31 InputDeviceMgr::InputDeviceMgr(IContext *context) : env_(context) {}
32
Enable()33 void InputDeviceMgr::Enable()
34 {
35 CALL_INFO_TRACE;
36 if (enable_) {
37 return;
38 }
39 FI_HILOGI("Enable InputDeviceMgr");
40 enable_ = true;
41 }
42
Disable()43 void InputDeviceMgr::Disable()
44 {
45 CALL_INFO_TRACE;
46 if (enable_) {
47 enable_ = false;
48 }
49 FI_HILOGI("Disable InputDeviceMgr");
50 }
51
OnSoftbusSessionOpened(const DSoftbusSessionOpened & notice)52 void InputDeviceMgr::OnSoftbusSessionOpened(const DSoftbusSessionOpened ¬ice)
53 {
54 CALL_INFO_TRACE;
55 NotifyInputDeviceToRemote(notice.networkId);
56 }
57
OnSoftbusSessionClosed(const DSoftbusSessionClosed & notice)58 void InputDeviceMgr::OnSoftbusSessionClosed(const DSoftbusSessionClosed ¬ice)
59 {
60 CALL_INFO_TRACE;
61 RemoveAllRemoteInputDevice(notice.networkId);
62 }
63
OnLocalHotPlug(const InputHotplugEvent & notice)64 void InputDeviceMgr::OnLocalHotPlug(const InputHotplugEvent ¬ice)
65 {
66 CALL_INFO_TRACE;
67 BroadcastHotPlugToRemote(notice);
68 }
69
OnRemoteInputDevice(const DSoftbusSyncInputDevice & notice)70 void 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
OnRemoteHotPlug(const DSoftbusHotPlugEvent & notice)80 void InputDeviceMgr::OnRemoteHotPlug(const DSoftbusHotPlugEvent ¬ice)
81 {
82 CALL_INFO_TRACE;
83 }
84
AddVirtualInputDevice(const std::string & networkId)85 void 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
RemoveVirtualInputDevice(const std::string & networkId)95 void 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
HandleRemoteHotPlug(const DSoftbusHotPlugEvent & notice)105 void 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
NotifyInputDeviceToRemote(const std::string & remoteNetworkId)122 void 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
BroadcastHotPlugToRemote(const InputHotplugEvent & notice)148 void 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
RemoveRemoteInputDevice(const std::string & networkId,std::shared_ptr<IDevice> device)180 void 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
AddRemoteInputDevice(const std::string & networkId,std::shared_ptr<IDevice> device)191 void 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
RemoveAllRemoteInputDevice(const std::string & networkId)203 void 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
DispDeviceInfo(std::shared_ptr<IDevice> device)213 void InputDeviceMgr::DispDeviceInfo(std::shared_ptr<IDevice> device)
214 {
215 CHKPV(device);
216 FI_HILOGI(" device %{public}d:%{private}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: \"%{private}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
DumpRemoteInputDevice(const std::string & networkId)229 void 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
SerializeDevice(std::shared_ptr<IDevice> device,NetPacket & packet)243 int32_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
Transform(std::shared_ptr<IDevice> device)257 std::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
AddVirtualInputDevice(const std::string & networkId,int32_t remoteDeviceId)279 void 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
RemoveVirtualInputDevice(const std::string & networkId,int32_t remoteDeviceId)300 void 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
GetRemoteDeviceById(const std::string & networkId,int32_t remoteDeviceId)318 std::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