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/UserPlacesTypes.h"
21 #include "../utils/DebugUtils.h"
22 #include "WifiLogger.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 DatabaseManager dbManager;
40 bool ret = dbManager.createTable(0, WIFI_TABLE, __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 std::stringstream query;
49 const char* separator = " ";
50 query << "BEGIN TRANSACTION; \
51 INSERT INTO " WIFI_TABLE " \
52 ( " WIFI_COLUMN_BSSID ", " WIFI_COLUMN_ESSID ", " WIFI_COLUMN_TIMESTAMP " ) \
54 for (MacEvent mac_event : __logs) {
55 query << separator << "( '" << mac_event.mac << "', '" << mac_event.networkName << "', '" << mac_event.timestamp << "' )";
61 DatabaseManager dbManager;
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) :
73 __intervalMinutes(WIFI_LOGGER_INTERVAL_MINUTES_HIGH_ACCURACY),
75 __lastScanTime(time_t(0)),
76 __lasTimerCallbackTime(time_t(0)),
78 __connectedToWifiAp(false),
84 __setInterval(energyMode);
86 if (WIFI_LOGGER_DATABASE)
89 __logs = std::vector<MacEvent>();
91 __wifiSetDeviceStateChangedCbRequest();
93 if (WIFI_LOGGER_LOW_POWER_MODE)
94 __wifiSetConnectionStateChangedCbRequest();
96 wifi_connection_state_e state = __wifiGetConnectionStateRequest();
97 __connectedToWifiAp = (state == WIFI_CONNECTION_STATE_CONNECTED);
98 _D("__connectedToWifiAp = %d, __duringVisit = %d IN CONSTRUCTOR",
99 static_cast<int>(__connectedToWifiAp),
100 static_cast<int>(__duringVisit));
103 ctx::WifiLogger::~WifiLogger()
109 void ctx::WifiLogger::__wifiDeviceStateChangedCb(wifi_device_state_e state, void *userData)
111 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
113 case WIFI_DEVICE_STATE_DEACTIVATED:
114 _D("WIFI setting OFF");
115 if (wifiLogger->__started)
116 wifiLogger->__stopLogging();
118 case WIFI_DEVICE_STATE_ACTIVATED:
119 _D("WIFI setting ON");
120 if (wifiLogger->__started)
121 wifiLogger->__startLogging();
128 void ctx::WifiLogger::__wifiConnectionStateChangedCb(wifi_connection_state_e state, wifi_ap_h ap, void *userData)
130 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
132 case WIFI_CONNECTION_STATE_CONNECTED:
133 _D("connected to AP");
134 wifiLogger->__connectedToWifiAp = true;
137 _D("disconnected from AP -> __lastScansPool.clear()");
138 wifiLogger->__connectedToWifiAp = false;
139 wifiLogger->__lastScansPool.clear();
142 // TODO: Check if AP bssid (MAC Address) will be helpful somehow in LOW_POWER mode
145 bool ctx::WifiLogger::__wifiFoundApCb(wifi_ap_h ap, void *userData)
147 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
150 int ret = wifiLogger->__wifiApGetBssidRequest(ap, &bssid);
151 if (ret != WIFI_ERROR_NONE)
155 ret = wifiLogger->__wifiApGetEssidRequest(ap, &essid);
156 if (ret != WIFI_ERROR_NONE)
162 } catch (std::runtime_error &e) {
163 _E("Cannot create mac_event. Exception: %s", e.what());
167 MacEvent log(wifiLogger->__lastScanTime, mac, std::string(essid));
168 if (wifiLogger->__listener) {
169 wifiLogger->__listener->onWifiScan(log);
170 if (WIFI_LOGGER_LOW_POWER_MODE
171 && (wifiLogger->__connectedToWifiAp || wifiLogger->__duringVisit) ) {
172 // Add to last scans AP's set
173 wifiLogger->__lastScansPool.insert(std::pair<std::string, std::string>(std::string(bssid), std::string(essid)));
176 if (WIFI_LOGGER_DATABASE)
177 wifiLogger->__logs.push_back(log);
182 const char* ctx::WifiLogger::__wifiError2Str(int error)
185 case WIFI_ERROR_INVALID_PARAMETER:
186 return "WIFI_ERROR_INVALID_PARAMETER";
187 case WIFI_ERROR_OUT_OF_MEMORY:
188 return "WIFI_ERROR_OUT_OF_MEMORY";
189 case WIFI_ERROR_INVALID_OPERATION:
190 return "WIFI_ERROR_INVALID_OPERATION";
191 case WIFI_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
192 return "WIFI_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED";
193 case WIFI_ERROR_OPERATION_FAILED:
194 return "WIFI_ERROR_OPERATION_FAILED";
195 case WIFI_ERROR_NO_CONNECTION:
196 return "WIFI_ERROR_NO_CONNECTION";
197 case WIFI_ERROR_NOW_IN_PROGRESS:
198 return "WIFI_ERROR_NOW_IN_PROGRESS";
199 case WIFI_ERROR_ALREADY_EXISTS:
200 return "WIFI_ERROR_ALREADY_EXISTS";
201 case WIFI_ERROR_OPERATION_ABORTED:
202 return "WIFI_ERROR_OPERATION_ABORTED";
203 case WIFI_ERROR_DHCP_FAILED:
204 return "WIFI_ERROR_DHCP_FAILED";
205 case WIFI_ERROR_INVALID_KEY:
206 return "WIFI_ERROR_INVALID_KEY";
207 case WIFI_ERROR_NO_REPLY:
208 return "WIFI_ERROR_NO_REPLY";
209 case WIFI_ERROR_SECURITY_RESTRICTED:
210 return "WIFI_ERROR_SECURITY_RESTRICTED";
211 case WIFI_ERROR_PERMISSION_DENIED:
212 return "WIFI_ERROR_PERMISSION_DENIED";
214 return "unknown wifi error code";
218 void ctx::WifiLogger::__wifiScanFinishedCb(wifi_error_e errorCode, void *userData)
220 ctx::WifiLogger* wifiLogger = (ctx::WifiLogger *)userData;
222 time_t now = time(nullptr);
223 #ifdef TIZEN_ENGINEER_MODE
225 if (wifiLogger->__lastScanTime > 0) {
226 seconds = difftime(now, wifiLogger->__lastScanTime);
228 std::string timeStr = DebugUtils::humanReadableDateTime(now, "%T", 9);
229 _D("__connectedToWifiAp = %d, __duringVisit = %d, __lastScansPool.size() = %d -> scan %s (from last : %.1fs)",
230 static_cast<int>(wifiLogger->__connectedToWifiAp),
231 static_cast<int>(wifiLogger->__duringVisit),
232 wifiLogger->__lastScansPool.size(),
235 #endif /* TIZEN_ENGINEER_MODE */
236 wifiLogger->__lastScanTime = now;
238 int ret = wifiLogger->__wifiForeachFoundApsRequest(userData);
239 if (ret != WIFI_ERROR_NONE)
241 if (WIFI_LOGGER_DATABASE)
242 wifiLogger->__dbInsertLogs();
245 bool ctx::WifiLogger::__checkWifiIsActivated()
247 bool wifiActivated = true;
248 int ret = __wifiWrapper.isActivated(&wifiActivated);
249 __WIFI_ERROR_LOG(ret);
250 _D("Wi-Fi is %s", wifiActivated ? "ON" : "OFF");
251 return wifiActivated;
254 void ctx::WifiLogger::__wifiScanRequest()
256 int ret = __wifiWrapper.scan(__wifiScanFinishedCb, this);
257 __WIFI_ERROR_LOG(ret);
260 int ctx::WifiLogger::__wifiForeachFoundApsRequest(void *userData)
262 int ret = __wifiWrapper.foreachFoundAP(__wifiFoundApCb, userData);
263 __WIFI_ERROR_LOG(ret);
267 wifi_connection_state_e ctx::WifiLogger::__wifiGetConnectionStateRequest()
269 wifi_connection_state_e connectionState;
270 int ret = __wifiWrapper.getConnectionState(&connectionState);
271 __WIFI_ERROR_LOG(ret);
272 return connectionState;
275 void ctx::WifiLogger::__wifiSetBackgroundScanCbRequest()
277 int ret = __wifiWrapper.setBackgroundScanCb(__wifiScanFinishedCb, this);
278 __WIFI_ERROR_LOG(ret);
281 void ctx::WifiLogger::__wifiSetDeviceStateChangedCbRequest()
283 int ret = __wifiWrapper.setDeviceStateChangedCb(__wifiDeviceStateChangedCb, this);
284 __WIFI_ERROR_LOG(ret);
287 void ctx::WifiLogger::__wifiSetConnectionStateChangedCbRequest()
289 int ret = __wifiWrapper.setConnectionStateChangedCb(__wifiConnectionStateChangedCb, this);
290 __WIFI_ERROR_LOG(ret);
293 int ctx::WifiLogger::__wifiApGetEssidRequest(wifi_ap_h ap, char **essid)
295 int ret = __wifiWrapper.getEssidFromAP(ap, essid);
296 __WIFI_ERROR_LOG(ret);
300 int ctx::WifiLogger::__wifiApGetBssidRequest(wifi_ap_h ap, char **bssid)
302 int ret = __wifiWrapper.getBssidFromAP(ap, bssid);
303 __WIFI_ERROR_LOG(ret);
307 bool ctx::WifiLogger::__checkTimerId(int id)
309 _D("id == %d, __timerId == %d", id, __timerId);
310 return id == __timerId;
314 * Accepted time from last callback is >= than minimum interval
316 bool ctx::WifiLogger::__checkTimerTime(time_t now)
319 if (__lasTimerCallbackTime > 0) {
320 seconds = difftime(now, __lasTimerCallbackTime);
321 if (seconds < WIFI_LOGGER_ACTIVE_SCANNING_MIN_INTERVAL) {
322 _D("last == %d, now == %d, diff = %.1fs -> Incorrect timer callback", __lasTimerCallbackTime, now, seconds);
325 _D("last == %d, now == %d, diff = %.1fs -> Correct timer callback", __lasTimerCallbackTime, now, seconds);
328 _D("last == %d, now == %d -> First callback", __lasTimerCallbackTime, now);
330 __lasTimerCallbackTime = now;
334 bool ctx::WifiLogger::onTimerExpired(int id)
336 time_t now = time(nullptr);
338 if (__checkTimerId(id) == false) // Incorrect callback call
340 if (__checkTimerTime(now) == false) // Prevention from double callback call bug
342 _D("__connectedToWifiAp = %d, __duringVisit = %d, __lastScansPool.size() = %d",
343 static_cast<int>(__connectedToWifiAp),
344 static_cast<int>(__duringVisit),
345 __lastScansPool.size());
346 if (WIFI_LOGGER_LOW_POWER_MODE
348 && __connectedToWifiAp
349 && __lastScansPool.size() > 0) {
350 _D("trying to send fake scan");
352 _D("__listener != false -> CORRECT");
353 for (std::pair<std::string, std::string> ap : __lastScansPool) {
355 MacEvent scan(now, mac, ap.second);
356 _D("send fake scan (%s, %s)", ap.first.c_str(), ap.second.c_str());
357 __listener->onWifiScan(scan);
366 void ctx::WifiLogger::startLogging()
373 void ctx::WifiLogger::__startLogging()
376 if (!__checkWifiIsActivated() || __running)
380 if (WIFI_LOGGER_ACTIVE_SCANNING) {
381 __timerStart(__intervalMinutes);
384 if (WIFI_LOGGER_PASSIVE_SCANNING)
385 __wifiSetBackgroundScanCbRequest();
388 void ctx::WifiLogger::stopLogging()
395 void ctx::WifiLogger::__stopLogging()
400 if (WIFI_LOGGER_ACTIVE_SCANNING) {
404 __timerManager.remove(__timerId);
406 if (WIFI_LOGGER_PASSIVE_SCANNING)
407 __wifiWrapper.unsetBackgroundScanCb();
411 void ctx::WifiLogger::__timerStart(time_t minutes)
414 __timerId = __timerManager.setFor(minutes, this);
415 _D("%s (minutes=%d)", __timerId >= 0 ? "SUCCESS" : "ERROR", minutes);
418 void ctx::WifiLogger::onVisitStart()
421 __duringVisit = true;
424 void ctx::WifiLogger::onVisitEnd()
426 _D("__lastScansPool.clear()");
427 __duringVisit = false;
428 __lastScansPool.clear();
431 void ctx::WifiLogger::__setInterval(PlaceRecogMode energyMode)
433 switch (energyMode) {
434 case PLACE_RECOG_LOW_POWER_MODE:
435 __intervalMinutes = WIFI_LOGGER_INTERVAL_MINUTES_LOW_POWER;
437 case PLACE_RECOG_HIGH_ACCURACY_MODE:
438 __intervalMinutes = WIFI_LOGGER_INTERVAL_MINUTES_HIGH_ACCURACY;
441 _E("Incorrect energy mode");
445 void ctx::WifiLogger::__timerRestart()
447 __timerManager.remove(__timerId);
448 __timerStart(__intervalMinutes);
451 void ctx::WifiLogger::setMode(PlaceRecogMode energyMode)
454 __setInterval(energyMode);
455 if (WIFI_LOGGER_ACTIVE_SCANNING && __timerOn)