• 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 #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