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