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