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.
20 #include <DatabaseManager.h>
21 #include <UserPlacesTypes.h>
22 #include <UserPlacesParams.h>
23 #include <DebugUtils.h>
24 #include "LocationLogger.h"
27 #define __LOCATION_CREATE_TABLE_COLUMNS \
28 LOCATION_COLUMN_LATITUDE " REAL NOT NULL, "\
29 LOCATION_COLUMN_LONGITUDE " REAL NOT NULL, "\
30 LOCATION_COLUMN_ACCURACY " REAL, "\
31 LOCATION_COLUMN_TIMESTAMP " timestamp NOT NULL, "\
32 LOCATION_COLUMN_TIMESTAMP_HUMAN " TEXT, "\
33 LOCATION_COLUMN_METHOD " INTEGER "
34 #else /* DEBUG_MODE */
35 #define __LOCATION_CREATE_TABLE_COLUMNS \
36 LOCATION_COLUMN_LATITUDE " REAL NOT NULL, "\
37 LOCATION_COLUMN_LONGITUDE " REAL NOT NULL, "\
38 LOCATION_COLUMN_ACCURACY " REAL, "\
39 LOCATION_COLUMN_TIMESTAMP " timestamp NOT NULL "
40 #endif /* DEBUG_MODE */
42 #define __LOCATION_ERROR_LOG(error) { \
43 if (error != LOCATIONS_ERROR_NONE) { \
44 _E("ERROR == %s", __locationError2Str(error)); \
50 void ctx::LocationLogger::__locationServiceStateChangedCb(location_service_state_e state, void *userData)
52 ctx::LocationLogger* locationLogger = (ctx::LocationLogger *)userData;
53 locationLogger->__locationServiceState = state;
54 if (state == LOCATIONS_SERVICE_ENABLED) {
55 _D("LOCATIONS_SERVICE_ENABLED");
56 switch (locationLogger->__timerPurpose) {
57 case LOCATION_LOGGER_WAITING_FOR_SERVICE_START:
58 _D("Waiting for location service start FINISHED");
59 locationLogger->__timerStop();
60 locationLogger->__locationRequest();
62 case LOCATION_LOGGER_WAITING_FOR_ACTIVE_REQUEST:
63 case LOCATION_LOGGER_WAITING_FOR_LOCATION_METHOD_SETTING_ON:
64 case LOCATION_LOGGER_WAITING_FOR_ACTIVE_INTERVAL:
65 case LOCATION_LOGGER_WAITING_FOR_PASSIVE_INTERVAL:
71 _D("LOCATIONS_SERVICE_DISABLED");
72 // locationLogger->__timerStop();
76 void ctx::LocationLogger::__locationSettingChangedCb(location_method_e method, bool enable, void *userData)
78 ctx::LocationLogger* locationLogger = (ctx::LocationLogger *)userData;
79 locationLogger->__locationMethodState = enable;
80 if (method == locationLogger->__locationMethod) {
82 _D("Location method settings ON");
83 switch (locationLogger->__timerPurpose) {
84 case LOCATION_LOGGER_WAITING_FOR_LOCATION_METHOD_SETTING_ON:
85 _D("Waiting for location method settings on FINISHED");
86 if (locationLogger->__locationServiceState == LOCATIONS_SERVICE_ENABLED) {
87 locationLogger->__timerStop();
88 locationLogger->__locationRequest();
90 locationLogger->__locationManagerStart();
93 case LOCATION_LOGGER_WAITING_FOR_SERVICE_START:
94 case LOCATION_LOGGER_WAITING_FOR_ACTIVE_REQUEST:
95 case LOCATION_LOGGER_WAITING_FOR_ACTIVE_INTERVAL:
96 case LOCATION_LOGGER_WAITING_FOR_PASSIVE_INTERVAL:
102 _D("Location method settings OFF");
103 // locationLogger->__timerStop();
108 void ctx::LocationLogger::__positionUpdatedCb(double latitude, double longitude,
109 double altitude, time_t timestamp, void *userData)
112 ctx::LocationLogger* locationLogger = (ctx::LocationLogger *)userData;
113 double horizontal = locationLogger->__locationManagerGetHorizontalAccuracy();
115 ctx::LocationEvent location(latitude, longitude, horizontal, timestamp, LOCATION_METHOD_REQUEST);
116 #else /* DEBUG_MODE */
117 ctx::LocationEvent location(latitude, longitude, horizontal, timestamp);
118 #endif /* DEBUG_MODE */
119 locationLogger->__broadcast(location);
120 locationLogger->__onActiveRequestSucceeded();
123 void ctx::LocationLogger::__locationUpdatedCb(location_error_e error, double latitude, double longitude,
124 double altitude, time_t timestamp, double speed, double direction, double climb, void *userData)
127 __positionUpdatedCb(latitude, longitude, altitude, timestamp, userData);
130 const char* ctx::LocationLogger::__locationError2Str(int error)
133 case LOCATIONS_ERROR_NONE:
134 return "LOCATIONS_ERROR_NONE";
135 case LOCATIONS_ERROR_OUT_OF_MEMORY:
136 return "LOCATIONS_ERROR_OUT_OF_MEMORY";
137 case LOCATIONS_ERROR_INVALID_PARAMETER:
138 return "LOCATIONS_ERROR_INVALID_PARAMETER";
139 case LOCATIONS_ERROR_ACCESSIBILITY_NOT_ALLOWED:
140 return "LOCATIONS_ERROR_ACCESSIBILITY_NOT_ALLOWED";
141 case LOCATIONS_ERROR_NOT_SUPPORTED:
142 return "LOCATIONS_ERROR_NOT_SUPPORTED";
143 case LOCATIONS_ERROR_INCORRECT_METHOD:
144 return "LOCATIONS_ERROR_INCORRECT_METHOD";
145 case LOCATIONS_ERROR_NETWORK_FAILED:
146 return "LOCATIONS_ERROR_NETWORK_FAILED";
147 case LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE:
148 return "LOCATIONS_ERROR_SERVICE_NOT_AVAILABLE";
149 case LOCATIONS_ERROR_GPS_SETTING_OFF:
150 return "LOCATIONS_ERROR_GPS_SETTING_OFF";
151 case LOCATIONS_ERROR_SECURITY_RESTRICTED:
152 return "LOCATIONS_ERROR_SECURITY_RESTRICTED";
154 return "unknown location error code";
159 void ctx::LocationLogger::__log(location_accessibility_state_e state)
162 case LOCATIONS_ACCESS_STATE_NONE : // Access state is not determined
163 _D("LOCATIONS_ACCESS_STATE_NONE ");
165 case LOCATIONS_ACCESS_STATE_DENIED: // Access denied
166 _D("LOCATIONS_ACCESS_STATE_DENIED");
168 case LOCATIONS_ACCESS_STATE_ALLOWED: // Access authorized
169 _D("LOCATIONS_ACCESS_STATE_ALLOWED");
176 int ctx::LocationLogger::__dbCreateTable()
178 DatabaseManager dbManager;
179 bool ret = dbManager.createTableSync(LOCATION_TABLE, __LOCATION_CREATE_TABLE_COLUMNS);
180 _D("%s -> Table Creation Request", ret ? "SUCCESS" : "FAIL");
184 int ctx::LocationLogger::__dbInsertLog(LocationEvent locationEvent)
187 data.set(NULL, LOCATION_COLUMN_LATITUDE, locationEvent.coordinates.latitude);
188 data.set(NULL, LOCATION_COLUMN_LONGITUDE, locationEvent.coordinates.longitude);
189 data.set(NULL, LOCATION_COLUMN_ACCURACY, locationEvent.coordinates.accuracy);
190 data.set(NULL, LOCATION_COLUMN_TIMESTAMP, static_cast<int>(locationEvent.timestamp));
192 std::string timeHuman = DebugUtils::humanReadableDateTime(locationEvent.timestamp, "%F %T", 80);
193 data.set(NULL, LOCATION_COLUMN_TIMESTAMP_HUMAN, timeHuman);
194 data.set(NULL, LOCATION_COLUMN_METHOD, static_cast<int>(locationEvent.method));
195 #endif /* DEBUG_MODE */
197 DatabaseManager dbManager;
199 bool ret = dbManager.insertSync(LOCATION_TABLE, data, &rowId);
200 _D("%s -> DB: location table insert result", ret ? "SUCCESS" : "FAIL");
204 ctx::LocationLogger::LocationLogger(ILocationListener *listener) :
205 __listener(listener),
206 __activeRequestAttempts(0),
210 __activeRequestSucceeded(false),
211 __activeLocationSucceeded(false),
214 __timerPurpose(LOCATION_LOGGER_WAITING_FOR_PASSIVE_INTERVAL),
215 __locationServiceState(LOCATIONS_SERVICE_DISABLED),
216 __locationMethod(LOCATION_LOGGER_METHOD),
217 __locationMethodState(false)
221 __locationManagerCreate();
223 if (LOCATION_LOGGER_DATABASE)
226 __locationManagerSetServiceStateChangedCb();
227 __locationManagerSetSettingChangedCb();
228 __locationMethodState = __locationManagerIsEnabledMethod(__locationMethod);
231 ctx::LocationLogger::~LocationLogger()
235 __locationManagerUnsetServiceStateChangedCb();
236 __locationManagerUnsetSettingChangedCb();
237 __locationManagerDestroy();
240 void ctx::LocationLogger::__locationManagerCreate()
242 int ret = location_manager_create(__locationMethod, &__locationManager);
243 __LOCATION_ERROR_LOG(ret);
246 void ctx::LocationLogger::__locationManagerDestroy()
248 int ret = location_manager_destroy(__locationManager);
249 __LOCATION_ERROR_LOG(ret);
252 void ctx::LocationLogger::__locationManagerSetServiceStateChangedCb()
254 int ret = location_manager_set_service_state_changed_cb(__locationManager, __locationServiceStateChangedCb, this);
255 __LOCATION_ERROR_LOG(ret);
258 void ctx::LocationLogger::__locationManagerUnsetServiceStateChangedCb()
260 int ret = location_manager_unset_service_state_changed_cb(__locationManager);
261 __LOCATION_ERROR_LOG(ret);
264 void ctx::LocationLogger::__locationManagerStart()
266 int ret = location_manager_start(__locationManager);
267 __LOCATION_ERROR_LOG(ret);
268 __startServiceTimerStart();
271 void ctx::LocationLogger::__locationManagerStop()
273 int ret = location_manager_stop(__locationManager);
274 __LOCATION_ERROR_LOG(ret);
277 double ctx::LocationLogger::__locationManagerGetHorizontalAccuracy()
279 location_accuracy_level_e accuracyLevel;
280 double horizontal, vertical;
281 int ret = location_manager_get_accuracy(__locationManager, &accuracyLevel, &horizontal, &vertical);
282 __LOCATION_ERROR_LOG(ret);
286 location_accessibility_state_e ctx::LocationLogger::__locationManagerGetAccessibilityState()
288 location_accessibility_state_e state;
289 int ret = location_manager_get_accessibility_state(&state);
290 __LOCATION_ERROR_LOG(ret);
294 void ctx::LocationLogger::__locationManagerSetSettingChangedCb()
296 int ret = location_manager_set_setting_changed_cb(__locationMethod, __locationSettingChangedCb, this);
297 __LOCATION_ERROR_LOG(ret);
300 void ctx::LocationLogger::__locationManagerUnsetSettingChangedCb()
302 int ret = location_manager_unset_setting_changed_cb(__locationMethod);
303 __LOCATION_ERROR_LOG(ret);
306 bool ctx::LocationLogger::__locationManagerRequestSingleLocation()
308 int ret = location_manager_request_single_location(__locationManager,
309 LOCATION_LOGGER_ACTIVE_REQUEST_TIMEOUT_SECONDS, __locationUpdatedCb, this);
310 _D("%s (seconds=%d) ----- ATTEMPTS: REQ[%d/%d], ACT[%d/%d], ALL[%d/%d]; ----- LOCATIONS:[%d/%d]",
311 ret == LOCATIONS_ERROR_NONE ? "SUCCESS" : "ERROR",
312 LOCATION_LOGGER_ACTIVE_REQUEST_TIMEOUT_SECONDS,
313 __activeRequestAttempts,
314 LOCATION_LOGGER_MAX_ACTIVE_REQUEST_ATTEMPTS,
316 LOCATION_LOGGER_MAX_ACTIVE_LOCATION_ATTEMPTS,
318 LOCATION_LOGGER_MAX_LOCATION_ATTEMPTS,
320 LOCATION_LOGGER_MAX_LOCATION_COUNT);
321 __LOCATION_ERROR_LOG(ret);
322 __activeRequestAttempts++;
325 if (ret == LOCATIONS_ERROR_NONE) {
326 __activeRequestTimerStart();
333 bool ctx::LocationLogger::__locationManagerGetLocation()
335 double altitude, latitude, longitude, climb, direction, speed, horizontal, vertical;
336 location_accuracy_level_e level;
338 int ret = location_manager_get_location(__locationManager, &altitude, &latitude, &longitude,
339 &climb, &direction, &speed, &level, &horizontal, &vertical, ×tamp);
340 _D("%s ----- ATTEMPTS: REQ[%d/%d], ACT[%d/%d], ALL[%d/%d]; ----- LOCATIONS:[%d/%d]",
341 ret == LOCATIONS_ERROR_NONE ? "SUCCESS" : "ERROR",
342 __activeRequestAttempts,
343 LOCATION_LOGGER_MAX_ACTIVE_REQUEST_ATTEMPTS,
345 LOCATION_LOGGER_MAX_ACTIVE_LOCATION_ATTEMPTS,
347 LOCATION_LOGGER_MAX_LOCATION_ATTEMPTS,
349 LOCATION_LOGGER_MAX_LOCATION_COUNT);
350 __LOCATION_ERROR_LOG(ret);
353 if (ret == LOCATIONS_ERROR_NONE) {
355 ctx::LocationEvent location(latitude, longitude, horizontal, timestamp, LOCATION_METHOD_GET_LOCATION);
356 #else /* DEBUG_MODE */
357 ctx::LocationEvent location(latitude, longitude, horizontal, timestamp);
358 #endif /* DEBUG_MODE */
359 __broadcast(location);
360 __onActiveLocationSucceeded();
367 void ctx::LocationLogger::__locationManagerGetLastLocation()
369 double altitude, latitude, longitude, climb, direction, speed, horizontal, vertical;
370 location_accuracy_level_e level;
372 int ret = location_manager_get_last_location(__locationManager, &altitude, &latitude, &longitude,
373 &climb, &direction, &speed, &level, &horizontal, &vertical, ×tamp);
374 _D("%s ----- ATTEMPTS: REQ[%d/%d], ACT[%d/%d], ALL[%d/%d]; ----- LOCATIONS:[%d/%d]",
375 ret == LOCATIONS_ERROR_NONE ? "SUCCESS" : "ERROR",
376 __activeRequestAttempts,
377 LOCATION_LOGGER_MAX_ACTIVE_REQUEST_ATTEMPTS,
379 LOCATION_LOGGER_MAX_ACTIVE_LOCATION_ATTEMPTS,
381 LOCATION_LOGGER_MAX_LOCATION_ATTEMPTS,
383 LOCATION_LOGGER_MAX_LOCATION_COUNT);
384 __LOCATION_ERROR_LOG(ret);
386 if (ret == LOCATIONS_ERROR_NONE) {
388 ctx::LocationEvent location(latitude, longitude, horizontal, timestamp, LOCATION_METHOD_GET_LAST_LOCATION);
389 #else /* DEBUG_MODE */
390 ctx::LocationEvent location(latitude, longitude, horizontal, timestamp);
391 #endif /* DEBUG_MODE */
392 __broadcast(location);
396 bool ctx::LocationLogger::__locationManagerIsEnabledMethod(location_method_e method)
399 int ret = location_manager_is_enabled_method(method, &enable);
400 __LOCATION_ERROR_LOG(ret);
404 bool ctx::LocationLogger::__checkGeneralLimits()
406 return (__locationCount < LOCATION_LOGGER_MAX_LOCATION_COUNT
407 && __allAttempts < LOCATION_LOGGER_MAX_LOCATION_ATTEMPTS);
410 bool ctx::LocationLogger::__checkActiveLimits()
412 return (!__activeLocationSucceeded
413 && __activeAttempts < LOCATION_LOGGER_MAX_ACTIVE_LOCATION_ATTEMPTS);
416 bool ctx::LocationLogger::__checkActiveRequestLimits()
418 return (!__activeRequestSucceeded
419 && __activeRequestAttempts < LOCATION_LOGGER_MAX_ACTIVE_REQUEST_ATTEMPTS);
422 void ctx::LocationLogger::__locationRequest()
425 bool requestSingleLocationRet = false;
426 bool getLocationRet = false;
427 if (__checkGeneralLimits() && __checkActiveLimits() && __checkActiveRequestLimits()) {
428 requestSingleLocationRet = __locationManagerRequestSingleLocation();
430 if (__checkGeneralLimits() && __checkActiveLimits() && !requestSingleLocationRet) {
431 getLocationRet = __locationManagerGetLocation();
433 if (__checkGeneralLimits() && !requestSingleLocationRet && !getLocationRet
434 && __activeAttempts >= LOCATION_LOGGER_MAX_ACTIVE_LOCATION_ATTEMPTS) {
435 __locationManagerGetLastLocation();
437 if (!requestSingleLocationRet) {
438 __locationManagerStop();
443 void ctx::LocationLogger::__setNextTimer()
445 _D("ATTEMPTS: REQ[%d/%d], ACT[%d/%d], ALL[%d/%d]; ----- LOCATIONS:[%d/%d])",
446 __activeRequestAttempts,
447 LOCATION_LOGGER_MAX_ACTIVE_REQUEST_ATTEMPTS,
449 LOCATION_LOGGER_MAX_ACTIVE_LOCATION_ATTEMPTS,
451 LOCATION_LOGGER_MAX_LOCATION_ATTEMPTS,
453 LOCATION_LOGGER_MAX_LOCATION_COUNT);
454 if (__checkGeneralLimits()) {
455 if (__checkActiveLimits()) {
456 __activeIntervalTimerStart();
458 __passiveIntervalTimerStart();
463 void ctx::LocationLogger::__onActiveRequestSucceeded()
466 __locationManagerStop();
467 __activeRequestSucceeded = true;
468 __onActiveLocationSucceeded();
471 void ctx::LocationLogger::__onActiveLocationSucceeded()
474 __activeLocationSucceeded = true;
477 void ctx::LocationLogger::__broadcast(ctx::LocationEvent locationEvent)
482 __listener->onNewLocation(locationEvent);
483 if (LOCATION_LOGGER_DATABASE)
484 __dbInsertLog(locationEvent);
487 bool ctx::LocationLogger::onTimerExpired(int id)
489 time_t now = time(nullptr);
490 double seconds = difftime(now, __timerTimestamp);
492 switch (__timerPurpose) {
493 case LOCATION_LOGGER_WAITING_FOR_ACTIVE_REQUEST:
494 _D("Active request FAILED, timerId = %d[%d], from start = %.1fs", id, __timerId, seconds);
495 __locationManagerStop();
498 case LOCATION_LOGGER_WAITING_FOR_SERVICE_START:
499 _D("Service start in timeout time FAILED, timerId = %d[%d], from start = %.1fs", id, __timerId, seconds);
500 // Waiting for service start FAILURE is also some kind of active request attempt
501 __activeRequestAttempts++;
504 __locationManagerStop();
507 case LOCATION_LOGGER_WAITING_FOR_LOCATION_METHOD_SETTING_ON:
508 _D("Still waiting for Location method settings on, timerId = %d[%d], from start = %.1fs", id, __timerId, seconds);
511 case LOCATION_LOGGER_WAITING_FOR_ACTIVE_INTERVAL:
512 _D("Active interval time expired, timerId = %d[%d], from start = %.1fs", id, __timerId, seconds);
514 case LOCATION_LOGGER_WAITING_FOR_PASSIVE_INTERVAL:
515 _D("Passive interval time expired, timerId = %d[%d], from start = %.1fs", id, __timerId, seconds);
518 _D("Do nothing, timerId = %d[%d], from start = %.1fs", id, __timerId, seconds);
521 if (__locationMethodState) {
522 __locationManagerStart();
524 __timerPurpose = LOCATION_LOGGER_WAITING_FOR_LOCATION_METHOD_SETTING_ON;
525 _D("LOCATION_LOGGER_WAITING_FOR_LOCATION_METHOD_SETTING_ON");
530 void ctx::LocationLogger::__activeRequestTimerStart()
532 int minutes = LOCATION_LOGGER_ACTIVE_REQUEST_TIMEOUT_SECONDS / 60;
533 if (LOCATION_LOGGER_ACTIVE_REQUEST_TIMEOUT_SECONDS % 60)
535 __timerPurpose = LOCATION_LOGGER_WAITING_FOR_ACTIVE_REQUEST;
536 _D("LOCATION_LOGGER_WAITING_FOR_ACTIVE_REQUEST (minutes=%d)", minutes);
537 __timerStart(minutes);
540 void ctx::LocationLogger::__startServiceTimerStart()
542 __timerPurpose = LOCATION_LOGGER_WAITING_FOR_SERVICE_START;
543 _D("LOCATION_LOGGER_WAITING_FOR_SERVICE_START");
544 __timerStart(LOCATION_LOGGER_SERVICE_START_TIMEOUT_MINUTES);
547 void ctx::LocationLogger::__activeIntervalTimerStart()
549 __timerPurpose = LOCATION_LOGGER_WAITING_FOR_ACTIVE_INTERVAL;
550 _D("LOCATION_LOGGER_WAITING_FOR_ACTIVE_INTERVAL");
551 __timerStart(LOCATION_LOGGER_ACTIVE_INTERVAL_MINUTES);
554 void ctx::LocationLogger::__passiveIntervalTimerStart()
556 __timerPurpose = LOCATION_LOGGER_WAITING_FOR_PASSIVE_INTERVAL;
557 _D("LOCATION_LOGGER_WAITING_FOR_PASSIVE_INTERVAL");
558 __timerStart(LOCATION_LOGGER_PASSIVE_INTERVAL_MINUTES);
561 void ctx::LocationLogger::__timerStart(time_t minutes)
563 __timerTimestamp = time(nullptr);
564 __timerId = __timerManager.setFor(minutes, this);
565 _D("%s (minutes=%d) timerId = %d", __timerId >= 0 ? "SUCCESS" : "ERROR", minutes, __timerId);
568 void ctx::LocationLogger::__timerStop()
571 __timerManager.remove(__timerId);
574 void ctx::LocationLogger::__startLogging()
577 __activeRequestAttempts = 0;
578 __activeAttempts = 0;
581 __activeRequestSucceeded = false;;
582 __activeLocationSucceeded = false;
583 __locationManagerStart();
586 void ctx::LocationLogger::__stopLogging()
590 __locationManagerStop();
593 void ctx::LocationLogger::onVisitStart()
599 void ctx::LocationLogger::onVisitEnd()
605 #undef __LOCATION_ERROR_LOG