• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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