• 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 "monitor.h"
17 
18 #include <cstring>
19 #include <unistd.h>
20 
21 #include <string_view>
22 
23 #include <sys/epoll.h>
24 
25 #include "devicestatus_define.h"
26 #include "fi_log.h"
27 #include "napi_constants.h"
28 #include "utility.h"
29 
30 namespace OHOS {
31 namespace Msdp {
32 namespace DeviceStatus {
33 namespace {
34 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "Monitor" };
35 } // namespace
36 
~Monitor()37 Monitor::~Monitor()
38 {
39     Disable();
40 }
41 
Dispatch(const struct epoll_event & ev)42 void Monitor::Dispatch(const struct epoll_event &ev)
43 {
44     if ((ev.events & EPOLLIN) == EPOLLIN) {
45         ReceiveDevice();
46     } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
47         FI_HILOGE("Epoll hangup:%{public}s", strerror(errno));
48     }
49 }
50 
SetDeviceMgr(IDeviceMgr * devMgr)51 void Monitor::SetDeviceMgr(IDeviceMgr *devMgr)
52 {
53     CALL_DEBUG_ENTER;
54     CHKPV(devMgr);
55     devMgr_ = devMgr;
56 }
57 
Enable()58 int32_t Monitor::Enable()
59 {
60     CALL_INFO_TRACE;
61     int32_t ret = OpenConnection();
62     if (ret == RET_OK) {
63         ret = EnableReceiving();
64         if (ret != RET_OK) {
65             FI_HILOGE("Enable receive failed");
66             Disable();
67         }
68     }
69     return ret;
70 }
71 
Disable()72 void Monitor::Disable()
73 {
74     CALL_INFO_TRACE;
75     if (devWd_ >= 0) {
76         int32_t ret = inotify_rm_watch(inotifyFd_, devWd_);
77         if (ret != 0) {
78             FI_HILOGE("inotify_rm_watch failed");
79         }
80         devWd_ = -1;
81     }
82     if (inotifyFd_ >= 0) {
83         if (close(inotifyFd_) < 0) {
84             FI_HILOGE("Close inotify fd failed, error:%{public}s, inotifyFd_:%{public}d", strerror(errno), inotifyFd_);
85         }
86         inotifyFd_ = -1;
87     }
88 }
89 
OpenConnection()90 int32_t Monitor::OpenConnection()
91 {
92     CALL_DEBUG_ENTER;
93     inotifyFd_ = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
94     if (inotifyFd_ < 0) {
95         FI_HILOGE("Initializing inotify failed:%{public}s", strerror(errno));
96         return RET_ERR;
97     }
98     return RET_OK;
99 }
100 
EnableReceiving()101 int32_t Monitor::EnableReceiving()
102 {
103     CALL_DEBUG_ENTER;
104     devWd_ = inotify_add_watch(inotifyFd_, DEV_INPUT_PATH.c_str(), IN_CREATE | IN_DELETE);
105     if (devWd_ < 0) {
106         FI_HILOGE("Watching (\'%{public}s\') failed:%{public}s", DEV_INPUT_PATH.c_str(), strerror(errno));
107         return RET_ERR;
108     }
109     return RET_OK;
110 }
111 
ReceiveDevice()112 void Monitor::ReceiveDevice()
113 {
114     CALL_INFO_TRACE;
115     char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
116     size_t bufSize { sizeof(struct inotify_event) };
117     ssize_t numRead { 0 };
118 
119     do {
120         bufSize += sizeof(struct inotify_event);
121         numRead = ::read(inotifyFd_, buf, bufSize);
122     } while ((numRead < 0) && (errno == EINVAL) &&
123              (bufSize + sizeof(struct inotify_event) <= sizeof(buf)));
124 
125     if (numRead < 0) {
126         FI_HILOGE("Reading failed:%{public}s", strerror(errno));
127         return;
128     }
129     if (numRead == 0) {
130         FI_HILOGW("End of file encountered");
131         return;
132     }
133     FI_HILOGD("Read %{public}zd bytes from inotify events", numRead);
134     for (char *p = buf; p < buf + numRead;) {
135         struct inotify_event *event = reinterpret_cast<struct inotify_event *>(p);
136         HandleInotifyEvent(event);
137         p += sizeof(struct inotify_event) + event->len;
138     }
139 }
140 
HandleInotifyEvent(struct inotify_event * event) const141 void Monitor::HandleInotifyEvent(struct inotify_event *event) const
142 {
143     CALL_DEBUG_ENTER;
144     CHKPV(event);
145     if (Utility::IsEmpty(event->name)) {
146         return;
147     }
148     std::string devNode { event->name };
149 
150     if ((event->mask & IN_CREATE) == IN_CREATE) {
151         AddDevice(devNode);
152     } else if ((event->mask & IN_DELETE) == IN_DELETE) {
153         RemoveDevice(devNode);
154     }
155 }
156 
AddDevice(const std::string & devNode) const157 void Monitor::AddDevice(const std::string &devNode) const
158 {
159     CALL_DEBUG_ENTER;
160     CHKPV(devMgr_);
161     devMgr_->AddDevice(devNode);
162 }
163 
RemoveDevice(const std::string & devNode) const164 void Monitor::RemoveDevice(const std::string &devNode) const
165 {
166     CALL_DEBUG_ENTER;
167     CHKPV(devMgr_);
168     devMgr_->RemoveDevice(devNode);
169 }
170 } // namespace DeviceStatus
171 } // namespace Msdp
172 } // namespace OHOS