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 "coordination_device_manager.h"
17
18 #include <openssl/sha.h>
19 #include <regex>
20
21 #include "coordination_event_manager.h"
22 #include "coordination_sm.h"
23 #include "coordination_util.h"
24 #include "devicestatus_define.h"
25 #include "napi_constants.h"
26
27 namespace OHOS {
28 namespace Msdp {
29 namespace DeviceStatus {
30 namespace {
31 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "CoordinationDeviceManager" };
32 constexpr size_t NETWORK_ID_NUMS { 3 };
33 constexpr size_t DESCRIPTOR_INDEX { 2 };
34 } // namespace
35
CoordinationDeviceManager()36 CoordinationDeviceManager::CoordinationDeviceManager() {}
~CoordinationDeviceManager()37 CoordinationDeviceManager::~CoordinationDeviceManager() {}
38
Device(std::shared_ptr<IDevice> dev)39 CoordinationDeviceManager::Device::Device(std::shared_ptr<IDevice> dev)
40 : device_(dev)
41 {
42 Populate();
43 }
44
GetId() const45 int32_t CoordinationDeviceManager::Device::GetId() const
46 {
47 CHKPR(device_, RET_ERR);
48 return device_->GetId();
49 }
50
GetName() const51 std::string CoordinationDeviceManager::Device::GetName() const
52 {
53 CHKPS(device_);
54 return device_->GetName();
55 }
56
GetDhid() const57 std::string CoordinationDeviceManager::Device::GetDhid() const
58 {
59 return dhid_;
60 }
61
GetNetworkId() const62 std::string CoordinationDeviceManager::Device::GetNetworkId() const
63 {
64 return networkId_;
65 }
66
GetProduct() const67 int32_t CoordinationDeviceManager::Device::GetProduct() const
68 {
69 CHKPR(device_, RET_ERR);
70 return device_->GetProduct();
71 }
72
GetVendor() const73 int32_t CoordinationDeviceManager::Device::GetVendor() const
74 {
75 CHKPR(device_, RET_ERR);
76 return device_->GetVendor();
77 }
78
GetPhys() const79 std::string CoordinationDeviceManager::Device::GetPhys() const
80 {
81 CHKPS(device_);
82 return device_->GetPhys();
83 }
84
GetUniq() const85 std::string CoordinationDeviceManager::Device::GetUniq() const
86 {
87 CHKPS(device_);
88 return device_->GetUniq();
89 }
90
IsPointerDevice() const91 bool CoordinationDeviceManager::Device::IsPointerDevice() const
92 {
93 CHKPF(device_);
94 return device_->IsPointerDevice();
95 }
96
GetKeyboardType() const97 IDevice::KeyboardType CoordinationDeviceManager::Device::GetKeyboardType() const
98 {
99 CHKPR(device_, IDevice::KeyboardType::KEYBOARD_TYPE_NONE);
100 return device_->GetKeyboardType();
101 }
102
IsKeyboard() const103 bool CoordinationDeviceManager::Device::IsKeyboard() const
104 {
105 CHKPF(device_);
106 return device_->IsKeyboard();
107 }
108
Populate()109 void CoordinationDeviceManager::Device::Populate()
110 {
111 CALL_DEBUG_ENTER;
112 if (IsRemote()) {
113 networkId_ = MakeNetworkId(GetPhys());
114 }
115 dhid_ = GenerateDescriptor();
116 }
117
IsRemote()118 bool CoordinationDeviceManager::Device::IsRemote()
119 {
120 const std::string INPUT_VIRTUAL_DEVICE_NAME { "DistributedInput " };
121 return (GetName().find(INPUT_VIRTUAL_DEVICE_NAME) != std::string::npos);
122 }
123
MakeNetworkId(const std::string & phys) const124 std::string CoordinationDeviceManager::Device::MakeNetworkId(const std::string &phys) const
125 {
126 std::vector<std::string> idParts;
127 const std::string SPLIT_SYMBOL { "|" };
128 StringSplit(phys, SPLIT_SYMBOL, idParts);
129 if (idParts.size() == NETWORK_ID_NUMS) {
130 return idParts[1];
131 }
132 return {};
133 }
134
GenerateDescriptor()135 std::string CoordinationDeviceManager::Device::GenerateDescriptor()
136 {
137 const std::string phys = GetPhys();
138 const std::string SPLIT_SYMBOL { "|" };
139 const std::string DH_ID_PREFIX { "Input_" };
140 std::string descriptor;
141 if (IsRemote() && !phys.empty()) {
142 FI_HILOGD("physicalPath:%{public}s", phys.c_str());
143 std::vector<std::string> idParts;
144 StringSplit(phys.c_str(), SPLIT_SYMBOL, idParts);
145 if (idParts.size() == NETWORK_ID_NUMS) {
146 descriptor = idParts[DESCRIPTOR_INDEX];
147 }
148 return descriptor;
149 }
150
151 const std::string name = GetName();
152 const std::string uniq = GetUniq();
153 std::string rawDescriptor = StringPrintf(":%04x:%04x:", GetVendor(), GetProduct());
154
155 if (!uniq.empty()) {
156 rawDescriptor += "uniqueId:" + uniq;
157 }
158 if (!phys.empty()) {
159 rawDescriptor += "physicalPath:" + phys;
160 }
161 if (!name.empty()) {
162 rawDescriptor += "name:" + std::regex_replace(name, std::regex(" "), "");
163 }
164 descriptor = DH_ID_PREFIX + Sha256(rawDescriptor);
165 FI_HILOGD("Created descriptor raw:%{public}s", rawDescriptor.c_str());
166 return descriptor;
167 }
168
Sha256(const std::string & in) const169 std::string CoordinationDeviceManager::Device::Sha256(const std::string &in) const
170 {
171 unsigned char out[SHA256_DIGEST_LENGTH * 2 + 1] = { 0 };
172 SHA256_CTX ctx;
173 SHA256_Init(&ctx);
174 SHA256_Update(&ctx, in.data(), in.size());
175 SHA256_Final(&out[SHA256_DIGEST_LENGTH], &ctx);
176
177 constexpr int32_t width = 4;
178 constexpr unsigned char mask = 0x0F;
179 const char* hexCode = "0123456789abcdef";
180 constexpr int32_t DOUBLE_TIMES = 2;
181 for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
182 unsigned char value = out[SHA256_DIGEST_LENGTH + i];
183 out[i * DOUBLE_TIMES] = hexCode[(value >> width) & mask];
184 out[i * DOUBLE_TIMES + 1] = hexCode[value & mask];
185 }
186 out[SHA256_DIGEST_LENGTH * DOUBLE_TIMES] = 0;
187 return reinterpret_cast<char*>(out);
188 }
189
Init()190 void CoordinationDeviceManager::Init()
191 {
192 CALL_INFO_TRACE;
193 auto* context = COOR_EVENT_MGR->GetIContext();
194 CHKPV(context);
195 devObserver_ = std::make_shared<DeviceObserver>(*this);
196 context->GetDeviceManager().AddDeviceObserver(devObserver_);
197 context->GetDeviceManager().RetriggerHotplug(devObserver_);
198 }
199
IsRemote(int32_t id)200 bool CoordinationDeviceManager::IsRemote(int32_t id)
201 {
202 if (auto devIter = devices_.find(id); devIter != devices_.end()) {
203 CHKPF(devIter->second);
204 return devIter->second->IsRemote();
205 }
206 return false;
207 }
208
GetCoordinationDhids(int32_t deviceId) const209 std::vector<std::string> CoordinationDeviceManager::GetCoordinationDhids(int32_t deviceId) const
210 {
211 CALL_INFO_TRACE;
212 std::vector<std::string> inputDeviceDhids;
213 auto devIter = devices_.find(deviceId);
214 if (devIter == devices_.end()) {
215 FI_HILOGW("Cannot find pointer id:%{public}d", deviceId);
216 return inputDeviceDhids;
217 }
218 if (devIter->second == nullptr) {
219 FI_HILOGW("Device is nullptr");
220 return inputDeviceDhids;
221 }
222 std::shared_ptr<Device> dev = devIter->second;
223 if (!dev->IsPointerDevice()) {
224 FI_HILOGD("Not pointer device");
225 return inputDeviceDhids;
226 }
227 inputDeviceDhids.push_back(dev->GetDhid());
228 FI_HILOGD("unq:%{public}s, type:%{public}s", inputDeviceDhids.back().c_str(), "pointer");
229
230 const std::string localNetworkId { COORDINATION::GetLocalNetworkId() };
231 const std::string pointerNetworkId { dev->IsRemote() ? dev->GetNetworkId() : localNetworkId };
232
233 for (const auto &[id, dev] : devices_) {
234 CHKPC(dev);
235 const std::string networkId { dev->IsRemote() ? dev->GetNetworkId() : localNetworkId };
236 if (networkId != pointerNetworkId) {
237 continue;
238 }
239 if (dev->GetKeyboardType() == IDevice::KEYBOARD_TYPE_ALPHABETICKEYBOARD) {
240 inputDeviceDhids.push_back(dev->GetDhid());
241 FI_HILOGD("unq:%{public}s, type:%{public}s", inputDeviceDhids.back().c_str(), "supportkey");
242 }
243 }
244 return inputDeviceDhids;
245 }
246
GetCoordinationDhids(const std::string & dhid) const247 std::vector<std::string> CoordinationDeviceManager::GetCoordinationDhids(const std::string &dhid) const
248 {
249 int32_t deviceId { -1 };
250 for (const auto &[id, dev] : devices_) {
251 CHKPC(dev);
252 if (dev->GetDhid() == dhid) {
253 deviceId = id;
254 break;
255 }
256 }
257 return GetCoordinationDhids(deviceId);
258 }
259
GetOriginNetworkId(int32_t id) const260 std::string CoordinationDeviceManager::GetOriginNetworkId(int32_t id) const
261 {
262 CALL_INFO_TRACE;
263 auto devIter = devices_.find(id);
264 if (devIter == devices_.end()) {
265 FI_HILOGE("Failed to search for the device, id:%{public}d", id);
266 return {};
267 }
268 CHKPS(devIter->second);
269 auto OriginNetworkId = devIter->second->GetNetworkId();
270 if (OriginNetworkId.empty()) {
271 OriginNetworkId = COORDINATION::GetLocalNetworkId();
272 }
273 return OriginNetworkId;
274 }
275
GetOriginNetworkId(const std::string & dhid) const276 std::string CoordinationDeviceManager::GetOriginNetworkId(const std::string &dhid) const
277 {
278 CALL_INFO_TRACE;
279 if (dhid.empty()) {
280 FI_HILOGD("The current netWorkId is an empty string");
281 return {};
282 }
283 for (const auto &[id, dev] : devices_) {
284 CHKPC(dev);
285 if (dev->IsRemote() && dev->GetDhid() == dhid) {
286 return dev->GetNetworkId();
287 }
288 }
289 FI_HILOGD("The current netWorkId is an empty string");
290 return {};
291 }
292
GetDhid(int32_t deviceId) const293 std::string CoordinationDeviceManager::GetDhid(int32_t deviceId) const
294 {
295 CALL_INFO_TRACE;
296 if (auto devIter = devices_.find(deviceId); devIter != devices_.end()) {
297 if (devIter->second != nullptr) {
298 return devIter->second->GetDhid();
299 }
300 FI_HILOGW("Device is nullptr");
301 }
302 return {};
303 }
304
HasLocalPointerDevice() const305 bool CoordinationDeviceManager::HasLocalPointerDevice() const
306 {
307 for (const auto &[id, dev] : devices_) {
308 CHKPC(dev);
309 if (!dev->IsRemote() && dev->IsPointerDevice()) {
310 FI_HILOGD("It is currently a mouse device");
311 return true;
312 }
313 }
314 FI_HILOGD("Not currently a mouse device");
315 return false;
316 }
317
OnDeviceAdded(std::shared_ptr<IDevice> device)318 void CoordinationDeviceManager::OnDeviceAdded(std::shared_ptr<IDevice> device)
319 {
320 CALL_INFO_TRACE;
321 CHKPV(device);
322 auto dev = std::make_shared<CoordinationDeviceManager::Device>(device);
323 devices_.insert_or_assign(dev->GetId(), dev);
324 if (dev->IsKeyboard()) {
325 COOR_SM->OnKeyboardOnline(dev->GetDhid());
326 }
327 FI_HILOGD("Add device %{public}d:%{public}s, Dhid:\"%{public}s\", Network id:\"%{public}s\", "
328 "local/remote:\"%{public}s\"", device->GetId(), device->GetDevPath().c_str(), dev->GetDhid().c_str(),
329 dev->GetNetworkId().c_str(), dev->IsRemote() ? "Remote Device" : "Local Device");
330 }
331
OnDeviceRemoved(std::shared_ptr<IDevice> device)332 void CoordinationDeviceManager::OnDeviceRemoved(std::shared_ptr<IDevice> device)
333 {
334 CALL_INFO_TRACE;
335 CHKPV(device);
336 auto iter = devices_.find(device->GetId());
337 if (iter == devices_.end()) {
338 FI_HILOGE("The device corresponding to the current id:%{public}d cannot be found", device->GetId());
339 return;
340 }
341 std::shared_ptr<Device> dev = iter->second;
342 CHKPV(dev);
343 auto dhids = GetCoordinationDhids(dev->GetId());
344 devices_.erase(iter);
345 if (device->IsPointerDevice()) {
346 COOR_SM->OnPointerOffline(dev->GetDhid(), dhids);
347 } else if (device->IsKeyboard()) {
348 if (!dev->IsRemote() && dev->GetKeyboardType() == IDevice::KEYBOARD_TYPE_ALPHABETICKEYBOARD) {
349 COOR_SM->OnKeyboardOffline(dev->GetDhid());
350 }
351 }
352 }
353
DeviceObserver(CoordinationDeviceManager & cooDevMgr)354 CoordinationDeviceManager::DeviceObserver::DeviceObserver(CoordinationDeviceManager &cooDevMgr)
355 : cooDevMgr_(cooDevMgr)
356 {}
357
OnDeviceAdded(std::shared_ptr<IDevice> device)358 void CoordinationDeviceManager::DeviceObserver::OnDeviceAdded(std::shared_ptr<IDevice> device)
359 {
360 cooDevMgr_.OnDeviceAdded(device);
361 }
362
OnDeviceRemoved(std::shared_ptr<IDevice> device)363 void CoordinationDeviceManager::DeviceObserver::OnDeviceRemoved(std::shared_ptr<IDevice> device)
364 {
365 cooDevMgr_.OnDeviceRemoved(device);
366 }
367 } // namespace DeviceStatus
368 } // namespace Msdp
369 } // namespace OHOS