• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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