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 
Init(IContext * context)65 int32_t DeviceManager::Init(IContext *context)
66 {
67     CALL_INFO_TRACE;
68     CHKPR(context, RET_ERR);
69     int32_t ret = context->GetDelegateTasks().PostSyncTask([this, context] {
70         return this->OnInit(context);
71     });
72     if (ret != RET_OK) {
73         FI_HILOGE("Post sync task failed");
74     }
75     return ret;
76 }
77 
OnInit(IContext * context)78 int32_t DeviceManager::OnInit(IContext *context)
79 {
80     CALL_INFO_TRACE;
81     CHKPR(context, RET_ERR);
82     context_ = context;
83     monitor_.SetDeviceMgr(&hotplug_);
84     enumerator_.SetDeviceMgr(&hotplug_);
85     return RET_OK;
86 }
87 
Enable()88 int32_t DeviceManager::Enable()
89 {
90     CALL_INFO_TRACE;
91     CHKPR(context_, RET_ERR);
92     int32_t ret = context_->GetDelegateTasks().PostSyncTask([this] {
93         return this->OnEnable();
94     });
95     if (ret != RET_OK) {
96         FI_HILOGE("Post sync task failed");
97     }
98     return ret;
99 }
100 
OnEnable()101 int32_t DeviceManager::OnEnable()
102 {
103     CALL_DEBUG_ENTER;
104     epollMgr_ = std::make_shared<EpollManager>();
105     int32_t ret = epollMgr_->Open();
106     if (ret != RET_OK) {
107         return ret;
108     }
109     ret = monitor_.Enable();
110     if (ret != RET_OK) {
111         goto CLOSE_EPOLL;
112     }
113     ret = epollMgr_->Add(monitor_);
114     if (ret != RET_OK) {
115         goto DISABLE_MONITOR;
116     }
117     enumerator_.ScanDevices();
118     return RET_OK;
119 
120 DISABLE_MONITOR:
121     monitor_.Disable();
122 
123 CLOSE_EPOLL:
124     epollMgr_.reset();
125     return ret;
126 }
127 
Disable()128 int32_t DeviceManager::Disable()
129 {
130     CALL_INFO_TRACE;
131     CHKPR(context_, RET_ERR);
132     int32_t ret = context_->GetDelegateTasks().PostSyncTask([this] {
133         return this->OnDisable();
134     });
135     if (ret != RET_OK) {
136         FI_HILOGE("PostSyncTask failed");
137     }
138     return ret;
139 }
140 
OnDisable()141 int32_t DeviceManager::OnDisable()
142 {
143     CHKPR(epollMgr_, RET_ERR);
144     epollMgr_->Remove(monitor_);
145     monitor_.Disable();
146     epollMgr_.reset();
147     return RET_OK;
148 }
149 
FindDevice(const std::string & devPath)150 std::shared_ptr<IDevice> DeviceManager::FindDevice(const std::string &devPath)
151 {
152     auto tIter = std::find_if(devices_.cbegin(), devices_.cend(),
153         [devPath](const auto &item) {
154             return ((item.second != nullptr) && (item.second->GetDevPath() == devPath));
155         });
156     return (tIter != devices_.cend() ? tIter->second : nullptr);
157 }
158 
ParseDeviceId(const std::string & devNode)159 int32_t DeviceManager::ParseDeviceId(const std::string &devNode)
160 {
161     CALL_DEBUG_ENTER;
162     std::regex pattern("^event(\\d+)$");
163     std::smatch mr;
164 
165     if (std::regex_match(devNode, mr, pattern)) {
166         if (mr.ready() && mr.size() == EXPECTED_N_SUBMATCHES) {
167             return std::stoi(mr[EXPECTED_SUBMATCH].str());
168         }
169     }
170     return RET_ERR;
171 }
172 
AddDevice(const std::string & devNode)173 std::shared_ptr<IDevice> DeviceManager::AddDevice(const std::string &devNode)
174 {
175     const std::string SYS_INPUT_PATH { "/sys/class/input/" };
176     const std::string devPath { DEV_INPUT_PATH + devNode };
177     struct stat statbuf;
178 
179     if (stat(devPath.c_str(), &statbuf) != 0) {
180         FI_HILOGD("Invalid device path:%{private}s", devPath.c_str());
181         return nullptr;
182     }
183     if (!S_ISCHR(statbuf.st_mode)) {
184         FI_HILOGD("Not character device:%{public}s", devPath.c_str());
185         return nullptr;
186     }
187 
188     int32_t deviceId = ParseDeviceId(devNode);
189     if (deviceId < 0) {
190         FI_HILOGE("Parsing device name failed:%{public}s", devNode.c_str());
191         return nullptr;
192     }
193 
194     std::shared_ptr<IDevice> dev = FindDevice(devPath);
195     if (dev != nullptr) {
196         FI_HILOGD("Already exists:%{public}s", devPath.c_str());
197         return dev;
198     }
199 
200     const std::string lSysPath { SYS_INPUT_PATH + devNode };
201     char rpath[PATH_MAX];
202     if (realpath(lSysPath.c_str(), rpath) == nullptr) {
203         FI_HILOGD("Invalid sysPath:%{private}s", lSysPath.c_str());
204         return nullptr;
205     }
206 
207     dev = std::make_shared<Device>(deviceId);
208     dev->SetDevPath(devPath);
209     dev->SetSysPath(std::string(rpath));
210     if (dev->Open() != RET_OK) {
211         FI_HILOGE("Unable to open \'%{public}s\'", devPath.c_str());
212         return nullptr;
213     }
214     auto ret = devices_.insert_or_assign(dev->GetId(), dev);
215     if (ret.second) {
216         FI_HILOGD("\'%{public}s\' added", dev->GetName().c_str());
217         OnDeviceAdded(dev);
218     }
219     return dev;
220 }
221 
RemoveDevice(const std::string & devNode)222 std::shared_ptr<IDevice> DeviceManager::RemoveDevice(const std::string &devNode)
223 {
224     CALL_INFO_TRACE;
225     const std::string devPath { DEV_INPUT_PATH + devNode };
226 
227     for (auto devIter = devices_.begin(); devIter != devices_.end(); ++devIter) {
228         std::shared_ptr<IDevice> dev = devIter->second;
229         CHKPC(dev);
230         if (dev->GetDevPath() == devPath) {
231             devices_.erase(devIter);
232             FI_HILOGD("\'%{public}s\' removed", dev->GetName().c_str());
233             dev->Close();
234             OnDeviceRemoved(dev);
235             return dev;
236         }
237     }
238     FI_HILOGD("\'%{public}s\' was not found", devNode.c_str());
239     return nullptr;
240 }
241 
OnDeviceAdded(std::shared_ptr<IDevice> dev)242 void DeviceManager::OnDeviceAdded(std::shared_ptr<IDevice> dev)
243 {
244     CHKPV(dev);
245     FI_HILOGI("Add device %{public}d:%{private}s", dev->GetId(), dev->GetDevPath().c_str());
246     FI_HILOGI("  sysPath:       \"%{private}s\"", dev->GetSysPath().c_str());
247     FI_HILOGI("  bus:           %{public}04x", dev->GetBus());
248     FI_HILOGI("  vendor:        %{public}04x", dev->GetVendor());
249     FI_HILOGI("  product:       %{public}04x", dev->GetProduct());
250     FI_HILOGI("  version:       %{public}04x", dev->GetVersion());
251     FI_HILOGI("  name:          \"%{public}s\"", Utility::Anonymize(dev->GetName()).c_str());
252     FI_HILOGI("  location:      \"%{public}s\"", dev->GetPhys().c_str());
253     FI_HILOGI("  unique id:     \"%{public}s\"", dev->GetUniq().c_str());
254     FI_HILOGI("  is pointer:    %{private}s, is keyboard:%{public}s",
255         dev->IsPointerDevice() ? "True" : "False", dev->IsKeyboard() ? "True" : "False");
256 
257     for (const auto &observer : observers_) {
258         std::shared_ptr<IDeviceObserver> ptr = observer.lock();
259         CHKPC(ptr);
260         ptr->OnDeviceAdded(dev);
261     }
262 }
263 
OnDeviceRemoved(std::shared_ptr<IDevice> dev)264 void DeviceManager::OnDeviceRemoved(std::shared_ptr<IDevice> dev)
265 {
266     for (const auto &observer : observers_) {
267         std::shared_ptr<IDeviceObserver> ptr = observer.lock();
268         CHKPC(ptr);
269         ptr->OnDeviceRemoved(dev);
270     }
271 }
272 
Dispatch(const struct epoll_event & ev)273 void DeviceManager::Dispatch(const struct epoll_event &ev)
274 {
275     CALL_DEBUG_ENTER;
276     CHKPV(context_);
277     int32_t ret = context_->GetDelegateTasks().PostAsyncTask([this, &ev] {
278         return this->OnEpollDispatch(ev.events);
279     });
280     if (ret != RET_OK) {
281         FI_HILOGE("PostAsyncTask failed");
282     }
283 }
284 
OnEpollDispatch(uint32_t events)285 int32_t DeviceManager::OnEpollDispatch(uint32_t events)
286 {
287     struct epoll_event ev {};
288     ev.events = events;
289     ev.data.ptr = epollMgr_.get();
290 
291     CHKPR(epollMgr_, RET_ERR);
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 
HasKeyboard()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 
GetKeyboard()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