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