1 /*
2 * Copyright (c) 2022 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_rdb.h"
17
18 #include <string>
19 #include <cerrno>
20 #include <sys/epoll.h>
21 #include <sys/timerfd.h>
22 #include <unistd.h>
23 #include <linux/netlink.h>
24
25 #include "devicestatus_common.h"
26
27 using namespace OHOS::NativeRdb;
28 namespace OHOS {
29 namespace Msdp {
30 namespace {
31 const std::string DATABASE_NAME = "/data/MsdpStub.db";
32 constexpr int32_t TIMER_INTERVAL = 3;
33 constexpr int32_t ERR_INVALID_FD = -1;
34 constexpr int32_t READ_RDB_WAIT_TIME = 30;
35 std::unique_ptr<DevicestatusMsdpRdb> g_msdpRdb = std::make_unique<DevicestatusMsdpRdb>();
36 constexpr int32_t ERR_NG = -1;
37 DevicestatusMsdpRdb* g_rdb;
38 }
39
Init()40 bool DevicestatusMsdpRdb::Init()
41 {
42 DEV_HILOGD(SERVICE, "DevicestatusMsdpRdbInit: Enter");
43 InitRdbStore();
44 InitTimer();
45 StartThread();
46 DEV_HILOGD(SERVICE, "DevicestatusMsdpRdbInit: Exit");
47 return true;
48 }
49
InitRdbStore()50 void DevicestatusMsdpRdb::InitRdbStore()
51 {}
52
RegisterCallback(const std::shared_ptr<MsdpAlgorithmCallback> & callback)53 void DevicestatusMsdpRdb::RegisterCallback(const std::shared_ptr<MsdpAlgorithmCallback>& callback)
54 {
55 callbacksImpl_ = callback;
56 }
57
UnregisterCallback()58 void DevicestatusMsdpRdb::UnregisterCallback()
59 {
60 callbacksImpl_ = nullptr;
61 }
62
Enable()63 void DevicestatusMsdpRdb::Enable()
64 {
65 DEV_HILOGD(SERVICE, "Enter");
66 Init();
67 DEV_HILOGD(SERVICE, "Exit");
68 }
69
Disable()70 void DevicestatusMsdpRdb::Disable()
71 {
72 DEV_HILOGD(SERVICE, "Enter");
73 CloseTimer();
74 DEV_HILOGD(SERVICE, "Exit");
75 }
76
NotifyMsdpImpl(const DevicestatusDataUtils::DevicestatusData & data)77 ErrCode DevicestatusMsdpRdb::NotifyMsdpImpl(const DevicestatusDataUtils::DevicestatusData& data)
78 {
79 DEV_HILOGD(SERVICE, "Enter");
80 if (g_rdb == nullptr) {
81 DEV_HILOGE(SERVICE, "g_rdb is nullptr");
82 return ERR_NG;
83 }
84 if (g_rdb->GetCallbacksImpl() == nullptr) {
85 DEV_HILOGD(SERVICE, "callbacksImpl is nullptr");
86 return ERR_NG;
87 }
88 g_rdb->GetCallbacksImpl()->OnResult(data);
89
90 return ERR_OK;
91 }
92
SaveRdbData(const DevicestatusDataUtils::DevicestatusData & data)93 DevicestatusDataUtils::DevicestatusData DevicestatusMsdpRdb::SaveRdbData(
94 const DevicestatusDataUtils::DevicestatusData& data)
95 {
96 for (auto iter = rdbDataMap_.begin(); iter != rdbDataMap_.end(); ++iter) {
97 if (iter->first == data.type) {
98 if (iter->second != data.value) {
99 notifyFlag_ = true;
100 iter->second = data.value;
101 }
102 DEV_HILOGD(SERVICE, "data is not changed");
103 return data;
104 }
105 }
106
107 rdbDataMap_.insert(std::make_pair(data.type, data.value));
108 notifyFlag_ = true;
109
110 DEV_HILOGD(SERVICE, "devicestatusType_ = %{public}d, devicestatusStatus_ = %{public}d",
111 devicestatusType_, devicestatusStatus_);
112
113 return data;
114 }
115
TrigerData(const std::unique_ptr<NativeRdb::ResultSet> & resultSet)116 int32_t DevicestatusMsdpRdb::TrigerData(const std::unique_ptr<NativeRdb::ResultSet> &resultSet)
117 {
118 int32_t columnIndex;
119 int32_t intVal;
120 if (resultSet == nullptr) {
121 DEV_HILOGE(SERVICE, "resultSet is nullptr");
122 return ERR_NG;
123 }
124 int32_t ret = resultSet->GetColumnIndex("ID", columnIndex);
125 DEV_HILOGD(SERVICE, "TrigerDatabaseObserver GetColumnIndex = %{public}d", columnIndex);
126 if (ret != ERR_OK) {
127 DEV_HILOGE(SERVICE, "CheckID: GetColumnIndex failed");
128 return -1;
129 }
130 ret = resultSet->GetInt(columnIndex, intVal);
131 DEV_HILOGD(SERVICE, "ret = %{public}d, id = %{public}d", ret, intVal);
132 if (ret != ERR_OK) {
133 DEV_HILOGE(SERVICE, "CheckID: GetValue failed");
134 return -1;
135 }
136
137 ret = resultSet->GetColumnIndex("DEVICESTATUS_TYPE", columnIndex);
138 DEV_HILOGD(SERVICE, "DEVICESTATUS_TYPE GetColumnIndex = %{public}d", columnIndex);
139 if (ret != ERR_OK) {
140 DEV_HILOGE(SERVICE, "CheckDevicestatusType: GetColumnIndex failed");
141 return -1;
142 }
143 ret = resultSet->GetInt(columnIndex, intVal);
144 DEV_HILOGD(SERVICE, "ret = %{public}d, DevicestatusType = %{public}d", ret, intVal);
145 devicestatusType_ = intVal;
146 if (ret != ERR_OK) {
147 DEV_HILOGE(SERVICE, "CheckDevicestatusType: GetValue failed");
148 return -1;
149 }
150
151 ret = resultSet->GetColumnIndex("DEVICESTATUS_STATUS", columnIndex);
152 DEV_HILOGD(SERVICE, "DEVICESTATUS_STATUS GetColumnIndex = %{public}d", columnIndex);
153 if (ret != ERR_OK) {
154 DEV_HILOGE(SERVICE, "CheckDevicestatusStatus: GetColumnIndex failed");
155 return -1;
156 }
157 ret = resultSet->GetInt(columnIndex, intVal);
158 DEV_HILOGD(SERVICE, "ret = %{public}d, DevicestatusStatus = %{public}d", ret, intVal);
159 devicestatusStatus_ = intVal;
160 if (ret != ERR_OK) {
161 DEV_HILOGE(SERVICE, "CheckDevicestatusStatus: GetValue failed");
162 return -1;
163 }
164
165 return ERR_OK;
166 }
167
TrigerDatabaseObserver()168 int32_t DevicestatusMsdpRdb::TrigerDatabaseObserver()
169 {
170 DEV_HILOGD(SERVICE, "Enter");
171
172 if (store_ == nullptr) {
173 sleep(READ_RDB_WAIT_TIME);
174 InitRdbStore();
175 return -1;
176 }
177
178 std::unique_ptr<ResultSet> resultSet =
179 store_->QuerySql("SELECT * FROM DEVICESTATUSSENSOR WHERE ID = (SELECT max(ID) from DEVICESTATUSSENSOR)");
180
181 if (resultSet == nullptr) {
182 DEV_HILOGE(SERVICE, "database is not exist");
183 return -1;
184 }
185
186 int32_t ret = resultSet->GoToFirstRow();
187 DEV_HILOGD(SERVICE, "GoToFirstRow = %{public}d", ret);
188 if (ret != ERR_OK) {
189 sleep(READ_RDB_WAIT_TIME);
190 DEV_HILOGE(SERVICE, "database observer is null");
191 return -1;
192 }
193
194 if (TrigerData(resultSet) != ERR_OK) {
195 DEV_HILOGE(SERVICE, "triger data failed");
196 return -1;
197 }
198
199 ret = resultSet->Close();
200 if (ret != ERR_OK) {
201 DEV_HILOGE(SERVICE, "close database observer failed");
202 return -1;
203 }
204
205 DevicestatusDataUtils::DevicestatusData data;
206 data.type = (DevicestatusDataUtils::DevicestatusType)devicestatusType_;
207 data.value = (DevicestatusDataUtils::DevicestatusValue)devicestatusStatus_;
208
209 SaveRdbData(data);
210 DEV_HILOGD(SERVICE, "notifyFlag_ is %{public}d", notifyFlag_);
211 if (notifyFlag_) {
212 NotifyMsdpImpl(data);
213 notifyFlag_ = false;
214 }
215
216 return ERR_OK;
217 }
218
InitTimer()219 void DevicestatusMsdpRdb::InitTimer()
220 {
221 DEV_HILOGD(SERVICE, "Enter");
222 epFd_ = epoll_create1(EPOLL_CLOEXEC);
223 if (epFd_ == -1) {
224 DEV_HILOGD(SERVICE, "create epoll fd failed");
225 return;
226 }
227 timerFd_ = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
228 if (timerFd_ == ERR_INVALID_FD) {
229 DEV_HILOGD(SERVICE, "create timer fd failed");
230 return;
231 }
232 SetTimerInterval(TIMER_INTERVAL);
233 fcntl(timerFd_, F_SETFL, O_NONBLOCK);
234 callbacks_.insert(std::make_pair(timerFd_, &DevicestatusMsdpRdb::TimerCallback));
235 if (RegisterTimerCallback(timerFd_, EVENT_TIMER_FD)) {
236 DEV_HILOGD(SERVICE, "register timer fd failed");
237 return;
238 }
239 }
240
SetTimerInterval(int32_t interval)241 void DevicestatusMsdpRdb::SetTimerInterval(int32_t interval)
242 {
243 struct itimerspec itval;
244
245 if (timerFd_ == ERR_INVALID_FD) {
246 DEV_HILOGD(SERVICE, "create timer fd failed");
247 return;
248 }
249
250 timerInterval_ = interval;
251
252 if (interval < 0) {
253 interval = 0;
254 }
255
256 itval.it_interval.tv_sec = interval;
257 itval.it_interval.tv_nsec = 0;
258 itval.it_value.tv_sec = interval;
259 itval.it_value.tv_nsec = 0;
260
261 if (timerfd_settime(timerFd_, 0, &itval, nullptr) == -1) {
262 DEV_HILOGD(SERVICE, "set timer failed");
263 return;
264 }
265
266 return;
267 }
268
CloseTimer()269 void DevicestatusMsdpRdb::CloseTimer()
270 {
271 DEV_HILOGD(SERVICE, "Enter");
272 close(timerFd_);
273 DEV_HILOGD(SERVICE, "Exit");
274 }
275
TimerCallback()276 void DevicestatusMsdpRdb::TimerCallback()
277 {
278 unsigned long long timers;
279 if (read(timerFd_, &timers, sizeof(timers)) == -1) {
280 DEV_HILOGD(SERVICE, "read timer fd failed");
281 return;
282 }
283 TrigerDatabaseObserver();
284 }
285
RegisterTimerCallback(const int32_t fd,const EventType et)286 int32_t DevicestatusMsdpRdb::RegisterTimerCallback(const int32_t fd, const EventType et)
287 {
288 DEV_HILOGD(SERVICE, "Enter");
289 struct epoll_event ev;
290
291 ev.events = EPOLLIN;
292 if (et == EVENT_TIMER_FD) {
293 ev.events |= EPOLLWAKEUP;
294 }
295
296 ev.data.ptr = reinterpret_cast<void*>(this);
297 ev.data.fd = fd;
298 if (epoll_ctl(epFd_, EPOLL_CTL_ADD, fd, &ev) == -1) {
299 DEV_HILOGD(SERVICE, "epoll_ctl failed, error num =%{public}d", errno);
300 return -1;
301 }
302
303 return 0;
304 }
305
StartThread()306 void DevicestatusMsdpRdb::StartThread()
307 {
308 DEV_HILOGD(SERVICE, "Enter");
309 std::make_unique<std::thread>(&DevicestatusMsdpRdb::LoopingThreadEntry, this)->detach();
310 }
311
LoopingThreadEntry()312 void DevicestatusMsdpRdb::LoopingThreadEntry()
313 {
314 size_t cbct = callbacks_.size();
315 struct epoll_event events[cbct];
316
317 while (true) {
318 int32_t timeout = -1;
319
320 int32_t nevents = epoll_wait(epFd_, events, cbct, timeout);
321 if (nevents == -1) {
322 continue;
323 }
324 for (int32_t n = 0; n < nevents; ++n) {
325 if (events[n].data.ptr) {
326 DevicestatusMsdpRdb *func = const_cast<DevicestatusMsdpRdb *>(this);
327 (callbacks_.find(events[n].data.fd)->second)(func);
328 }
329 }
330 }
331 }
332
OnCreate(RdbStore & store)333 int32_t InsertOpenCallback::OnCreate(RdbStore &store)
334 {
335 DEV_HILOGD(SERVICE, "Enter");
336 return ERR_OK;
337 }
338
OnUpgrade(RdbStore & store,int32_t oldVersion,int32_t newVersion)339 int32_t InsertOpenCallback::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion)
340 {
341 DEV_HILOGD(SERVICE, "Enter");
342 return ERR_OK;
343 }
344
Create(void)345 extern "C" DevicestatusMsdpInterface *Create(void)
346 {
347 DEV_HILOGD(SERVICE, "Enter");
348 g_rdb = new DevicestatusMsdpRdb();
349 return g_rdb;
350 }
351
Destroy(DevicestatusMsdpInterface * algorithm)352 extern "C" void Destroy(DevicestatusMsdpInterface* algorithm)
353 {
354 DEV_HILOGD(SERVICE, "Enter");
355 delete algorithm;
356 }
357 }
358 }
359