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