2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <DatabaseManager.h>
20 #include "../facade/user_places_types.h"
21 #include "../utils/debug_utils.h"
22 #include "wifi_logger.h"
24 #define __WIFI_CREATE_TABLE_COLUMNS \
25 WIFI_COLUMN_TIMESTAMP " timestamp NOT NULL, "\
26 WIFI_COLUMN_BSSID " TEXT NOT NULL, "\
27 WIFI_COLUMN_ESSID " TEXT NOT NULL"
29 #define __WIFI_ERROR_LOG(error) { \
30 if (error != WIFI_ERROR_NONE) { \
31 _E("ERROR == %s", __wifiError2Str(error)); \
37 int ctx::WifiLogger::__dbCreateTable()
39 ctx::DatabaseManager dbManager;
40 bool ret = dbManager.createTable(0, WIFI_TABLE_NAME, __WIFI_CREATE_TABLE_COLUMNS, NULL, NULL);
41 _D("Table Creation Request: %s", ret ? "SUCCESS" : "FAIL");
45 int ctx::WifiLogger::__dbInsertLogs()
47 if (__logs.size() > 0) {
48 ctx::DatabaseManager dbManager;
49 std::stringstream query;
50 const char* separator = " ";
51 query << "BEGIN TRANSACTION; \
52 INSERT INTO " WIFI_TABLE_NAME " \
53 ( " WIFI_COLUMN_BSSID ", " WIFI_COLUMN_ESSID ", " WIFI_COLUMN_TIMESTAMP " ) \
55 for (MacEvent mac_event : __logs) {
56 query << separator << "( '" << mac_event.mac << "', '" << mac_event.networkName << "', '" << mac_event.timestamp << "' )";
62 bool ret = dbManager.execute(0, query.str().c_str(), NULL);
63 _D("DB insert request: %s", ret ? "SUCCESS" : "FAIL");
66 _D("__logs vector empty -> nothing to insert");
70 ctx::WifiLogger::WifiLogger(IWifiListener * listener, PlaceRecogMode energyMode) :
72 __intervalMinutes(WIFI_LOGGER_INTERVAL_MINUTES_HIGH_ACCURACY),
74 __lastScanTime(time_t(0)),
75 __lasTimerCallbackTime(time_t(0)),
77 __connectedToWifiAp(false),
83 __setInterval(energyMode);
85 if (WIFI_LOGGER_DATABASE)
88 __logs = std::vector<MacEvent>();
90 __wifiSetDeviceStateChangedCbRequest();
92 if (WIFI_LOGGER_LOW_POWER_MODE)
93 __wifiSetConnectionStateChangedCbRequest();
95 wifi_connection_state_e state = __wifiGetConnectionStateRequest();
96 __connectedToWifiAp = (state == WIFI_CONNECTION_STATE_CONNECTED);
97 _D("__connectedToWifiAp = %d, __duringVisit = %d IN CONSTRUCTOR",
98 static_cast<int>(__connectedToWifiAp),
99 static_cast<int>(__duringVisit));
102 ctx::WifiLogger::~WifiLogger()
108 void ctx::WifiLogger::__wifiDeviceStateChangedCb(wifi_device_state_e state, void *userData)
110 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
112 case WIFI_DEVICE_STATE_DEACTIVATED:
113 _D("WIFI setting OFF");
114 if (wifiLogger->__started)
115 wifiLogger->__stopLogging();
117 case WIFI_DEVICE_STATE_ACTIVATED:
118 _D("WIFI setting ON");
119 if (wifiLogger->__started)
120 wifiLogger->__startLogging();
127 void ctx::WifiLogger::__wifiConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, void *userData)
129 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
131 case WIFI_CONNECTION_STATE_CONNECTED:
132 _D("connected to AP");
133 wifiLogger->__connectedToWifiAp = true;
136 _D("disconnected from AP -> __lastScansPool.clear()");
137 wifiLogger->__connectedToWifiAp = false;
138 wifiLogger->__lastScansPool.clear();
141 // TODO: Check if AP bssid (MAC Address) will be helpful somehow in LOW_POWER mode
144 bool ctx::WifiLogger::__wifiFoundApCb(wifi_ap_h ap, void *userData)
146 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
149 int ret = wifiLogger->__wifiApGetBssidRequest(ap, &bssid);
150 if (ret != WIFI_ERROR_NONE)
154 ret = wifiLogger->__wifiApGetEssidRequest(ap, &essid);
155 if (ret != WIFI_ERROR_NONE)
161 } catch (std::runtime_error &e) {
162 _E("Cannot create mac_event. Exception: %s", e.what());
166 MacEvent log(wifiLogger->__lastScanTime, mac, std::string(essid));
167 if (wifiLogger->__listener) {
168 wifiLogger->__listener->onWifiScan(log);
169 if (WIFI_LOGGER_LOW_POWER_MODE
170 && (wifiLogger->__connectedToWifiAp || wifiLogger->__duringVisit) ) {
171 // Add to last scans AP's set
172 wifiLogger->__lastScansPool.insert(std::pair<std::string, std::string>(std::string(bssid), std::string(essid)));
175 if (WIFI_LOGGER_DATABASE)
176 wifiLogger->__logs.push_back(log);
181 const char* ctx::WifiLogger::__wifiError2Str(int error)
184 case WIFI_ERROR_INVALID_PARAMETER:
185 return "WIFI_ERROR_INVALID_PARAMETER";
186 case WIFI_ERROR_OUT_OF_MEMORY:
187 return "WIFI_ERROR_OUT_OF_MEMORY";
188 case WIFI_ERROR_INVALID_OPERATION:
189 return "WIFI_ERROR_INVALID_OPERATION";
190 case WIFI_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
191 return "WIFI_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED";
192 case WIFI_ERROR_OPERATION_FAILED:
193 return "WIFI_ERROR_OPERATION_FAILED";
194 case WIFI_ERROR_NO_CONNECTION:
195 return "WIFI_ERROR_NO_CONNECTION";
196 case WIFI_ERROR_NOW_IN_PROGRESS:
197 return "WIFI_ERROR_NOW_IN_PROGRESS";
198 case WIFI_ERROR_ALREADY_EXISTS:
199 return "WIFI_ERROR_ALREADY_EXISTS";
200 case WIFI_ERROR_OPERATION_ABORTED:
201 return "WIFI_ERROR_OPERATION_ABORTED";
202 case WIFI_ERROR_DHCP_FAILED:
203 return "WIFI_ERROR_DHCP_FAILED";
204 case WIFI_ERROR_INVALID_KEY:
205 return "WIFI_ERROR_INVALID_KEY";
206 case WIFI_ERROR_NO_REPLY:
207 return "WIFI_ERROR_NO_REPLY";
208 case WIFI_ERROR_SECURITY_RESTRICTED:
209 return "WIFI_ERROR_SECURITY_RESTRICTED";
210 case WIFI_ERROR_PERMISSION_DENIED:
211 return "WIFI_ERROR_PERMISSION_DENIED";
213 return "unknown wifi error code";
217 void ctx::WifiLogger::__wifiScanFinishedCb(wifi_error_e errorCode, void *userData)
219 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
221 time_t now = time(nullptr);
222 #ifdef TIZEN_ENGINEER_MODE
224 if (wifiLogger->__lastScanTime > 0) {
225 seconds = difftime(now, wifiLogger->__lastScanTime);
227 std::string timeStr = DebugUtils::humanReadableDateTime(now, "%T", 9);
228 _D("__connectedToWifiAp = %d, __duringVisit = %d, __lastScansPool.size() = %d -> scan %s (from last : %.1fs)",
229 static_cast<int>(wifiLogger->__connectedToWifiAp),
230 static_cast<int>(wifiLogger->__duringVisit),
231 wifiLogger->__lastScansPool.size(),
234 #endif /* TIZEN_ENGINEER_MODE */
235 wifiLogger->__lastScanTime = now;
237 int ret = wifiLogger->__wifiForeachFoundApsRequest(userData);
238 if (ret != WIFI_ERROR_NONE)
240 if (WIFI_LOGGER_DATABASE)
241 wifiLogger->__dbInsertLogs();
244 bool ctx::WifiLogger::__checkWifiIsActivated()
246 bool wifiActivated = true;
247 int ret = __wifiWrapper.isActivated(&wifiActivated);
248 __WIFI_ERROR_LOG(ret);
249 _D("Wi-Fi is %s", wifiActivated ? "ON" : "OFF");
250 return wifiActivated;
253 void ctx::WifiLogger::__wifiScanRequest()
255 int ret = __wifiWrapper.scan(__wifiScanFinishedCb, this);
256 __WIFI_ERROR_LOG(ret);
259 int ctx::WifiLogger::__wifiForeachFoundApsRequest(void *userData)
261 int ret = __wifiWrapper.foreachFoundAP(__wifiFoundApCb, userData);
262 __WIFI_ERROR_LOG(ret);
266 wifi_connection_state_e ctx::WifiLogger::__wifiGetConnectionStateRequest()
268 wifi_connection_state_e connectionState;
269 int ret = __wifiWrapper.getConnectionState(&connectionState);
270 __WIFI_ERROR_LOG(ret);
271 return connectionState;
274 void ctx::WifiLogger::__wifiSetBackgroundScanCbRequest()
276 int ret = __wifiWrapper.setBackgroundScanCb(__wifiScanFinishedCb, this);
277 __WIFI_ERROR_LOG(ret);
280 void ctx::WifiLogger::__wifiSetDeviceStateChangedCbRequest()
282 int ret = __wifiWrapper.setDeviceStateChangedCb(__wifiDeviceStateChangedCb, this);
283 __WIFI_ERROR_LOG(ret);
286 void ctx::WifiLogger::__wifiSetConnectionStateChangedCbRequest()
288 int ret = __wifiWrapper.setConnectionStateChangedCb(__wifiConnectionStateChangedCb, this);
289 __WIFI_ERROR_LOG(ret);
292 int ctx::WifiLogger::__wifiApGetEssidRequest(wifi_ap_h ap, char **essid)
294 int ret = __wifiWrapper.getEssidFromAP(ap, essid);
295 __WIFI_ERROR_LOG(ret);
299 int ctx::WifiLogger::__wifiApGetBssidRequest(wifi_ap_h ap, char **bssid)
301 int ret = __wifiWrapper.getBssidFromAP(ap, bssid);
302 __WIFI_ERROR_LOG(ret);
306 bool ctx::WifiLogger::__checkTimerId(int id)
308 _D("id == %d, __timerId == %d", id, __timerId);
309 return id == __timerId;
313 * Accepted time from last callback is >= than minimum interval
315 bool ctx::WifiLogger::__checkTimerTime(time_t now)
318 if (__lasTimerCallbackTime > 0) {
319 seconds = difftime(now, __lasTimerCallbackTime);
320 if (seconds < WIFI_LOGGER_ACTIVE_SCANNING_MIN_INTERVAL) {
321 _D("last == %d, now == %d, diff = %.1fs -> Incorrect timer callback", __lasTimerCallbackTime, now, seconds);
324 _D("last == %d, now == %d, diff = %.1fs -> Correct timer callback", __lasTimerCallbackTime, now, seconds);
327 _D("last == %d, now == %d -> First callback", __lasTimerCallbackTime, now);
329 __lasTimerCallbackTime = now;
333 bool ctx::WifiLogger::onTimerExpired(int id)
335 time_t now = time(nullptr);
337 if (__checkTimerId(id) == false) // Incorrect callback call
339 if (__checkTimerTime(now) == false) // Prevention from double callback call bug
341 _D("__connectedToWifiAp = %d, __duringVisit = %d, __lastScansPool.size() = %d",
342 static_cast<int>(__connectedToWifiAp),
343 static_cast<int>(__duringVisit),
344 __lastScansPool.size());
345 if (WIFI_LOGGER_LOW_POWER_MODE
347 && __connectedToWifiAp
348 && __lastScansPool.size() > 0) {
349 _D("trying to send fake scan");
351 _D("__listener != false -> CORRECT");
352 for (std::pair<std::string, std::string> ap : __lastScansPool) {
354 MacEvent scan(now, mac, ap.second);
355 _D("send fake scan (%s, %s)", ap.first.c_str(), ap.second.c_str());
356 __listener->onWifiScan(scan);
365 void ctx::WifiLogger::startLogging()
372 void ctx::WifiLogger::__startLogging()
375 if (!__checkWifiIsActivated() || __running)
379 if (WIFI_LOGGER_ACTIVE_SCANNING) {
380 __timerStart(__intervalMinutes);
383 if (WIFI_LOGGER_PASSIVE_SCANNING)
384 __wifiSetBackgroundScanCbRequest();
387 void ctx::WifiLogger::stopLogging()
394 void ctx::WifiLogger::__stopLogging()
399 if (WIFI_LOGGER_ACTIVE_SCANNING) {
403 __timerManager.remove(__timerId);
405 if (WIFI_LOGGER_PASSIVE_SCANNING)
406 __wifiWrapper.unsetBackgroundScanCb();
410 void ctx::WifiLogger::__timerStart(time_t minutes)
413 __timerId = __timerManager.setFor(minutes, this);
414 _D("%s (minutes=%d)", __timerId >= 0 ? "SUCCESS" : "ERROR", minutes);
417 void ctx::WifiLogger::onVisitStart()
420 __duringVisit = true;
423 void ctx::WifiLogger::onVisitEnd()
425 _D("__lastScansPool.clear()");
426 __duringVisit = false;
427 __lastScansPool.clear();
430 void ctx::WifiLogger::__setInterval(PlaceRecogMode energyMode)
432 switch (energyMode) {
433 case PLACE_RECOG_LOW_POWER_MODE:
434 __intervalMinutes = WIFI_LOGGER_INTERVAL_MINUTES_LOW_POWER;
436 case PLACE_RECOG_HIGH_ACCURACY_MODE:
437 __intervalMinutes = WIFI_LOGGER_INTERVAL_MINUTES_HIGH_ACCURACY;
440 _E("Incorrect energy mode");
444 void ctx::WifiLogger::__timerRestart()
446 __timerManager.remove(__timerId);
447 __timerStart(__intervalMinutes);
450 void ctx::WifiLogger::setMode(PlaceRecogMode energyMode)
453 __setInterval(energyMode);
454 if (WIFI_LOGGER_ACTIVE_SCANNING && __timerOn)