1 /*
2 * Copyright (c) 2023 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_manager.h"
17
18 #include <openssl/sha.h>
19 #include <regex>
20
21 #include "devicestatus_define.h"
22 #include "dsoftbus_adapter.h"
23 #include "event_manager.h"
24 #include "napi_constants.h"
25
26 namespace OHOS {
27 namespace Msdp {
28 namespace DeviceStatus {
29 namespace Cooperate {
30 namespace {
31 constexpr HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "InputDeviceManager" };
32 constexpr size_t NETWORK_ID_NUMS { 3 };
33 constexpr size_t DESCRIPTOR_INDEX { 2 };
34 } // namespace
35
Device(std::shared_ptr<IDevice> dev)36 InputDeviceManager::Device::Device(std::shared_ptr<IDevice> dev)
37 : device_(dev)
38 {
39 Populate();
40 }
41
GetId() const42 int32_t InputDeviceManager::Device::GetId() const
43 {
44 CHKPR(device_, RET_ERR);
45 return device_->GetId();
46 }
47
GetName() const48 std::string InputDeviceManager::Device::GetName() const
49 {
50 CHKPS(device_);
51 return device_->GetName();
52 }
53
GetDhid() const54 std::string InputDeviceManager::Device::GetDhid() const
55 {
56 return dhid_;
57 }
58
GetNetworkId() const59 std::string InputDeviceManager::Device::GetNetworkId() const
60 {
61 return networkId_;
62 }
63
GetProduct() const64 int32_t InputDeviceManager::Device::GetProduct() const
65 {
66 CHKPR(device_, RET_ERR);
67 return device_->GetProduct();
68 }
69
GetVendor() const70 int32_t InputDeviceManager::Device::GetVendor() const
71 {
72 CHKPR(device_, RET_ERR);
73 return device_->GetVendor();
74 }
75
GetPhys() const76 std::string InputDeviceManager::Device::GetPhys() const
77 {
78 CHKPS(device_);
79 return device_->GetPhys();
80 }
81
GetUniq() const82 std::string InputDeviceManager::Device::GetUniq() const
83 {
84 CHKPS(device_);
85 return device_->GetUniq();
86 }
87
IsPointerDevice() const88 bool InputDeviceManager::Device::IsPointerDevice() const
89 {
90 CHKPF(device_);
91 return device_->IsPointerDevice();
92 }
93
GetKeyboardType() const94 IDevice::KeyboardType InputDeviceManager::Device::GetKeyboardType() const
95 {
96 CHKPR(device_, IDevice::KeyboardType::KEYBOARD_TYPE_NONE);
97 return device_->GetKeyboardType();
98 }
99
IsKeyboard() const100 bool InputDeviceManager::Device::IsKeyboard() const
101 {
102 CHKPF(device_);
103 return device_->IsKeyboard();
104 }
105
Populate()106 void InputDeviceManager::Device::Populate()
107 {
108 CALL_DEBUG_ENTER;
109 if (IsRemote()) {
110 networkId_ = MakeNetworkId(GetPhys());
111 }
112 dhid_ = GenerateDescriptor();
113 }
114
IsRemote()115 bool InputDeviceManager::Device::IsRemote()
116 {
117 const std::string INPUT_VIRTUAL_DEVICE_NAME { "DistributedInput " };
118 return (GetName().find(INPUT_VIRTUAL_DEVICE_NAME) != std::string::npos);
119 }
120
MakeNetworkId(const std::string & phys) const121 std::string InputDeviceManager::Device::MakeNetworkId(const std::string &phys) const
122 {
123 std::vector<std::string> idParts;
124 const std::string SPLIT_SYMBOL { "|" };
125 StringSplit(phys, SPLIT_SYMBOL, idParts);
126 if (idParts.size() == NETWORK_ID_NUMS) {
127 return idParts[1];
128 }
129 return {};
130 }
131
GenerateDescriptor()132 std::string InputDeviceManager::Device::GenerateDescriptor()
133 {
134 const std::string phys = GetPhys();
135 const std::string SPLIT_SYMBOL { "|" };
136 const std::string DH_ID_PREFIX { "Input_" };
137 std::string descriptor;
138 if (IsRemote() && !phys.empty()) {
139 FI_HILOGD("physicalPath:%{public}s", phys.c_str());
140 std::vector<std::string> idParts;
141 StringSplit(phys.c_str(), SPLIT_SYMBOL, idParts);
142 if (idParts.size() == NETWORK_ID_NUMS) {
143 descriptor = idParts[DESCRIPTOR_INDEX];
144 }
145 return descriptor;
146 }
147
148 const std::string name = GetName();
149 const std::string uniq = GetUniq();
150 std::string rawDescriptor = StringPrintf(":%04x:%04x:", GetVendor(), GetProduct());
151
152 if (!uniq.empty()) {
153 rawDescriptor += "uniqueId:" + uniq;
154 }
155 if (!phys.empty()) {
156 rawDescriptor += "physicalPath:" + phys;
157 }
158 if (!name.empty()) {
159 rawDescriptor += "name:" + std::regex_replace(name, std::regex(" "), "");
160 }
161 descriptor = DH_ID_PREFIX + Sha256(rawDescriptor);
162 FI_HILOGD("Created descriptor raw:%{public}s", rawDescriptor.c_str());
163 return descriptor;
164 }
165
Sha256(const std::string & in) const166 std::string InputDeviceManager::Device::Sha256(const std::string &in) const
167 {
168 unsigned char out[SHA256_DIGEST_LENGTH * 2 + 1] = { 0 }; // 2:coefficient
169 SHA256_CTX ctx;
170 SHA256_Init(&ctx);
171 SHA256_Update(&ctx, in.data(), in.size());
172 SHA256_Final(&out[SHA256_DIGEST_LENGTH], &ctx);
173
174 constexpr int32_t width = 4;
175 constexpr unsigned char mask = 0x0F;
176 const char* hexCode = "0123456789abcdef";
177 constexpr int32_t DOUBLE_TIMES = 2;
178 for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
179 unsigned char value = out[SHA256_DIGEST_LENGTH + i];
180 out[i * DOUBLE_TIMES] = hexCode[(value >> width) & mask];
181 out[i * DOUBLE_TIMES + 1] = hexCode[value & mask];
182 }
183 out[SHA256_DIGEST_LENGTH * DOUBLE_TIMES] = 0;
184 return reinterpret_cast<char*>(out);
185 }
186
InputDeviceManager(IContext * env)187 InputDeviceManager::InputDeviceManager(IContext *env)
188 : env_(env)
189 {}
190
~InputDeviceManager()191 InputDeviceManager::~InputDeviceManager()
192 {
193 Disable();
194 }
195
AttachSender(Channel<CooperateEvent>::Sender sender)196 void InputDeviceManager::AttachSender(Channel<CooperateEvent>::Sender sender)
197 {
198 sender_ = sender;
199 }
200
Enable()201 bool InputDeviceManager::Enable()
202 {
203 CALL_DEBUG_ENTER;
204 if (observer_ != nullptr) {
205 return true;
206 }
207 observer_ = std::make_shared<DeviceObserver>(shared_from_this());
208 int32_t ret = env_->GetDeviceManager().AddDeviceObserver(observer_);
209 if (ret != RET_OK) {
210 FI_HILOGE("Failed to add observer");
211 observer_.reset();
212 return false;
213 }
214 env_->GetDeviceManager().RetriggerHotplug(observer_);
215 return true;
216 }
217
Disable()218 void InputDeviceManager::Disable()
219 {
220 CALL_DEBUG_ENTER;
221 CHKPV(observer_);
222 env_->GetDeviceManager().RemoveDeviceObserver(observer_);
223 observer_.reset();
224 devices_.clear();
225 }
226
IsRemote(int32_t id)227 bool InputDeviceManager::IsRemote(int32_t id)
228 {
229 if (auto devIter = devices_.find(id); devIter != devices_.end()) {
230 CHKPF(devIter->second);
231 return devIter->second->IsRemote();
232 }
233 return false;
234 }
235
GetCooperateDhids(int32_t deviceId) const236 std::vector<std::string> InputDeviceManager::GetCooperateDhids(int32_t deviceId) const
237 {
238 CALL_INFO_TRACE;
239 std::vector<std::string> inputDeviceDhids;
240 auto devIter = devices_.find(deviceId);
241 if (devIter == devices_.end()) {
242 FI_HILOGW("Cannot find pointer id:%{public}d", deviceId);
243 return inputDeviceDhids;
244 }
245 if (devIter->second == nullptr) {
246 FI_HILOGW("Device is nullptr");
247 return inputDeviceDhids;
248 }
249 std::shared_ptr<Device> dev = devIter->second;
250 if (!dev->IsPointerDevice()) {
251 FI_HILOGD("Not pointer device");
252 return inputDeviceDhids;
253 }
254 inputDeviceDhids.push_back(dev->GetDhid());
255 FI_HILOGD("unq:%{public}s, type:%{public}s", inputDeviceDhids.back().c_str(), "pointer");
256
257 const std::string localNetworkId { DSoftbusAdapter::GetLocalNetworkId() };
258 const std::string pointerNetworkId { dev->IsRemote() ? dev->GetNetworkId() : localNetworkId };
259
260 for (const auto &[id, dev] : devices_) {
261 CHKPC(dev);
262 const std::string networkId { dev->IsRemote() ? dev->GetNetworkId() : localNetworkId };
263 if (networkId != pointerNetworkId) {
264 continue;
265 }
266 if (dev->GetKeyboardType() == IDevice::KEYBOARD_TYPE_ALPHABETICKEYBOARD) {
267 inputDeviceDhids.push_back(dev->GetDhid());
268 FI_HILOGD("unq:%{public}s, type:%{public}s", inputDeviceDhids.back().c_str(), "supportkey");
269 }
270 }
271 return inputDeviceDhids;
272 }
273
GetCooperateDhids(const std::string & dhid,bool isRemote) const274 std::vector<std::string> InputDeviceManager::GetCooperateDhids(const std::string &dhid, bool isRemote) const
275 {
276 int32_t deviceId { -1 };
277 for (const auto &[id, dev] : devices_) {
278 CHKPC(dev);
279 if (dev->GetDhid() == dhid && dev->IsRemote() == isRemote) {
280 deviceId = id;
281 break;
282 }
283 }
284 return GetCooperateDhids(deviceId);
285 }
286
GetOriginNetworkId(int32_t id) const287 std::string InputDeviceManager::GetOriginNetworkId(int32_t id) const
288 {
289 CALL_INFO_TRACE;
290 auto devIter = devices_.find(id);
291 if (devIter == devices_.end()) {
292 FI_HILOGE("Failed to search for the device, id:%{public}d", id);
293 return {};
294 }
295 CHKPS(devIter->second);
296 auto OriginNetworkId = devIter->second->GetNetworkId();
297 if (OriginNetworkId.empty()) {
298 OriginNetworkId = DSoftbusAdapter::GetLocalNetworkId();
299 }
300 return OriginNetworkId;
301 }
302
GetOriginNetworkId(const std::string & dhid) const303 std::string InputDeviceManager::GetOriginNetworkId(const std::string &dhid) const
304 {
305 CALL_INFO_TRACE;
306 if (dhid.empty()) {
307 FI_HILOGD("The current netWorkId is an empty string");
308 return {};
309 }
310 for (const auto &[id, dev] : devices_) {
311 CHKPC(dev);
312 if (dev->IsRemote() && dev->GetDhid() == dhid) {
313 return dev->GetNetworkId();
314 }
315 }
316 FI_HILOGD("The current netWorkId is an empty string");
317 return {};
318 }
319
GetDhid(int32_t deviceId) const320 std::string InputDeviceManager::GetDhid(int32_t deviceId) const
321 {
322 CALL_INFO_TRACE;
323 if (auto devIter = devices_.find(deviceId); devIter != devices_.end()) {
324 if (devIter->second != nullptr) {
325 return devIter->second->GetDhid();
326 }
327 FI_HILOGW("Device is nullptr");
328 }
329 return {};
330 }
331
HasLocalPointerDevice() const332 bool InputDeviceManager::HasLocalPointerDevice() const
333 {
334 for (const auto &[id, dev] : devices_) {
335 CHKPC(dev);
336 if (!dev->IsRemote() && dev->IsPointerDevice()) {
337 FI_HILOGD("It is currently a mouse device");
338 return true;
339 }
340 }
341 FI_HILOGD("Not currently a mouse device");
342 return false;
343 }
344
OnDeviceAdded(std::shared_ptr<IDevice> device)345 void InputDeviceManager::OnDeviceAdded(std::shared_ptr<IDevice> device)
346 {
347 CALL_INFO_TRACE;
348 CHKPV(device);
349 auto dev = std::make_shared<InputDeviceManager::Device>(device);
350 devices_.insert_or_assign(dev->GetId(), dev);
351 if (dev->IsKeyboard()) {
352 sender_.Send(CooperateEvent(CooperateEventType::INPUT_PLUG_KEYBOARD, InputHotplugEvent {
353 .dhid = dev->GetDhid()
354 }));
355 }
356 FI_HILOGD("Add device %{public}d:%{public}s, Dhid:\"%{public}s\", Network id:\"%{public}s\", "
357 "local/remote:\"%{public}s\"", device->GetId(), device->GetDevPath().c_str(), dev->GetDhid().c_str(),
358 dev->GetNetworkId().c_str(), dev->IsRemote() ? "Remote Device" : "Local Device");
359 }
360
OnDeviceRemoved(std::shared_ptr<IDevice> device)361 void InputDeviceManager::OnDeviceRemoved(std::shared_ptr<IDevice> device)
362 {
363 CALL_INFO_TRACE;
364 CHKPV(device);
365 auto iter = devices_.find(device->GetId());
366 if (iter == devices_.end()) {
367 FI_HILOGE("The device corresponding to the current id:%{public}d cannot be found", device->GetId());
368 return;
369 }
370 std::shared_ptr<Device> dev = iter->second;
371 devices_.erase(iter);
372 CHKPV(dev);
373 if (dev->IsPointerDevice()) {
374 sender_.Send(CooperateEvent(CooperateEventType::INPUT_UNPLUG_POINTER, InputHotplugEvent {
375 .dhid = dev->GetDhid()
376 }));
377 } else if (dev->IsKeyboard() && !dev->IsRemote() &&
378 (dev->GetKeyboardType() == IDevice::KEYBOARD_TYPE_ALPHABETICKEYBOARD)) {
379 sender_.Send(CooperateEvent(CooperateEventType::INPUT_UNPLUG_KEYBOARD, InputHotplugEvent {
380 .dhid = dev->GetDhid()
381 }));
382 }
383 }
384
DeviceObserver(std::shared_ptr<InputDeviceManager> devMgr)385 InputDeviceManager::DeviceObserver::DeviceObserver(std::shared_ptr<InputDeviceManager> devMgr)
386 : devMgr_(devMgr)
387 {}
388
OnDeviceAdded(std::shared_ptr<IDevice> device)389 void InputDeviceManager::DeviceObserver::OnDeviceAdded(std::shared_ptr<IDevice> device)
390 {
391 std::shared_ptr<InputDeviceManager> devMgr = devMgr_.lock();
392 if (devMgr == nullptr) {
393 FI_HILOGE("Reference has expired");
394 return;
395 }
396 devMgr->OnDeviceAdded(device);
397 }
398
OnDeviceRemoved(std::shared_ptr<IDevice> device)399 void InputDeviceManager::DeviceObserver::OnDeviceRemoved(std::shared_ptr<IDevice> device)
400 {
401 std::shared_ptr<InputDeviceManager> devMgr = devMgr_.lock();
402 if (devMgr == nullptr) {
403 FI_HILOGE("Reference has expired");
404 return;
405 }
406 devMgr->OnDeviceRemoved(device);
407 }
408 } // namespace Cooperate
409 } // namespace DeviceStatus
410 } // namespace Msdp
411 } // namespace OHOS