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 &notice)
53 {
54     CALL_INFO_TRACE;
55     NotifyInputDeviceToRemote(notice.networkId);
56 }
57 
OnSoftbusSessionClosed(const DSoftbusSessionClosed & notice)58 void InputDeviceMgr::OnSoftbusSessionClosed(const DSoftbusSessionClosed &notice)
59 {
60     CALL_INFO_TRACE;
61     RemoveAllRemoteInputDevice(notice.networkId);
62 }
63 
OnLocalHotPlug(const InputHotplugEvent & notice)64 void InputDeviceMgr::OnLocalHotPlug(const InputHotplugEvent &notice)
65 {
66     CALL_INFO_TRACE;
67     BroadcastHotPlugToRemote(notice);
68 }
69 
OnRemoteInputDevice(const DSoftbusSyncInputDevice & notice)70 void InputDeviceMgr::OnRemoteInputDevice(const DSoftbusSyncInputDevice &notice)
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 &notice)
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 &notice)
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 &notice)
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