• 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 "devicestatus_msdp_mock.h"
17 
18 #include <cerrno>
19 #include <string>
20 #include <unistd.h>
21 
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
24 
25 #include "devicestatus_common.h"
26 #include "devicestatus_define.h"
27 #include "fi_log.h"
28 
29 namespace OHOS {
30 namespace Msdp {
31 namespace DeviceStatus {
32 namespace {
33 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceStatusMsdpMock" };
34 constexpr int32_t TIMER_INTERVAL { 3 };
35 constexpr int32_t ERR_INVALID_FD { -1 };
36 DeviceStatusMsdpMock* g_msdpMock { nullptr };
37 } // namespace
38 
DeviceStatusMsdpMock()39 DeviceStatusMsdpMock::DeviceStatusMsdpMock()
40 {
41     enabledType_ = {
42         TYPE_STILL,
43         TYPE_RELATIVE_STILL,
44         TYPE_CAR_BLUETOOTH
45     };
46     if (dataParse_ == nullptr) {
47         dataParse_ = std::make_unique<DeviceStatusDataParse>();
48     }
49 }
50 
~DeviceStatusMsdpMock()51 DeviceStatusMsdpMock::~DeviceStatusMsdpMock()
52 {
53     callbacks_.clear();
54     alive_ = false;
55     CloseTimer();
56     if (thread_.joinable()) {
57         thread_.join();
58         FI_HILOGI("thread_ is stop");
59     }
60 }
61 
Init()62 bool DeviceStatusMsdpMock::Init()
63 {
64     CALL_DEBUG_ENTER;
65     InitTimer();
66     StartThread();
67     return true;
68 }
69 
RegisterCallback(std::shared_ptr<MsdpAlgoCallback> callback)70 ErrCode DeviceStatusMsdpMock::RegisterCallback(std::shared_ptr<MsdpAlgoCallback> callback)
71 {
72     std::lock_guard lock(mutex_);
73     callback_ = callback;
74     return RET_OK;
75 }
76 
UnregisterCallback()77 ErrCode DeviceStatusMsdpMock::UnregisterCallback()
78 {
79     std::lock_guard lock(mutex_);
80     callback_ = nullptr;
81     return RET_OK;
82 }
83 
Enable(Type type)84 ErrCode DeviceStatusMsdpMock::Enable(Type type)
85 {
86     CALL_DEBUG_ENTER;
87     Init();
88     return RET_OK;
89 }
90 
Disable(Type type)91 ErrCode DeviceStatusMsdpMock::Disable(Type type)
92 {
93     CALL_DEBUG_ENTER;
94     alive_ = false;
95     CloseTimer();
96     if (thread_.joinable()) {
97         thread_.join();
98         FI_HILOGI("thread_ is stop");
99     }
100     return RET_OK;
101 }
102 
DisableCount(Type type)103 ErrCode DeviceStatusMsdpMock::DisableCount(Type type)
104 {
105     CALL_DEBUG_ENTER;
106     CHKPR(dataParse_, RET_ERR);
107     dataParse_->DisableCount(type);
108     return RET_OK;
109 }
110 
NotifyMsdpImpl(const Data & data)111 ErrCode DeviceStatusMsdpMock::NotifyMsdpImpl(const Data &data)
112 {
113     CALL_DEBUG_ENTER;
114     CHKPR(g_msdpMock, RET_ERR);
115     CHKPR(g_msdpMock->GetCallbackImpl(), RET_ERR);
116     FI_HILOGI("type:%{public}d, value:%{public}d", data.type, data.value);
117     g_msdpMock->GetCallbackImpl()->OnResult(data);
118     return RET_OK;
119 }
120 
InitTimer()121 void DeviceStatusMsdpMock::InitTimer()
122 {
123     CALL_DEBUG_ENTER;
124     epFd_ = epoll_create1(EPOLL_CLOEXEC);
125     if (epFd_ == -1) {
126         FI_HILOGE("Create epoll fd failed");
127         return;
128     }
129     timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
130     if (timerFd_ == ERR_INVALID_FD) {
131         FI_HILOGE("Create timer fd failed");
132         if (close(epFd_) < 0) {
133             FI_HILOGE("Close epoll fd failed, error:%{public}s, epFd_:%{public}d", strerror(errno), epFd_);
134         }
135         epFd_ = ERR_INVALID_FD;
136         return;
137     }
138     SetTimerInterval(TIMER_INTERVAL);
139     fcntl(timerFd_, F_SETFL, O_NONBLOCK);
140     auto [_, ret] = callbacks_.insert(std::make_pair(timerFd_, &DeviceStatusMsdpMock::TimerCallback));
141     if (!ret) {
142         FI_HILOGW("Insert timer fd failed");
143     }
144     if (RegisterTimerCallback(timerFd_, EVENT_TIMER_FD)) {
145         FI_HILOGE("Register timer fd failed");
146         return;
147     }
148 }
149 
SetTimerInterval(int32_t interval)150 int32_t DeviceStatusMsdpMock::SetTimerInterval(int32_t interval)
151 {
152     if (timerFd_ == ERR_INVALID_FD) {
153         FI_HILOGE("Create timer fd failed");
154         return RET_ERR;
155     }
156 
157     if (interval < 0) {
158         FI_HILOGE("Illegal time interval");
159         return RET_ERR;
160     }
161     struct itimerspec itval;
162     itval.it_interval.tv_sec = interval;
163     itval.it_interval.tv_nsec = 0;
164     itval.it_value.tv_sec = interval;
165     itval.it_value.tv_nsec = 0;
166     if (timerfd_settime(timerFd_, 0, &itval, nullptr) == -1) {
167         FI_HILOGE("Set timer failed");
168         return RET_ERR;
169     }
170     return RET_OK;
171 }
172 
CloseTimer()173 void DeviceStatusMsdpMock::CloseTimer()
174 {
175     if (timerFd_ < 0) {
176         FI_HILOGE("Invalid timerFd_");
177         return;
178     }
179     if (close(timerFd_) < 0) {
180         FI_HILOGE("Close timer fd failed, error:%{public}s, timerFd_:%{public}d", strerror(errno), timerFd_);
181     }
182     timerFd_ = -1;
183 }
184 
TimerCallback()185 void DeviceStatusMsdpMock::TimerCallback()
186 {
187     uint64_t timers {};
188     if (read(timerFd_, &timers, sizeof(timers)) == -1) {
189         FI_HILOGE("Read timer fd failed");
190         return;
191     }
192     GetDeviceStatusData();
193 }
194 
GetDeviceStatusData()195 int32_t DeviceStatusMsdpMock::GetDeviceStatusData()
196 {
197     for (const auto &item : enabledType_) {
198         Type type = item;
199         CHKPR(dataParse_, RET_ERR);
200         Data data;
201         dataParse_->ParseDeviceStatusData(type, data);
202         FI_HILOGD("Mock type:%{public}d, value:%{public}d", data.type, data.value);
203         NotifyMsdpImpl(data);
204     }
205     return RET_OK;
206 }
207 
RegisterTimerCallback(int32_t fd,const EventType et)208 int32_t DeviceStatusMsdpMock::RegisterTimerCallback(int32_t fd, const EventType et)
209 {
210     CALL_DEBUG_ENTER;
211     struct epoll_event ev;
212     ev.events = EPOLLIN;
213     if (et == EVENT_TIMER_FD) {
214         ev.events |= EPOLLWAKEUP;
215     }
216 
217     ev.data.ptr = reinterpret_cast<void*>(this);
218     ev.data.fd = fd;
219     if (epoll_ctl(epFd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
220         FI_HILOGE("epoll_ctl failed, errno:%{public}d", errno);
221         return RET_ERR;
222     }
223 
224     return RET_OK;
225 }
226 
StartThread()227 void DeviceStatusMsdpMock::StartThread()
228 {
229     CALL_DEBUG_ENTER;
230     if (!alive_) {
231         alive_ = true;
232         thread_ = std::thread(std::bind(&DeviceStatusMsdpMock::LoopingThreadEntry, this));
233     }
234 }
235 
LoopingThreadEntry()236 void DeviceStatusMsdpMock::LoopingThreadEntry()
237 {
238     SetThreadName("os_loop_mock");
239     if (callbacks_.empty()) {
240         FI_HILOGD("callbacks_ is empty");
241         return;
242     }
243     size_t cbct = callbacks_.size();
244     struct epoll_event events[cbct];
245     while (alive_) {
246         int32_t timeout = 200;
247         int32_t nevents = epoll_wait(epFd_, events, cbct, timeout);
248         if (nevents == -1) {
249             FI_HILOGE("No events available");
250             return;
251         }
252         for (int32_t n = 0; n < nevents; ++n) {
253             if (events[n].data.ptr) {
254                 DeviceStatusMsdpMock *func = const_cast<DeviceStatusMsdpMock *>(this);
255                 (callbacks_.find(events[n].data.fd)->second)(func);
256             }
257         }
258     }
259 }
260 
Create(void)261 extern "C" IMsdp *Create(void)
262 {
263     CALL_DEBUG_ENTER;
264     g_msdpMock = new (std::nothrow) DeviceStatusMsdpMock();
265     CHKPP(g_msdpMock);
266     return g_msdpMock;
267 }
268 
Destroy(const IMsdp * algorithm)269 extern "C" void Destroy(const IMsdp* algorithm)
270 {
271     CALL_INFO_TRACE;
272     if (algorithm != nullptr) {
273         FI_HILOGD("algorithm is not nullptr");
274         delete algorithm;
275     }
276 }
277 } // namespace DeviceStatus
278 } // namespace Msdp
279 } // namespace OHOS
280