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