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
34 #undef LOG_TAG
35 #define LOG_TAG "DeviceManager"
36
37 namespace OHOS {
38 namespace Msdp {
39 namespace DeviceStatus {
40 namespace {
41 constexpr size_t EXPECTED_N_SUBMATCHES { 2 };
42 constexpr size_t EXPECTED_SUBMATCH { 1 };
43 const std::string FINGER_PRINT { "hw_fingerprint_mouse" };
44 } // namespace
45
HotplugHandler(DeviceManager & devMgr)46 DeviceManager::HotplugHandler::HotplugHandler(DeviceManager &devMgr)
47 : devMgr_(devMgr)
48 {}
49
AddDevice(const std::string & devNode)50 void DeviceManager::HotplugHandler::AddDevice(const std::string &devNode)
51 {
52 devMgr_.AddDevice(devNode);
53 }
54
RemoveDevice(const std::string & devNode)55 void DeviceManager::HotplugHandler::RemoveDevice(const std::string &devNode)
56 {
57 devMgr_.RemoveDevice(devNode);
58 }
59
DeviceManager()60 DeviceManager::DeviceManager()
61 : hotplug_(*this)
62 {}
63
Init(IContext * context)64 int32_t DeviceManager::Init(IContext *context)
65 {
66 CALL_INFO_TRACE;
67 CHKPR(context, RET_ERR);
68 int32_t ret = context->GetDelegateTasks().PostSyncTask([this, context] {
69 return this->OnInit(context);
70 });
71 if (ret != RET_OK) {
72 FI_HILOGE("Post sync task failed");
73 }
74 return ret;
75 }
76
OnInit(IContext * context)77 int32_t DeviceManager::OnInit(IContext *context)
78 {
79 CALL_INFO_TRACE;
80 CHKPR(context, RET_ERR);
81 context_ = context;
82 monitor_.SetDeviceMgr(&hotplug_);
83 enumerator_.SetDeviceMgr(&hotplug_);
84 return RET_OK;
85 }
86
Enable()87 int32_t DeviceManager::Enable()
88 {
89 CALL_INFO_TRACE;
90 CHKPR(context_, RET_ERR);
91 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this] {
92 return this->OnEnable();
93 });
94 if (ret != RET_OK) {
95 FI_HILOGE("Post sync task failed");
96 }
97 return ret;
98 }
99
OnEnable()100 int32_t DeviceManager::OnEnable()
101 {
102 CALL_DEBUG_ENTER;
103 epollMgr_ = std::make_shared<EpollManager>();
104 int32_t ret = epollMgr_->Open();
105 if (ret != RET_OK) {
106 return ret;
107 }
108 ret = monitor_.Enable();
109 if (ret != RET_OK) {
110 goto CLOSE_EPOLL;
111 }
112 ret = epollMgr_->Add(monitor_);
113 if (ret != RET_OK) {
114 goto DISABLE_MONITOR;
115 }
116 enumerator_.ScanDevices();
117 return RET_OK;
118
119 DISABLE_MONITOR:
120 monitor_.Disable();
121
122 CLOSE_EPOLL:
123 epollMgr_.reset();
124 return ret;
125 }
126
Disable()127 int32_t DeviceManager::Disable()
128 {
129 CALL_INFO_TRACE;
130 CHKPR(context_, RET_ERR);
131 int32_t ret = context_->GetDelegateTasks().PostSyncTask([this] {
132 return this->OnDisable();
133 });
134 if (ret != RET_OK) {
135 FI_HILOGE("PostSyncTask failed");
136 }
137 return ret;
138 }
139
OnDisable()140 int32_t DeviceManager::OnDisable()
141 {
142 CHKPR(epollMgr_, RET_ERR);
143 epollMgr_->Remove(monitor_);
144 monitor_.Disable();
145 epollMgr_.reset();
146 return RET_OK;
147 }
148
FindDevice(const std::string & devPath)149 std::shared_ptr<IDevice> DeviceManager::FindDevice(const std::string &devPath)
150 {
151 auto tIter = std::find_if(devices_.cbegin(), devices_.cend(),
152 [devPath](const auto &item) {
153 return ((item.second != nullptr) && (item.second->GetDevPath() == devPath));
154 });
155 return (tIter != devices_.cend() ? tIter->second : nullptr);
156 }
157
ParseDeviceId(const std::string & devNode)158 int32_t DeviceManager::ParseDeviceId(const std::string &devNode)
159 {
160 CALL_DEBUG_ENTER;
161 std::regex pattern("^event(\\d+)$");
162 std::smatch mr;
163
164 if (std::regex_match(devNode, mr, pattern)) {
165 if (mr.ready() && mr.size() == EXPECTED_N_SUBMATCHES) {
166 return std::stoi(mr[EXPECTED_SUBMATCH].str());
167 }
168 }
169 return RET_ERR;
170 }
171
AddDevice(const std::string & devNode)172 std::shared_ptr<IDevice> DeviceManager::AddDevice(const std::string &devNode)
173 {
174 CALL_INFO_TRACE;
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:%{public}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\"", 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: %{public}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