• 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 <linux/netlink.h>
23 #include <sys/epoll.h>
24 #include <sys/timerfd.h>
25 
26 #include "devicestatus_common.h"
27 
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace {
32 constexpr int32_t TIMER_INTERVAL = 3;
33 constexpr int32_t ERR_INVALID_FD = -1;
34 constexpr int32_t ERR_NG = -1;
35 constexpr int32_t TIMER_MS = 1000;
36 DeviceStatusMsdpMock* g_msdpMock = nullptr;
37 } // namespace
38 
39 std::vector<int32_t> DeviceStatusMsdpMock::enabledType_ =
40     std::vector<int32_t> (static_cast<int32_t>(DevicestatusDataUtils::DevicestatusType::TYPE_MAX),
41     static_cast<int32_t>(DevicestatusDataUtils::Value::INVALID));
42 
Init()43 bool DeviceStatusMsdpMock::Init()
44 {
45     DEV_HILOGD(SERVICE, "DeviceStatusMsdpMock: Enter");
46     if (dataParse_ == nullptr) {
47         dataParse_ = std::make_unique<DeviceStatusDataParse>();
48     }
49     InitMockStore();
50     InitTimer();
51     StartThread();
52     DEV_HILOGD(SERVICE, "DeviceStatusMsdpMock: Exit");
53     return true;
54 }
55 
InitMockStore()56 void DeviceStatusMsdpMock::InitMockStore() {}
57 
RegisterCallback(std::shared_ptr<MsdpAlgorithmCallback> callback)58 ErrCode DeviceStatusMsdpMock::RegisterCallback(std::shared_ptr<MsdpAlgorithmCallback> callback)
59 {
60     std::lock_guard lock(mutex_);
61     callback_ = callback;
62     return RET_OK;
63 }
64 
UnregisterCallback()65 ErrCode DeviceStatusMsdpMock::UnregisterCallback()
66 {
67     std::lock_guard lock(mutex_);
68     callback_ = nullptr;
69     return RET_OK;
70 }
71 
Enable(DevicestatusDataUtils::DevicestatusType type)72 ErrCode DeviceStatusMsdpMock::Enable(DevicestatusDataUtils::DevicestatusType type)
73 {
74     DEV_HILOGD(SERVICE, "Enter");
75     if (type < DevicestatusDataUtils::DevicestatusType::TYPE_STILL ||
76         type >= DevicestatusDataUtils::DevicestatusType::TYPE_LID_OPEN) {
77         DEV_HILOGE(SERVICE, "Type error");
78     }
79     enabledType_[type] = static_cast<int32_t>(DevicestatusDataUtils::Value::VALID);
80     Init();
81     DEV_HILOGD(SERVICE, "Exit");
82     return RET_OK;
83 }
84 
Disable(DevicestatusDataUtils::DevicestatusType type)85 ErrCode DeviceStatusMsdpMock::Disable(DevicestatusDataUtils::DevicestatusType type)
86 {
87     DEV_HILOGD(SERVICE, "Enter");
88     scFlag_ = false;
89     CloseTimer();
90     DEV_HILOGD(SERVICE, "Exit");
91     return RET_OK;
92 }
93 
DisableCount(DevicestatusDataUtils::DevicestatusType type)94 ErrCode DeviceStatusMsdpMock::DisableCount(DevicestatusDataUtils::DevicestatusType type)
95 {
96     DEV_HILOGD(SERVICE, "Enter");
97     enabledType_[type] = static_cast<int32_t>(DevicestatusDataUtils::Value::INVALID);
98     dataParse_->DisableCount(type);
99     DEV_HILOGD(SERVICE, "Exit");
100     return RET_OK;
101 }
102 
NotifyMsdpImpl(const DevicestatusDataUtils::DevicestatusData & data)103 ErrCode DeviceStatusMsdpMock::NotifyMsdpImpl(const DevicestatusDataUtils::DevicestatusData& data)
104 {
105     DEV_HILOGD(SERVICE, "Enter");
106     if (g_msdpMock == nullptr) {
107         DEV_HILOGE(SERVICE, "g_msdpMock is nullptr");
108         return ERR_NG;
109     }
110     if (g_msdpMock->GetCallbackImpl() == nullptr) {
111         DEV_HILOGE(SERVICE, "callbacksImpl is nullptr");
112         return ERR_NG;
113     }
114     g_msdpMock->GetCallbackImpl()->OnResult(data);
115 
116     return ERR_OK;
117 }
118 
InitTimer()119 void DeviceStatusMsdpMock::InitTimer()
120 {
121     DEV_HILOGD(SERVICE, "Enter");
122     epFd_ = epoll_create1(EPOLL_CLOEXEC);
123     if (epFd_ == -1) {
124         DEV_HILOGE(SERVICE, "create epoll fd failed");
125         return;
126     }
127     timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
128     if (timerFd_ == ERR_INVALID_FD) {
129         DEV_HILOGE(SERVICE, "create timer fd failed");
130         close(epFd_);
131         epFd_ = ERR_INVALID_FD;
132         return;
133     }
134     SetTimerInterval(TIMER_INTERVAL);
135     fcntl(timerFd_, F_SETFL, O_NONBLOCK);
136     callbacks_.insert(std::make_pair(timerFd_, &DeviceStatusMsdpMock::TimerCallback));
137     if (RegisterTimerCallback(timerFd_, EVENT_TIMER_FD)) {
138         DEV_HILOGE(SERVICE, "register timer fd failed");
139         return;
140     }
141 }
142 
SetTimerInterval(int32_t interval)143 void DeviceStatusMsdpMock::SetTimerInterval(int32_t interval)
144 {
145     if (timerFd_ == ERR_INVALID_FD) {
146         DEV_HILOGE(SERVICE, "create timer fd failed");
147         return;
148     }
149     if (interval != 0) {
150         timerInterval_ = interval;
151     }
152     if (interval < 0) {
153         interval = 0;
154     }
155     struct itimerspec itval;
156     itval.it_interval.tv_sec = interval;
157     itval.it_interval.tv_nsec = 0;
158     itval.it_value.tv_sec = interval;
159     itval.it_value.tv_nsec = 0;
160     if (timerfd_settime(timerFd_, 0, &itval, nullptr) == -1) {
161         DEV_HILOGE(SERVICE, "set timer failed");
162         return;
163     }
164 }
165 
CloseTimer()166 void DeviceStatusMsdpMock::CloseTimer()
167 {
168     DEV_HILOGD(SERVICE, "Enter");
169     close(timerFd_);
170     DEV_HILOGD(SERVICE, "Exit");
171 }
172 
TimerCallback()173 void DeviceStatusMsdpMock::TimerCallback()
174 {
175     uint64_t timers;
176     if (read(timerFd_, &timers, sizeof(timers)) == -1) {
177         DEV_HILOGE(SERVICE, "read timer fd failed");
178         return;
179     }
180     GetDeviceStatusData();
181 }
182 
GetDeviceStatusData()183 void DeviceStatusMsdpMock::GetDeviceStatusData()
184 {
185     DevicestatusDataUtils::DevicestatusData data;
186     for (int32_t i = int(DevicestatusDataUtils::DevicestatusType::TYPE_STILL);
187         i <= DevicestatusDataUtils::DevicestatusType::TYPE_LID_OPEN; ++i) {
188         if (enabledType_[i] == static_cast<int32_t>(DevicestatusDataUtils::Value::VALID)) {
189             DevicestatusDataUtils::DevicestatusType type = DevicestatusDataUtils::DevicestatusType(i);
190             DEV_HILOGE(SERVICE, "type:%{public}d", type);
191             if (dataParse_ == nullptr) {
192                 DEV_HILOGE(SERVICE, "dataParse_ is nullptr");
193                 return;
194             }
195             dataParse_->ParseDeviceStatusData(data, type);
196             NotifyMsdpImpl(data);
197         }
198     }
199 }
200 
RegisterTimerCallback(const int32_t fd,const EventType et)201 int32_t DeviceStatusMsdpMock::RegisterTimerCallback(const int32_t fd, const EventType et)
202 {
203     DEV_HILOGD(SERVICE, "Enter");
204     struct epoll_event ev;
205     ev.events = EPOLLIN;
206     if (et == EVENT_TIMER_FD) {
207         ev.events |= EPOLLWAKEUP;
208     }
209 
210     ev.data.ptr = reinterpret_cast<void*>(this);
211     ev.data.fd = fd;
212     if (epoll_ctl(epFd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
213         DEV_HILOGE(SERVICE, "epoll_ctl failed, error num:%{public}d", errno);
214         return ERR_NG;
215     }
216 
217     return ERR_OK;
218 }
219 
StartThread()220 void DeviceStatusMsdpMock::StartThread()
221 {
222     DEV_HILOGD(SERVICE, "Enter");
223     std::make_unique<std::thread>(&DeviceStatusMsdpMock::LoopingThreadEntry, this)->detach();
224 }
225 
LoopingThreadEntry()226 void DeviceStatusMsdpMock::LoopingThreadEntry()
227 {
228     if (callbacks_.empty()) {
229         DEV_HILOGD(SERVICE, "callbacks_ is empty");
230         return;
231     }
232     size_t cbct = callbacks_.size();
233     struct epoll_event events[cbct];
234     while (alive_) {
235         int32_t nevents = epoll_wait(epFd_, events, cbct, TIMER_INTERVAL * TIMER_MS);
236         if (nevents == -1 || nevents == 0) {
237             continue;
238         }
239         for (int32_t n = 0; n < nevents; ++n) {
240             if (events[n].data.ptr) {
241                 DeviceStatusMsdpMock *func = const_cast<DeviceStatusMsdpMock *>(this);
242                 (callbacks_.find(events[n].data.fd)->second)(func);
243             }
244         }
245     }
246 }
247 
Create(void)248 extern "C" DevicestatusMsdpInterface *Create(void)
249 {
250     DEV_HILOGD(SERVICE, "Enter");
251     g_msdpMock = new DeviceStatusMsdpMock();
252     return g_msdpMock;
253 }
254 
Destroy(const DevicestatusMsdpInterface * algorithm)255 extern "C" void Destroy(const DevicestatusMsdpInterface* algorithm)
256 {
257     DEV_HILOGD(SERVICE, "Enter");
258     delete algorithm;
259 }
260 } // namespace DeviceStatus
261 } // namespace Msdp
262 } // namespace OHOS
263