1 /*
2 * Copyright (c) 2022-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 "device_manager.h"
17
18 #include <algorithm>
19 #include <cstring>
20 #include <regex>
21 #include <unistd.h>
22 #include "special_input_device_parser.h"
23 #include <sys/epoll.h>
24 #include <sys/stat.h>
25
26 #ifdef OHOS_BUILD_ENABLE_COORDINATION
27 #include "coordination_util.h"
28 #endif // OHOS_BUILD_ENABLE_COORDINATION
29 #include "device.h"
30 #include "devicestatus_define.h"
31 #include "fi_log.h"
32 #include "input_manager.h"
33 #include "napi_constants.h"
34 #include "utility.h"
35
36 #undef LOG_TAG
37 #define LOG_TAG "DeviceManager"
38
39 namespace OHOS {
40 namespace Msdp {
41 namespace DeviceStatus {
42 namespace {
43 constexpr size_t EXPECTED_N_SUBMATCHES { 2 };
44 constexpr size_t EXPECTED_SUBMATCH { 1 };
45 const std::string VIRTUAL_TRACK_PAD_NAME { "VirtualTrackpad" };
46 constexpr int32_t INVALID_DEVICE_ID { -1 };
47 } // namespace
48
HotplugHandler(DeviceManager & devMgr)49 DeviceManager::HotplugHandler::HotplugHandler(DeviceManager &devMgr)
50 : devMgr_(devMgr)
51 {}
52
AddDevice(const std::string & devNode)53 void DeviceManager::HotplugHandler::AddDevice(const std::string &devNode)
54 {
55 devMgr_.AddDevice(devNode);
56 }
57
RemoveDevice(const std::string & devNode)58 void DeviceManager::HotplugHandler::RemoveDevice(const std::string &devNode)
59 {
60 devMgr_.RemoveDevice(devNode);
61 }
62
DeviceManager()63 DeviceManager::DeviceManager()
64 : hotplug_(*this)
65 {
66 monitor_ = std::make_shared<Monitor>();
67 }
68
Init(IContext * context)69 int32_t DeviceManager::Init(IContext *context)
70 {
71 CALL_INFO_TRACE;
72 CHKPR(context, RET_ERR);
73 int32_t ret = context->GetDelegateTasks().PostSyncTask([this, context] {
74 return this->OnInit(context);
75 });
76 if (ret != RET_OK) {
77 FI_HILOGE("Post sync task failed");
78 }
79 return ret;
80 }
81
OnInit(IContext * context)82 int32_t DeviceManager::OnInit(IContext *context)
83 {
84 CALL_INFO_TRACE;
85 CHKPR(context, RET_ERR);
86 CHKPR(monitor_, RET_ERR);
87 context_ = context;
88 monitor_->SetDeviceMgr(&hotplug_);
89 enumerator_.SetDeviceMgr(&hotplug_);
90 return RET_OK;
91 }
92
Enable()93 int32_t DeviceManager::Enable()
94 {
95 CALL_INFO_TRACE;
96 CHKPR(context_, RET_ERR);
97 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this] {
98 return this->OnEnable();
99 });
100 if (ret != RET_OK) {
101 FI_HILOGE("Post sync task failed");
102 }
103 return ret;
104 }
105
OnEnable()106 int32_t DeviceManager::OnEnable()
107 {
108 CALL_DEBUG_ENTER;
109 if (!epollMgr_.Open()) {
110 FI_HILOGE("EpollMgr::Open fail");
111 return RET_ERR;
112 }
113 CHKPR(monitor_, RET_ERR);
114 auto ret = monitor_->Enable();
115 if (ret != RET_OK) {
116 goto CLOSE_EPOLL;
117 }
118 if (!epollMgr_.Add(monitor_)) {
119 ret = RET_ERR;
120 goto DISABLE_MONITOR;
121 }
122 enumerator_.ScanDevices();
123 return RET_OK;
124
125 DISABLE_MONITOR:
126 monitor_->Disable();
127
128 CLOSE_EPOLL:
129 epollMgr_.Close();
130 return ret;
131 }
132
Disable()133 int32_t DeviceManager::Disable()
134 {
135 CALL_INFO_TRACE;
136 CHKPR(context_, RET_ERR);
137 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this] {
138 return this->OnDisable();
139 });
140 if (ret != RET_OK) {
141 FI_HILOGE("PostSyncTask failed");
142 }
143 return ret;
144 }
145
OnDisable()146 int32_t DeviceManager::OnDisable()
147 {
148 CHKPR(monitor_, RET_ERR);
149 epollMgr_.Remove(monitor_);
150 monitor_->Disable();
151 epollMgr_.Close();
152 return RET_OK;
153 }
154
FindDevice(const std::string & devPath)155 std::shared_ptr<IDevice> DeviceManager::FindDevice(const std::string &devPath)
156 {
157 auto tIter = std::find_if(devices_.cbegin(), devices_.cend(),
158 [devPath](const auto &item) {
159 return ((item.second != nullptr) && (item.second->GetDevPath() == devPath));
160 });
161 return (tIter != devices_.cend() ? tIter->second : nullptr);
162 }
163
ParseDeviceId(const std::string & devNode)164 int32_t DeviceManager::ParseDeviceId(const std::string &devNode)
165 {
166 CALL_DEBUG_ENTER;
167 std::regex pattern("^event(\\d+)$");
168 std::smatch mr;
169
170 if (std::regex_match(devNode, mr, pattern)) {
171 if (mr.ready() && mr.size() == EXPECTED_N_SUBMATCHES) {
172 std::string value = mr[EXPECTED_SUBMATCH].str();
173 if ((!value.empty()) && (Utility::IsInteger(value))) {
174 return std::stoi(mr[EXPECTED_SUBMATCH].str());
175 }
176 }
177 }
178 return RET_ERR;
179 }
180
AddDevice(const std::string & devNode)181 std::shared_ptr<IDevice> DeviceManager::AddDevice(const std::string &devNode)
182 {
183 CALL_INFO_TRACE;
184 const std::string SYS_INPUT_PATH { "/sys/class/input/" };
185 const std::string devPath { DEV_INPUT_PATH + devNode };
186 struct stat statbuf;
187
188 if (stat(devPath.c_str(), &statbuf) != 0) {
189 FI_HILOGE("Invalid device path:%{private}s", devPath.c_str());
190 return nullptr;
191 }
192 if (!S_ISCHR(statbuf.st_mode)) {
193 FI_HILOGE("Not character device:%{private}s", devPath.c_str());
194 return nullptr;
195 }
196
197 int32_t deviceId = ParseDeviceId(devNode);
198 if (deviceId < 0) {
199 FI_HILOGE("Parsing device name failed:%{private}s", devNode.c_str());
200 return nullptr;
201 }
202
203 std::shared_ptr<IDevice> dev = FindDevice(devPath);
204 if (dev != nullptr) {
205 FI_HILOGD("Already exists:%{private}s", devPath.c_str());
206 return dev;
207 }
208
209 const std::string lSysPath { SYS_INPUT_PATH + devNode };
210 char rpath[PATH_MAX];
211 if (realpath(lSysPath.c_str(), rpath) == nullptr) {
212 FI_HILOGE("Invalid sysPath:%{private}s", lSysPath.c_str());
213 return nullptr;
214 }
215
216 dev = std::make_shared<Device>(deviceId);
217 dev->SetDevPath(devPath);
218 dev->SetSysPath(std::string(rpath));
219 if (dev->Open() != RET_OK) {
220 FI_HILOGE("Unable to open \'%{private}s\'", devPath.c_str());
221 return nullptr;
222 }
223 auto ret = devices_.insert_or_assign(dev->GetId(), dev);
224 if (ret.second) {
225 FI_HILOGI("\'%{public}s\' added", dev->GetName().c_str());
226 OnDeviceAdded(dev);
227 }
228 return dev;
229 }
230
IsLocalPointerDevice(std::shared_ptr<MMI::InputDevice> device)231 bool DeviceManager::IsLocalPointerDevice(std::shared_ptr<MMI::InputDevice> device)
232 {
233 CHKPR(device, false);
234 return device->HasCapability(MMI::InputDeviceCapability::INPUT_DEV_CAP_POINTER);
235 }
236
IsVirtualTrackpad(std::shared_ptr<MMI::InputDevice> device)237 bool DeviceManager::IsVirtualTrackpad(std::shared_ptr<MMI::InputDevice> device)
238 {
239 CHKPR(device, false);
240 return device->GetName() == VIRTUAL_TRACK_PAD_NAME;
241 }
242
RemoveDevice(const std::string & devNode)243 std::shared_ptr<IDevice> DeviceManager::RemoveDevice(const std::string &devNode)
244 {
245 CALL_INFO_TRACE;
246 const std::string devPath { DEV_INPUT_PATH + devNode };
247
248 for (auto devIter = devices_.begin(); devIter != devices_.end(); ++devIter) {
249 std::shared_ptr<IDevice> dev = devIter->second;
250 CHKPC(dev);
251 if (dev->GetDevPath() == devPath) {
252 devices_.erase(devIter);
253 FI_HILOGI("\'%{public}s\' removed", dev->GetName().c_str());
254 dev->Close();
255 OnDeviceRemoved(dev);
256 return dev;
257 }
258 }
259 FI_HILOGE("\'%{public}s\' was not found", devNode.c_str());
260 return nullptr;
261 }
262
OnDeviceAdded(std::shared_ptr<IDevice> dev)263 void DeviceManager::OnDeviceAdded(std::shared_ptr<IDevice> dev)
264 {
265 DeviceInfo(dev);
266 for (const auto &observer : observers_) {
267 std::shared_ptr<IDeviceObserver> ptr = observer.lock();
268 CHKPC(ptr);
269 ptr->OnDeviceAdded(dev);
270 }
271 }
272
DeviceInfo(std::shared_ptr<IDevice> dev)273 void DeviceManager::DeviceInfo(std::shared_ptr<IDevice> dev)
274 {
275 CHKPV(dev);
276 FI_HILOGI("Add device %{public}d:%{private}s", dev->GetId(), dev->GetDevPath().c_str());
277 FI_HILOGI(" sysPath: \"%{private}s\"", dev->GetSysPath().c_str());
278 FI_HILOGD(" bus: %{public}04x", dev->GetBus());
279 FI_HILOGI(" vendor: %{public}04x", dev->GetVendor());
280 FI_HILOGD(" product: %{public}04x", dev->GetProduct());
281 FI_HILOGD(" version: %{public}04x", dev->GetVersion());
282 FI_HILOGI(" name: \"%{public}s\"", Utility::Anonymize(dev->GetName()).c_str());
283 FI_HILOGD(" location: \"%{private}s\"", dev->GetPhys().c_str());
284 FI_HILOGD(" unique id: \"%{private}s\"", dev->GetUniq().c_str());
285 FI_HILOGI(" is pointer: %{public}s, is keyboard:%{public}s",
286 dev->IsPointerDevice() ? "True" : "False", dev->IsKeyboard() ? "True" : "False");
287 }
288
OnDeviceRemoved(std::shared_ptr<IDevice> dev)289 void DeviceManager::OnDeviceRemoved(std::shared_ptr<IDevice> dev)
290 {
291 for (const auto &observer : observers_) {
292 std::shared_ptr<IDeviceObserver> ptr = observer.lock();
293 CHKPC(ptr);
294 ptr->OnDeviceRemoved(dev);
295 }
296 }
297
Dispatch(const struct epoll_event & ev)298 void DeviceManager::Dispatch(const struct epoll_event &ev)
299 {
300 CALL_DEBUG_ENTER;
301 CHKPV(context_);
302 int32_t ret = context_->GetDelegateTasks().PostAsyncTask([this, ev] {
303 return this->OnEpollDispatch(ev.events);
304 });
305 if (ret != RET_OK) {
306 FI_HILOGE("PostAsyncTask failed");
307 }
308 }
309
OnEpollDispatch(uint32_t events)310 int32_t DeviceManager::OnEpollDispatch(uint32_t events)
311 {
312 struct epoll_event ev {};
313 ev.events = events;
314 ev.data.ptr = &epollMgr_;
315
316 epollMgr_.Dispatch(ev);
317 return RET_OK;
318 }
319
GetDevice(int32_t id) const320 std::shared_ptr<IDevice> DeviceManager::GetDevice(int32_t id) const
321 {
322 CHKPP(context_);
323 std::packaged_task<std::shared_ptr<IDevice>(int32_t)> task {[this](int32_t id) {
324 return this->OnGetDevice(id);
325 }};
326 auto fu = task.get_future();
327
328 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this, &task, id] {
329 return this->RunGetDevice(std::ref(task), id);
330 });
331 if (ret != RET_OK) {
332 FI_HILOGE("Post task failed");
333 return nullptr;
334 }
335 return fu.get();
336 }
337
OnGetDevice(int32_t id) const338 std::shared_ptr<IDevice> DeviceManager::OnGetDevice(int32_t id) const
339 {
340 if (auto devIter = devices_.find(id); devIter != devices_.cend()) {
341 return devIter->second;
342 }
343 FI_HILOGE("Device id not found");
344 return nullptr;
345 }
346
RunGetDevice(std::packaged_task<std::shared_ptr<IDevice> (int32_t)> & task,int32_t id) const347 int32_t DeviceManager::RunGetDevice(std::packaged_task<std::shared_ptr<IDevice>(int32_t)> &task,
348 int32_t id) const
349 {
350 task(id);
351 return RET_OK;
352 }
353
RetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)354 void DeviceManager::RetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)
355 {
356 CALL_INFO_TRACE;
357 CHKPV(context_);
358 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this, observer] {
359 return this->OnRetriggerHotplug(observer);
360 });
361 if (ret != RET_OK) {
362 FI_HILOGE("Post task failed");
363 }
364 }
365
OnRetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)366 int32_t DeviceManager::OnRetriggerHotplug(std::weak_ptr<IDeviceObserver> observer)
367 {
368 CALL_INFO_TRACE;
369 CHKPR(observer, RET_ERR);
370 std::shared_ptr<IDeviceObserver> ptr = observer.lock();
371 CHKPR(ptr, RET_ERR);
372 std::for_each(devices_.cbegin(), devices_.cend(),
373 [ptr] (const auto &item) {
374 if (item.second != nullptr) {
375 ptr->OnDeviceAdded(item.second);
376 }
377 });
378 return RET_OK;
379 }
380
AddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)381 int32_t DeviceManager::AddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
382 {
383 CALL_DEBUG_ENTER;
384 CHKPR(context_, RET_ERR);
385 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this, observer] {
386 return this->OnAddDeviceObserver(observer);
387 });
388 if (ret != RET_OK) {
389 FI_HILOGE("Post task failed");
390 }
391 return ret;
392 }
393
OnAddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)394 int32_t DeviceManager::OnAddDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
395 {
396 CALL_INFO_TRACE;
397 CHKPR(observer, RET_ERR);
398 auto ret = observers_.insert(observer);
399 if (!ret.second) {
400 FI_HILOGW("Observer is duplicated");
401 }
402 return RET_OK;
403 }
404
RemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)405 void DeviceManager::RemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
406 {
407 CALL_INFO_TRACE;
408 CHKPV(context_);
409 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this, observer] {
410 return this->OnRemoveDeviceObserver(observer);
411 });
412 if (ret != RET_OK) {
413 FI_HILOGE("Post task failed");
414 }
415 }
416
OnRemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)417 int32_t DeviceManager::OnRemoveDeviceObserver(std::weak_ptr<IDeviceObserver> observer)
418 {
419 CALL_INFO_TRACE;
420 CHKPR(observer, RET_ERR);
421 observers_.erase(observer);
422 return RET_OK;
423 }
424
AnyOf(std::function<bool (std::shared_ptr<IDevice>)> pred)425 bool DeviceManager::AnyOf(std::function<bool(std::shared_ptr<IDevice>)> pred)
426 {
427 return std::any_of(devices_.cbegin(), devices_.cend(), [pred](const auto &item) {
428 return (pred != nullptr ? pred(item.second) : false);
429 });
430 }
431
HasLocalPointerDevice()432 bool DeviceManager::HasLocalPointerDevice()
433 {
434 return AnyOf([this](std::shared_ptr<IDevice> dev) {
435 DeviceInfo(dev);
436 if ((dev == nullptr) || IsFakePointerDevice(dev)) {
437 return false;
438 }
439 return (dev->IsPointerDevice() && !dev->IsRemote());
440 });
441 }
442
IsFakePointerDevice(std::shared_ptr<IDevice> dev)443 bool DeviceManager::IsFakePointerDevice(std::shared_ptr<IDevice> dev)
444 {
445 if (dev == nullptr) {
446 return false;
447 }
448 bool isPointerDevice { false };
449 if (SPECIAL_INPUT_DEVICE_PARSER.IsPointerDevice(dev->GetName(), isPointerDevice) != RET_OK) {
450 return false;
451 }
452 return !isPointerDevice;
453 }
454
HasLocalKeyboardDevice()455 bool DeviceManager::HasLocalKeyboardDevice()
456 {
457 return AnyOf([this](std::shared_ptr<IDevice> dev) {
458 CHKPR(dev, false);
459 return (dev->IsKeyboard() && !dev->IsRemote());
460 });
461 }
462
HasKeyboard()463 bool DeviceManager::HasKeyboard()
464 {
465 return AnyOf([this](std::shared_ptr<IDevice> dev) {
466 if ((dev == nullptr)) {
467 return false;
468 }
469 return (dev->IsKeyboard() && !dev->IsRemote() &&
470 dev->GetKeyboardType() == IDevice::KeyboardType::KEYBOARD_TYPE_ALPHABETICKEYBOARD);
471 });
472 }
473
GetKeyboard()474 std::vector<std::shared_ptr<IDevice>> DeviceManager::GetKeyboard()
475 {
476 std::vector<std::shared_ptr<IDevice>> keyboards;
477 for (const auto &dev : devices_) {
478 if (dev.second != nullptr) {
479 if (dev.second->IsKeyboard() && !dev.second->IsRemote() &&
480 dev.second->GetKeyboardType() == IDevice::KeyboardType::KEYBOARD_TYPE_ALPHABETICKEYBOARD) {
481 keyboards.push_back(dev.second);
482 }
483 }
484 }
485 return keyboards;
486 }
487
GetPointerDevice()488 std::vector<std::shared_ptr<IDevice>> DeviceManager::GetPointerDevice()
489 {
490 if (!HasLocalPointerDevice()) {
491 return {};
492 }
493 std::vector<std::shared_ptr<IDevice>> pointerDevices;
494 for (const auto &dev : devices_) {
495 if (dev.second != nullptr) {
496 if (dev.second->IsPointerDevice() && !dev.second->IsRemote() &&
497 !IsFakePointerDevice(dev.second)) {
498 pointerDevices.push_back(dev.second);
499 }
500 }
501 }
502 return pointerDevices;
503 }
504
GetVirTrackPad()505 std::vector<std::shared_ptr<IDevice>> DeviceManager::GetVirTrackPad()
506 {
507 std::vector<int32_t> deviceIds;
508 std::vector<std::shared_ptr<IDevice>> VirTrackPadDevices;
509 if (MMI::InputManager::GetInstance()->GetDeviceIds(
510 [&deviceIds](std::vector<int32_t> &ids) { deviceIds = ids; }) != RET_OK) {
511 FI_HILOGE("GetDeviceIds failed");
512 return VirTrackPadDevices;
513 }
514 for (int32_t dev : deviceIds) {
515 std::shared_ptr<Device> virDev = std::make_shared<Device>(INVALID_DEVICE_ID);
516 auto ret = MMI::InputManager::GetInstance()->GetDevice(dev,
517 [virDev, &VirTrackPadDevices, dev, this] (
518 std::shared_ptr<MMI::InputDevice> device) {
519 if (this->IsLocalPointerDevice(device) && this->IsVirtualTrackpad(device)) {
520 FI_HILOGI("Has VirtualTrackpad");
521 virDev->SetName(device->GetName().c_str());
522 virDev->SetId(dev);
523 VirTrackPadDevices.push_back(virDev);
524 }
525 });
526 if (ret != RET_OK) {
527 FI_HILOGE("GetDevice failed");
528 }
529 }
530 return VirTrackPadDevices;
531 }
532
SetPencilAirMouse(bool existAirMouse)533 void DeviceManager::SetPencilAirMouse(bool existAirMouse)
534 {
535 FI_HILOGI("Set pencil air mouse:%{public}s", existAirMouse ? "true" : "false");
536 hasPencilAirMouse_ = existAirMouse;
537 }
538
HasPencilAirMouse()539 bool DeviceManager::HasPencilAirMouse()
540 {
541 FI_HILOGI("Has pencil air mouse:%{public}s", hasPencilAirMouse_ ? "true" : "false");
542 return hasPencilAirMouse_;
543 }
544
545 } // namespace DeviceStatus
546 } // namespace Msdp
547 } // namespace OHOS