From ae46b290aad15164222174892a42bf830bce7ab8 Mon Sep 17 00:00:00 2001 From: Somin Kim Date: Thu, 22 Dec 2016 00:05:36 +0900 Subject: [PATCH 01/16] [battery-stats] Request heart db sync Change-Id: I1e76bfa2ef8f64322f80eb61339445a15b604ae9 Signed-off-by: Somin Kim --- src/battery-stats/BatteryMonitor.cpp | 33 +++++++++++--- src/battery-stats/BatteryMonitor.h | 3 ++ src/battery-stats/BatteryUsage.cpp | 3 ++ src/battery-stats/HeartDbReader.cpp | 76 ++++++++++++++++++++++++++++++-- src/battery-stats/HeartDbReader.h | 15 +++++-- src/battery-stats/RecentBatteryUsage.cpp | 2 + 6 files changed, 118 insertions(+), 14 deletions(-) diff --git a/src/battery-stats/BatteryMonitor.cpp b/src/battery-stats/BatteryMonitor.cpp index e196338..d7dee42 100644 --- a/src/battery-stats/BatteryMonitor.cpp +++ b/src/battery-stats/BatteryMonitor.cpp @@ -21,7 +21,6 @@ #include #include #include -#include "HeartDbReader.h" #include "BatteryMonitor.h" #define DEFAULT_ROW_ID_STR "1" @@ -34,7 +33,8 @@ BatteryMonitor* BatteryMonitor::__instance = NULL; BatteryMonitor::BatteryMonitor() : __bootingTime(0), __lastFullTime(0), - __lastHeartAccessTime(0) + __lastHeartAccessTime(0), + __heartReader(NULL) { } @@ -136,6 +136,9 @@ gboolean BatteryMonitor::__timeoutCb(gpointer data) int BatteryMonitor::start() { + __heartReader = new(std::nothrow) HeartDbReader(); + IF_FAIL_RETURN_TAG(__heartReader, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + __loadLastInfo(); int error = device_add_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb, this); @@ -149,6 +152,11 @@ int BatteryMonitor::start() int BatteryMonitor::stop() { + if (__heartReader) { + delete __heartReader; + __heartReader = NULL; + } + int error = device_remove_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb); IF_FAIL_RETURN_TAG(error == DEVICE_ERROR_NONE, ERR_OPERATION_FAILED, _E, "Failed to remove callback for charger status"); @@ -189,13 +197,12 @@ bool BatteryMonitor::__getLastCpuUsageTable(CpuUsageMap* lastHeartCpuLog) bool BatteryMonitor::__processBatteryUsage() { // Read from heart cpu table - HeartDbReader heartReader; - bool ret = heartReader.open(); + bool ret = __heartReader->dbOpen(); IF_FAIL_RETURN_TAG(ret, true, _E, "Failed to open heart db"); std::vector heartCpuLog; - ret = heartReader.readCpuLog(__lastHeartAccessTime, &heartCpuLog); - heartReader.close(); + ret = __heartReader->readCpuLog(__lastHeartAccessTime, &heartCpuLog); + __heartReader->dbClose(); IF_FAIL_RETURN_TAG(ret, true, _E, "Cannot read from heart cpu table"); IF_FAIL_RETURN_TAG(heartCpuLog.size() > 0, true, _W, "Heart cpu data is not prepared"); @@ -259,6 +266,7 @@ bool BatteryMonitor::__insertBatteryUsageLog(std::vector& usage) bool BatteryMonitor::__updateLastCpuUsageLog(CpuUsageMap& usage) { IF_FAIL_RETURN_TAG(usage.size(), true, _W, "No data"); + _D("Delete all rows from app last times table"); __dbMgr.executeSync("DELETE FROM " BATTERY_LAST_CPU_USAGE_TABLE, NULL); std::string query("INSERT INTO " BATTERY_LAST_CPU_USAGE_TABLE "(" BATTERY_APP_ID ", " BATTERY_UTIME ", " BATTERY_STIME ", " BATTERY_TIMESTAMP ", " BATTERY_PID ") VALUES"); @@ -298,3 +306,16 @@ int BatteryMonitor::getLastFullTime() return __lastFullTime; } + +void BatteryMonitor::prepareData() +{ + int timeDiff = CURRENT_TIME - __lastHeartAccessTime; + IF_FAIL_VOID_TAG(timeDiff >= 5 * 60 * 1000, + _D, "Battery usage was updated %d minutes ago", timeDiff / 60000); + + _D("Request to sync heart cpu data"); + bool ret = __heartReader->requestSync(); + IF_FAIL_VOID_TAG(ret, _E, "Failed to sync heart db"); + + __processBatteryUsage(); +} diff --git a/src/battery-stats/BatteryMonitor.h b/src/battery-stats/BatteryMonitor.h index c6c10a8..89bf7f0 100644 --- a/src/battery-stats/BatteryMonitor.h +++ b/src/battery-stats/BatteryMonitor.h @@ -20,6 +20,7 @@ #include #include #include "BatteryUsageAnalyzer.h" +#include "HeartDbReader.h" namespace ctx { @@ -35,6 +36,7 @@ namespace ctx { int start(); int stop(); int getLastFullTime(); + void prepareData(); private: bool __loadLastInfo(); @@ -55,6 +57,7 @@ namespace ctx { DatabaseManager __dbMgr; BatteryUsageAnalyzer __analyzer; + HeartDbReader *__heartReader; }; } /* namespace ctx */ diff --git a/src/battery-stats/BatteryUsage.cpp b/src/battery-stats/BatteryUsage.cpp index c443f62..532234c 100644 --- a/src/battery-stats/BatteryUsage.cpp +++ b/src/battery-stats/BatteryUsage.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "BatteryMonitor.h" #include "BatteryUsage.h" #define SECONDS_IN_A_DAY 86400 @@ -31,6 +32,8 @@ BatteryUsageProvider::~BatteryUsageProvider() int BatteryUsageProvider::read(Json option, Json *requestResult) { + BatteryMonitor::getInstance()->prepareData(); + int startTime; int endTime; int timeSpan = DEFAULT_TIME_SPAN; diff --git a/src/battery-stats/HeartDbReader.cpp b/src/battery-stats/HeartDbReader.cpp index 5d8126a..d8db28f 100644 --- a/src/battery-stats/HeartDbReader.cpp +++ b/src/battery-stats/HeartDbReader.cpp @@ -31,33 +31,52 @@ using namespace ctx; HeartDbReader::HeartDbReader() : - __heartDb(NULL) + __heartDb(NULL), + __connection(NULL), + __dbRefCount(0) { + __initializeDBusConnection(); } HeartDbReader::~HeartDbReader() { if (__heartDb) { - close(); + dbClose(); + } + + if (__connection) { + __releaseDBusConnection(); } } -bool HeartDbReader::open() +bool HeartDbReader::dbOpen() { + if (__heartDb) { + __dbRefCount++; + return true; + } + sqlite3 *db = NULL; int ret; ret = sqlite3_open_v2(HEART_DB_PATH, &db, SQLITE_OPEN_READONLY, NULL); IF_FAIL_RETURN_TAG(ret == SQLITE_OK, false, _E, "Failed to open HEART db: %s", sqlite3_errmsg(db)); __heartDb = db; + __dbRefCount++; return true; } -void HeartDbReader::close() +void HeartDbReader::dbClose() { + if (__dbRefCount > 1) { + __dbRefCount--; + return; + } + sqlite3_close(__heartDb); __heartDb = NULL; + __dbRefCount = 0; } bool HeartDbReader::readCpuLog(int lastHeartAccessTime, std::vector* cpuUsageLog) @@ -134,3 +153,52 @@ void HeartDbReader::__convertCpuUsageLog(Json& row, Json* newRow) newRow->set(NULL, BATTERY_INDEX, index); newRow->set(NULL, BATTERY_PID, pid); } + +bool HeartDbReader::__initializeDBusConnection() +{ +#if !GLIB_CHECK_VERSION(2, 36, 0) + g_type_init(); +#endif + GError *error = NULL; + + __connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!__connection) { + _E("dbus connection get failed: %s", error->message); + g_error_free(error); + return false; + } + + return true; +} + +void HeartDbReader::__releaseDBusConnection() +{ + if (__connection) { + g_object_unref(__connection); + __connection = NULL; + } +} + +bool HeartDbReader::requestSync() +{ + IF_FAIL_RETURN_TAG(__connection, false, _E, "Dbus connection is not initialized"); + + GError *error = NULL; + GVariant* ret = NULL; + ret = g_dbus_connection_call_sync(__connection, + "org.tizen.resourced", "/Org/Tizen/ResourceD/Logging", "org.tizen.resourced.logging", + "SyncCpuData", NULL, NULL, G_DBUS_CALL_FLAGS_NONE, 2000, NULL, &error); + + if (error) { + _E("Failed to dbus call: %s", error->message); + g_clear_error(&error); + return false; + } + + int result; + g_variant_get(ret, "(i)", &result); + g_variant_unref(ret); + IF_FAIL_RETURN_TAG(result != -1, false, _E, "Failed to sync heart cpu data"); + + return true; +} diff --git a/src/battery-stats/HeartDbReader.h b/src/battery-stats/HeartDbReader.h index ddf600e..b219919 100644 --- a/src/battery-stats/HeartDbReader.h +++ b/src/battery-stats/HeartDbReader.h @@ -17,9 +17,11 @@ #ifndef _CONTEXT_HEART_DB_READER_H_ #define _CONTEXT_HEART_DB_READER_H_ -#include #include +#include +#include #include +#include namespace ctx { @@ -28,16 +30,21 @@ namespace ctx { HeartDbReader(); ~HeartDbReader(); - bool open(); - void close(); - + bool dbOpen(); + void dbClose(); bool readCpuLog(int __lastHeartAccessTime, std::vector* cpuUsageLog); + bool requestSync(); private: static int __cpuUsageLogCb(void *userData, int dim, char **value, char **column); static void __convertCpuUsageLog(Json& row, Json* newRow); + bool __initializeDBusConnection(); + void __releaseDBusConnection(); + sqlite3 *__heartDb; + GDBusConnection *__connection; + int __dbRefCount; }; } /* namespace ctx */ diff --git a/src/battery-stats/RecentBatteryUsage.cpp b/src/battery-stats/RecentBatteryUsage.cpp index f6954c7..eda9d8e 100644 --- a/src/battery-stats/RecentBatteryUsage.cpp +++ b/src/battery-stats/RecentBatteryUsage.cpp @@ -30,6 +30,8 @@ RecentBatteryUsageProvider::~RecentBatteryUsageProvider() int RecentBatteryUsageProvider::read(Json option, Json *requestResult) { + BatteryMonitor::getInstance()->prepareData(); + int resultSize; bool hasLimit = option.get(NULL, KEY_RESULT_SIZE, &resultSize); -- 2.7.4 From 74e73a3dfd2e2b19a213f615ee74a0cc4c93e6b7 Mon Sep 17 00:00:00 2001 From: Somin Kim Date: Thu, 22 Dec 2016 14:36:58 +0900 Subject: [PATCH 02/16] [battery-stats] Remove expired log & Version 0.9.11 Change-Id: I95508ae62154f37c88a02d5748c46580776e6ef3 Signed-off-by: Somin Kim --- packaging/context-provider.spec | 2 +- src/battery-stats/BatteryMonitor.cpp | 19 +++++++++++++++++++ src/battery-stats/BatteryMonitor.h | 1 + 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index cc39fd3..d973523 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -1,6 +1,6 @@ Name: context-provider Summary: Context Provider -Version: 0.9.10 +Version: 0.9.11 Release: 1 Group: Service/Context License: Apache-2.0 diff --git a/src/battery-stats/BatteryMonitor.cpp b/src/battery-stats/BatteryMonitor.cpp index d7dee42..4c34e8c 100644 --- a/src/battery-stats/BatteryMonitor.cpp +++ b/src/battery-stats/BatteryMonitor.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -25,6 +26,7 @@ #define DEFAULT_ROW_ID_STR "1" #define HEART_DB_QUERY_INTERVAL 10 * 60 * 1000 +#define ONE_DAY_IN_SEC 86400 using namespace ctx; @@ -227,6 +229,8 @@ bool BatteryMonitor::__processBatteryUsage() ret = __updateLastCpuUsageLog(lastHeartCpuLog); IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to update last cpu log"); + __removeExpiredLog(); + return true; } @@ -263,6 +267,21 @@ bool BatteryMonitor::__insertBatteryUsageLog(std::vector& usage) return __dbMgr.executeSync(query.c_str(), NULL); } +void BatteryMonitor::__removeExpiredLog() +{ + static int lastCleanupTime = 0; + + int currentTime = CURRENT_TIME; + IF_FAIL_VOID(currentTime - lastCleanupTime >= ONE_DAY_IN_SEC); + lastCleanupTime = currentTime; + + std::stringstream query; + query << "DELETE FROM " BATTERY_USAGE_TABLE " WHERE " \ + "EndTime < strftime('%s', 'now') - " << LOG_RETENTION_PERIOD; + __dbMgr.execute(0, query.str().c_str(), NULL); + _D("Remove expired log"); +} + bool BatteryMonitor::__updateLastCpuUsageLog(CpuUsageMap& usage) { IF_FAIL_RETURN_TAG(usage.size(), true, _W, "No data"); diff --git a/src/battery-stats/BatteryMonitor.h b/src/battery-stats/BatteryMonitor.h index 89bf7f0..4127b09 100644 --- a/src/battery-stats/BatteryMonitor.h +++ b/src/battery-stats/BatteryMonitor.h @@ -46,6 +46,7 @@ namespace ctx { bool __insertBatteryUsageLog(std::vector& usage); bool __updateLastCpuUsageLog(CpuUsageMap& usage); bool __getLastCpuUsageTable(CpuUsageMap* lastCpuUsage); + void __removeExpiredLog(); static void __chargerChangeCb(device_callback_e type, void* value, void* userData); static int __timeoutCb(void* data); -- 2.7.4 From a94936b68c6f947626fb8142d590ad2689e087f3 Mon Sep 17 00:00:00 2001 From: Somin Kim Date: Mon, 26 Dec 2016 16:22:42 +0900 Subject: [PATCH 03/16] [battery-stats] Changed heart sync policy (after rebooting, fully charged ...) & Version 0.9.12 Change-Id: I72136a878c40bcd30942c218bc83c32b4a54e04c Signed-off-by: Somin Kim --- packaging/context-provider.spec | 2 +- src/battery-stats/BatteryMonitor.cpp | 22 ++++++++++++---------- src/battery-stats/BatteryMonitor.h | 1 - 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index d973523..7a22304 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -1,6 +1,6 @@ Name: context-provider Summary: Context Provider -Version: 0.9.11 +Version: 0.9.12 Release: 1 Group: Service/Context License: Apache-2.0 diff --git a/src/battery-stats/BatteryMonitor.cpp b/src/battery-stats/BatteryMonitor.cpp index 4c34e8c..3e1715f 100644 --- a/src/battery-stats/BatteryMonitor.cpp +++ b/src/battery-stats/BatteryMonitor.cpp @@ -30,10 +30,10 @@ using namespace ctx; +bool __needSync = true; BatteryMonitor* BatteryMonitor::__instance = NULL; BatteryMonitor::BatteryMonitor() : - __bootingTime(0), __lastFullTime(0), __lastHeartAccessTime(0), __heartReader(NULL) @@ -80,8 +80,6 @@ void BatteryMonitor::initialize() bool BatteryMonitor::__loadLastInfo() { - __bootingTime = CURRENT_TIME; - std::vector records; bool ret = __dbMgr.executeSync( "SELECT * FROM " BATTERY_LAST_INFO_TABLE \ @@ -93,6 +91,12 @@ bool BatteryMonitor::__loadLastInfo() records[0].get(NULL, BATTERY_LAST_HEART_ACCESS_TIME, &__lastHeartAccessTime); } + if (__lastFullTime == 0) { + __lastFullTime = CURRENT_TIME; + _I("Device has not fully charged until now. Start time of recent battery usage will be %d", __lastFullTime); + __updateLastInfo(); + } + return true; } @@ -120,6 +124,8 @@ void BatteryMonitor::__chargerChangeCb(device_callback_e type, void* value, void // If charger is disconnected after 100% charged if (percent == 100) { + __needSync = true; + instance->__lastFullTime = CURRENT_TIME; _D("Charger is disconnected after fully charged. Last fully charged time: %d", instance->__lastFullTime); @@ -230,6 +236,7 @@ bool BatteryMonitor::__processBatteryUsage() IF_FAIL_RETURN_TAG(ret, false, _E, "Failed to update last cpu log"); __removeExpiredLog(); + __needSync = false; return true; } @@ -318,19 +325,14 @@ bool BatteryMonitor::__updateLastCpuUsageLog(CpuUsageMap& usage) // Used for Recent Battery Usage int BatteryMonitor::getLastFullTime() { - if (__lastFullTime == 0) { - _I("Device has not fully charged until now. Start time of recent battery usage will be booting time: %d", __bootingTime); - return __bootingTime; - } - return __lastFullTime; } void BatteryMonitor::prepareData() { int timeDiff = CURRENT_TIME - __lastHeartAccessTime; - IF_FAIL_VOID_TAG(timeDiff >= 5 * 60 * 1000, - _D, "Battery usage was updated %d minutes ago", timeDiff / 60000); + IF_FAIL_VOID_TAG(__needSync || timeDiff >= 5 * 60, + _D, "Battery usage was updated %d minutes ago", timeDiff / 60); _D("Request to sync heart cpu data"); bool ret = __heartReader->requestSync(); diff --git a/src/battery-stats/BatteryMonitor.h b/src/battery-stats/BatteryMonitor.h index 4127b09..f87dc3b 100644 --- a/src/battery-stats/BatteryMonitor.h +++ b/src/battery-stats/BatteryMonitor.h @@ -52,7 +52,6 @@ namespace ctx { static int __timeoutCb(void* data); static BatteryMonitor* __instance; - int __bootingTime; int __lastFullTime; int __lastHeartAccessTime; -- 2.7.4 From cf56eb44e2bb6a924cf47cab52a10de71a563ec2 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Thu, 29 Dec 2016 14:52:42 +0900 Subject: [PATCH 04/16] [battery-usage] add defence code for time changes & Version 0.9.13 Change-Id: I97470e5f0cb4d3b011e5d44060b8d50ce3527c33 Signed-off-by: Mu-Woong Lee --- packaging/context-provider.spec | 2 +- src/battery-stats/BatteryMonitor.cpp | 23 +++++++++++++++++------ src/battery-stats/HeartDbReader.cpp | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index 7a22304..f66d6a2 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -1,6 +1,6 @@ Name: context-provider Summary: Context Provider -Version: 0.9.12 +Version: 0.9.13 Release: 1 Group: Service/Context License: Apache-2.0 diff --git a/src/battery-stats/BatteryMonitor.cpp b/src/battery-stats/BatteryMonitor.cpp index 3e1715f..0bb5097 100644 --- a/src/battery-stats/BatteryMonitor.cpp +++ b/src/battery-stats/BatteryMonitor.cpp @@ -27,6 +27,8 @@ #define DEFAULT_ROW_ID_STR "1" #define HEART_DB_QUERY_INTERVAL 10 * 60 * 1000 #define ONE_DAY_IN_SEC 86400 +#define DEFAULT_TIME_DIFF 600 +#define TIME_DIFF_THRESHOLD 300 using namespace ctx; @@ -204,6 +206,13 @@ bool BatteryMonitor::__getLastCpuUsageTable(CpuUsageMap* lastHeartCpuLog) bool BatteryMonitor::__processBatteryUsage() { + if (__lastHeartAccessTime > CURRENT_TIME) { + __lastHeartAccessTime = CURRENT_TIME - DEFAULT_TIME_DIFF; + __lastFullTime = CURRENT_TIME - DEFAULT_TIME_DIFF; + __updateLastInfo(); + __dbMgr.executeSync("DELETE FROM " BATTERY_LAST_CPU_USAGE_TABLE, NULL); + } + // Read from heart cpu table bool ret = __heartReader->dbOpen(); IF_FAIL_RETURN_TAG(ret, true, _E, "Failed to open heart db"); @@ -282,19 +291,21 @@ void BatteryMonitor::__removeExpiredLog() IF_FAIL_VOID(currentTime - lastCleanupTime >= ONE_DAY_IN_SEC); lastCleanupTime = currentTime; - std::stringstream query; - query << "DELETE FROM " BATTERY_USAGE_TABLE " WHERE " \ - "EndTime < strftime('%s', 'now') - " << LOG_RETENTION_PERIOD; - __dbMgr.execute(0, query.str().c_str(), NULL); + char *sql = sqlite3_mprintf( + "DELETE FROM " BATTERY_USAGE_TABLE " WHERE EndTime < %d OR EndTime > %d", + CURRENT_TIME - LOG_RETENTION_PERIOD, CURRENT_TIME); + __dbMgr.execute(0, sql, NULL); + sqlite3_free(sql); _D("Remove expired log"); } bool BatteryMonitor::__updateLastCpuUsageLog(CpuUsageMap& usage) { - IF_FAIL_RETURN_TAG(usage.size(), true, _W, "No data"); _D("Delete all rows from app last times table"); __dbMgr.executeSync("DELETE FROM " BATTERY_LAST_CPU_USAGE_TABLE, NULL); + IF_FAIL_RETURN_TAG(usage.size(), true, _W, "No data"); + std::string query("INSERT INTO " BATTERY_LAST_CPU_USAGE_TABLE "(" BATTERY_APP_ID ", " BATTERY_UTIME ", " BATTERY_STIME ", " BATTERY_TIMESTAMP ", " BATTERY_PID ") VALUES"); std::string appId; @@ -331,7 +342,7 @@ int BatteryMonitor::getLastFullTime() void BatteryMonitor::prepareData() { int timeDiff = CURRENT_TIME - __lastHeartAccessTime; - IF_FAIL_VOID_TAG(__needSync || timeDiff >= 5 * 60, + IF_FAIL_VOID_TAG(__needSync || timeDiff >= TIME_DIFF_THRESHOLD || timeDiff < 0, _D, "Battery usage was updated %d minutes ago", timeDiff / 60); _D("Request to sync heart cpu data"); diff --git a/src/battery-stats/HeartDbReader.cpp b/src/battery-stats/HeartDbReader.cpp index d8db28f..ee79f85 100644 --- a/src/battery-stats/HeartDbReader.cpp +++ b/src/battery-stats/HeartDbReader.cpp @@ -85,7 +85,7 @@ bool HeartDbReader::readCpuLog(int lastHeartAccessTime, std::vector* cpuUs char* sql = sqlite3_mprintf( "SELECT " HEART_APP_ID ", " HEART_TIME ", " HEART_DATA ", " HEART_INDEX " FROM " HEART_CPU_TABLE \ - " WHERE " HEART_TIME " > %d", lastHeartAccessTime); + " WHERE " HEART_TIME " > %d AND " HEART_TIME " <= %d", lastHeartAccessTime, CURRENT_TIME); char* err = NULL; int ret = sqlite3_exec(__heartDb, sql, __cpuUsageLogCb, cpuUsageLog, &err); -- 2.7.4 From 5b0c2fb08499e06d65e16b9021ac0c7cd686880c Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Fri, 30 Dec 2016 10:41:16 +0900 Subject: [PATCH 05/16] Sync with 2.3.2's sensor timestamp compensation Change-Id: I5aef796e98e1159daa4d6ac3a226fc8e5dd13ef5 Signed-off-by: Mu-Woong Lee --- src/sensor/TimeUtil.cpp | 52 +++++++++++++++++++++++--------- src/sensor/TimeUtil.h | 2 +- src/sensor/pedometer/PedometerLogger.cpp | 2 ++ 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/sensor/TimeUtil.cpp b/src/sensor/TimeUtil.cpp index ecfec5c..2e37da6 100644 --- a/src/sensor/TimeUtil.cpp +++ b/src/sensor/TimeUtil.cpp @@ -16,11 +16,19 @@ */ #include -#include -#include #include "TypesInternal.h" #include "TimeUtil.h" +/* NOTE: CLOCK_BOOTTIME is defined in linux/time.h. + But if it is included, we encounters the redefinition error of timespec. */ +#define CLOCK_BOOTTIME 7 + +#define DIFF(X, Y) ((X) > (Y) ? (X) - (Y) : (Y) - (X)) +#define SEC_TO_MSEC(X) ((uint64_t)(X) * 1000ull) +#define USEC_TO_MSEC(X) ((uint64_t)(X) / 1000ull) +#define NSEC_TO_MSEC(X) ((uint64_t)(X) / 1000000ull) +#define EPSILON 3ull + using namespace ctx; TimeUtil::TimeUtil() @@ -29,24 +37,38 @@ TimeUtil::TimeUtil() uint64_t TimeUtil::getTime() { - struct timeval tv; - double timestamp; + struct timespec ts; + uint64_t epochInMSec; + + clock_gettime(CLOCK_REALTIME_COARSE, &ts); + epochInMSec = SEC_TO_MSEC(ts.tv_sec) + NSEC_TO_MSEC(ts.tv_nsec); - gettimeofday(&tv, NULL); - timestamp = tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0; - return static_cast(round(timestamp)); + return epochInMSec; } -uint64_t TimeUtil::getTime(unsigned long long monotonic) +uint64_t TimeUtil::getTime(unsigned long long sensorTimestamp) { - struct timespec ts; - double timestamp; - uint64_t currentTime = getTime(); + uint64_t currentEpoch = getTime(); + uint64_t sensorTimeMSec = USEC_TO_MSEC(sensorTimestamp); + + bool isEpoch = DIFF(currentEpoch, sensorTimeMSec) < SEC_TO_MSEC(SECONDS_PER_DAY); + + if (isEpoch) + return sensorTimeMSec; - if (std::abs(currentTime / 1000 - monotonic / 1000000) < SECONDS_PER_DAY) - return static_cast(round(monotonic / 1000.0)); + struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - timestamp = static_cast(currentTime) - (ts.tv_sec * 1000000000.0 + ts.tv_nsec) / 1000000.0 + monotonic / 1000.0; - return static_cast(round(timestamp)); + + uint64_t currentMonotonic = SEC_TO_MSEC(ts.tv_sec) + NSEC_TO_MSEC(ts.tv_nsec); + bool isMonotonic = currentMonotonic + EPSILON > sensorTimeMSec; + + if (isMonotonic) + return currentEpoch - currentMonotonic + sensorTimeMSec; + + + clock_gettime(CLOCK_BOOTTIME, &ts); + uint64_t currentBootTime = SEC_TO_MSEC(ts.tv_sec) + NSEC_TO_MSEC(ts.tv_nsec); + + return currentEpoch - currentBootTime + sensorTimeMSec; } diff --git a/src/sensor/TimeUtil.h b/src/sensor/TimeUtil.h index 0fb3169..bdacf06 100644 --- a/src/sensor/TimeUtil.h +++ b/src/sensor/TimeUtil.h @@ -25,7 +25,7 @@ namespace ctx { class TimeUtil { public: static uint64_t getTime(); - static uint64_t getTime(unsigned long long monotonic); + static uint64_t getTime(unsigned long long sensorTimestamp); private: TimeUtil(); diff --git a/src/sensor/pedometer/PedometerLogger.cpp b/src/sensor/pedometer/PedometerLogger.cpp index b27fa3d..cc44856 100644 --- a/src/sensor/pedometer/PedometerLogger.cpp +++ b/src/sensor/pedometer/PedometerLogger.cpp @@ -73,6 +73,8 @@ void PedometerLogger::stop() unlisten(); __firstEvent = true; + + flushCache(true); } void PedometerLogger::flushCache(bool force) -- 2.7.4 From 7fe434d653c6af9ccb82176df90609136e0de617 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Tue, 20 Sep 2016 05:22:24 +0000 Subject: [PATCH 06/16] Remove profile build dependencies The previous spec/build scripts stated that it will add more libraries if the profile macro is mobile while the other libraries and devel packages were identical. The patch allows this package to become profile agnostic by seperating the additional mobile libraries (context-provider-extended), which can be optionally installed at any time, at any profile, while they can share the same build project. (Yay!) NOTE: When this commit is being SR'ed, maintainers need to create JIRA-TRE of: - Add context-provider-profile_mobile for mobile profile. Change-Id: Ie646dc6fcfab7251e43149dfbe43fa972aee8784 Signed-off-by: MyungJoo Ham --- packaging/context-provider.spec | 72 ++++++++++++++++++++++++++++++----------- src/CMakeLists.txt | 8 ++--- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index f66d6a2..66d1fd8 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -1,12 +1,19 @@ Name: context-provider Summary: Context Provider -Version: 0.9.13 +Version: 0.9.14 Release: 1 Group: Service/Context License: Apache-2.0 Source0: %{name}-%{version}.tar.gz +Provides: context-provider-profile_common = %{version}-%{release} +Provides: context-provider-profile_wearable = %{version}-%{release} +Provides: context-provider-profile_tv = %{version}-%{release} +Provides: context-provider-profile_ivi = %{version}-%{release} -%define BUILD_PROFILE %{?profile}%{!?profile:%{?tizen_profile_name}} +# Temporarily need to keep this until context-provider is in Tizen:TV OBS project. +# Once this package is moved to Base2, we can remove al BUILD_PROFILE related statements (if/endif) +# In order to be prepared for transition period, we defined "null" +%define BUILD_PROFILE %{?profile}%{!?profile:%{?tizen_profile_name}%{!?tizen_profile_name:null}} BuildRequires: cmake @@ -17,15 +24,18 @@ BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-device) BuildRequires: pkgconfig(capi-system-runtime-info) BuildRequires: pkgconfig(capi-media-sound-manager) -BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(capi-network-wifi) BuildRequires: pkgconfig(sensor) BuildRequires: pkgconfig(motion) -%if "%{?BUILD_PROFILE}" == "mobile" +# TODO TEMPORARY STATEMENT +# if it is mobile or BASE2 (when we have migrated everything into BASE2, we can remove this if statement) +# Common also supports extension mode. +%if "%{?BUILD_PROFILE}" != "tv" && "%{?BUILD_PROFILE}" != "wearable" && "%{?BUILD_PROFILE}" != "ivi" BuildRequires: pkgconfig(capi-appfw-package-manager) BuildRequires: pkgconfig(capi-appfw-application) BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(msg-service) @@ -48,24 +58,21 @@ Context Provider %build MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` -export CFLAGS+=" -Wextra -Wcast-align -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-parameter" export CXXFLAGS+=" -Wextra -Wcast-align -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-parameter" - -export CFLAGS+=" -Wno-empty-body -fomit-frame-pointer -fno-optimize-sibling-calls" export CXXFLAGS+=" -Wno-empty-body -fomit-frame-pointer -fno-optimize-sibling-calls" - -export CFLAGS+=" -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow" export CXXFLAGS+=" -fno-strict-aliasing -fno-unroll-loops -fsigned-char -fstrict-overflow" +export CXXFLAGS+=" -Wnon-virtual-dtor -std=c++0x" -export CFLAGS+=" -fno-common" -export CXXFLAGS+=" -Wnon-virtual-dtor" -export CXXFLAGS+=" -std=c++0x" - -#export CFLAGS+=" -Wcast-qual" -#export CXXFLAGS+=" -Wcast-qual" +# TODO TEMPORARY STATEMENT +# if it is mobile or BASE2 (when we have migrated everything into BASE2, we can remove this if statement) +%if "%{?BUILD_PROFILE}" != "tv" && "%{?BUILD_PROFILE}" != "wearable" && "%{?BUILD_PROFILE}" != "ivi" +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DLIBDIR=%{_libdir} -DMAJORVER=${MAJORVER} -DFULLVER=%{version} -DFEATURES=extended +make %{?jobs:-j%jobs} -cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DLIBDIR=%{_libdir} -DMAJORVER=${MAJORVER} -DFULLVER=%{version} -DPROFILE=%{?BUILD_PROFILE} +%else +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DLIBDIR=%{_libdir} -DMAJORVER=${MAJORVER} -DFULLVER=%{version} -DFEATURES=standard make %{?jobs:-j%jobs} +%endif %install rm -rf %{buildroot} @@ -79,9 +86,12 @@ rm -rf %{buildroot} %files %manifest packaging/%{name}.manifest -%defattr(-,root,root,-) %{_libdir}/*.so* -%{_libdir}/context-service/*.so* +%{_libdir}/context-service/*activity.so* +%{_libdir}/context-service/*custom.so* +%{_libdir}/context-service/*sensor.so* +%{_libdir}/context-service/*system.so* +%{_libdir}/context-service/*time.so* %license LICENSE %package devel @@ -93,5 +103,29 @@ Requires: %{name} = %{version}-%{release} Context Provider Shared Header (DEV) %files devel -%defattr(-,root,root,-) +%manifest packaging/%{name}.manifest %{_includedir}/context-service/internal/*.h + +# TODO TEMPORARY STATEMENT +# if it is mobile or BASE2 (when we have migrated everything into BASE2, we can remove this if statement) +%if "%{?BUILD_PROFILE}" != "tv" && "%{?BUILD_PROFILE}" != "wearable" && "%{?BUILD_PROFILE}" != "ivi" + +%package extended +Summary: Extended binary for mobile functions +Requires: context-provider = %{version}-%{release} +Provides: context-provider-profile_mobile = %{version}-%{release} + +%description extended +Extended context-provider binary for mobile functions. +The metadata for mobile-supporting KS should include this subpackage + +%files extended +%manifest packaging/%{name}.manifest +%exclude %{_libdir}/context-service/*activity.so* +%exclude %{_libdir}/context-service/*custom.so* +%exclude %{_libdir}/context-service/*sensor.so* +%exclude %{_libdir}/context-service/*system.so* +%exclude %{_libdir}/context-service/*time.so* +%{_libdir}/context-service/*.so* + +%endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 30d980b..a137021 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,21 +6,21 @@ SET(DEPS ADD_SUBDIRECTORY(shared) ADD_SUBDIRECTORY(activity) ADD_SUBDIRECTORY(custom) -ADD_SUBDIRECTORY(headphone) ADD_SUBDIRECTORY(sensor) ADD_SUBDIRECTORY(system) ADD_SUBDIRECTORY(time) -ADD_SUBDIRECTORY(wifi) -IF("${PROFILE}" STREQUAL "mobile") +IF("${FEATURES}" STREQUAL "extended") ADD_SUBDIRECTORY(app-stats) ADD_SUBDIRECTORY(battery-stats) ADD_SUBDIRECTORY(call) ADD_SUBDIRECTORY(contacts) ADD_SUBDIRECTORY(email) ADD_SUBDIRECTORY(geofence) +ADD_SUBDIRECTORY(headphone) ADD_SUBDIRECTORY(media-stats) ADD_SUBDIRECTORY(message) ADD_SUBDIRECTORY(my-place) ADD_SUBDIRECTORY(social-stats) -ENDIF("${PROFILE}" STREQUAL "mobile") +ADD_SUBDIRECTORY(wifi) +ENDIF("${FEATURES}" STREQUAL "extended") -- 2.7.4 From dc0a8426af4f6c916190dc9d137ca0eff449c678 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Thu, 5 Jan 2017 19:14:39 +0900 Subject: [PATCH 07/16] "profile_common" virtual package is provided by the extension Change-Id: I4730b92efb738c55ba129a97d6be8a89a2094820 Signed-off-by: Mu-Woong Lee --- packaging/context-provider.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index 66d1fd8..8cf4fde 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -5,7 +5,6 @@ Release: 1 Group: Service/Context License: Apache-2.0 Source0: %{name}-%{version}.tar.gz -Provides: context-provider-profile_common = %{version}-%{release} Provides: context-provider-profile_wearable = %{version}-%{release} Provides: context-provider-profile_tv = %{version}-%{release} Provides: context-provider-profile_ivi = %{version}-%{release} @@ -114,6 +113,7 @@ Context Provider Shared Header (DEV) Summary: Extended binary for mobile functions Requires: context-provider = %{version}-%{release} Provides: context-provider-profile_mobile = %{version}-%{release} +Provides: context-provider-profile_common = %{version}-%{release} %description extended Extended context-provider binary for mobile functions. -- 2.7.4 From 52e0ca954149321fe6d976e4d3a116ba627880ba Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Tue, 17 Jan 2017 13:13:30 +0900 Subject: [PATCH 08/16] Add a cache for application display types Change-Id: I4e49ae6e9161ac4d4db6f539499de249bb998243 Signed-off-by: Mu-Woong Lee --- src/app-stats/ActiveWindowMonitor.cpp | 65 ++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/src/app-stats/ActiveWindowMonitor.cpp b/src/app-stats/ActiveWindowMonitor.cpp index 107d598..97a5b48 100644 --- a/src/app-stats/ActiveWindowMonitor.cpp +++ b/src/app-stats/ActiveWindowMonitor.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include @@ -27,6 +29,51 @@ /* Active window changes frequently. * We thus consider the apps being foregrounded at least 3 secs */ #define ONE_DAY_IN_SEC 86400 +#define DEFAULT_CACHE_SIZE 10 +#define TOP_TIER_LIMIT 2 + +class AppDisplayTypeCache { +private: + unsigned int __size; + std::list> __cache; + +public: + AppDisplayTypeCache(unsigned int size) : + __size(size) + { + } + + void put(const std::string& appId, bool noDisp) + { + __cache.push_front(std::make_pair(appId, noDisp)); + + if (__cache.size() > __size) + __cache.pop_back(); + } + + bool get(const std::string& appId, bool* noDisp) + { + int index = 0; + + for (auto it = __cache.begin(); it != __cache.end(); ++it) { + if ((*it).first != appId) { + ++index; + continue; + } + + *noDisp = (*it).second; + + if (index > TOP_TIER_LIMIT) { + __cache.erase(it); + __cache.push_front(std::make_pair(appId, *noDisp)); + } + + return true; + } + + return false; + } +}; ctx::AppUseMonitor::AppUseMonitor() : __signalId(-1), @@ -117,13 +164,20 @@ void ctx::AppUseMonitor::__finishRecord(std::string appId) bool ctx::AppUseMonitor::__isSkippable(std::string appId) { - /* TODO: circular cache */ + static AppDisplayTypeCache __cache(DEFAULT_CACHE_SIZE); + + bool noDisp = false; + + if (__cache.get(appId, &noDisp)) + return noDisp; + + _D("No cache for '%s'", appId.c_str()); + app_info_h appInfo = NULL; int err = app_manager_get_app_info(appId.c_str(), &appInfo); IF_FAIL_RETURN_TAG(err == APP_MANAGER_ERROR_NONE && appInfo, true, _E, "app_manager_get_app_info() failed"); - bool nodisp = false; - err = app_info_is_nodisplay(appInfo, &nodisp); + err = app_info_is_nodisplay(appInfo, &noDisp); if (err != APP_MANAGER_ERROR_NONE) { app_info_destroy(appInfo); _E("app_info_is_nodisplay() failed"); @@ -131,7 +185,10 @@ bool ctx::AppUseMonitor::__isSkippable(std::string appId) } app_info_destroy(appInfo); - return nodisp; + + __cache.put(appId, noDisp); + + return noDisp; } void ctx::AppUseMonitor::__removeExpired() -- 2.7.4 From 6987b02636004b3d30f9605f0fa55d6aca108d93 Mon Sep 17 00:00:00 2001 From: Somin Kim Date: Thu, 19 Jan 2017 15:22:11 +0900 Subject: [PATCH 09/16] Add defence code for duration calculation when time manually changed Change-Id: I0f575e97cfc7fbd8f2e6e56a7f637898945f6073 Signed-off-by: Somin Kim --- src/app-stats/ActiveWindowMonitor.cpp | 19 ++++++++++++-- src/app-stats/ActiveWindowMonitor.h | 4 +++ src/app-stats/CMakeLists.txt | 1 + src/battery-stats/BatteryMonitor.cpp | 42 ++++++++++++++++++++++++------ src/battery-stats/BatteryMonitor.h | 3 +++ src/battery-stats/BatteryUsageAnalyzer.cpp | 8 ++++++ src/battery-stats/CMakeLists.txt | 1 + 7 files changed, 68 insertions(+), 10 deletions(-) diff --git a/src/app-stats/ActiveWindowMonitor.cpp b/src/app-stats/ActiveWindowMonitor.cpp index 97a5b48..2f06201 100644 --- a/src/app-stats/ActiveWindowMonitor.cpp +++ b/src/app-stats/ActiveWindowMonitor.cpp @@ -78,14 +78,17 @@ public: ctx::AppUseMonitor::AppUseMonitor() : __signalId(-1), __lastCleanupTime(0), - __dbusWatcher(DBusType::SYSTEM) + __dbusWatcher(DBusType::SYSTEM), + __timeDiff(0) { __startLogging(); + vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, __timeChangeCb, this); } ctx::AppUseMonitor::~AppUseMonitor() { __stopLogging(); + vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, __timeChangeCb); } bool ctx::AppUseMonitor::__startLogging() @@ -122,6 +125,7 @@ void ctx::AppUseMonitor::onSignal(const char* sender, const char* path, const ch } else if (STR_EQ(status, "bg")) { __finishRecord(appId); __removeExpired(); + __timeDiff = 0; } } @@ -154,7 +158,7 @@ void ctx::AppUseMonitor::__finishRecord(std::string appId) std::stringstream query; query << "UPDATE " APP_TABLE_USAGE_LOG \ - " SET " KEY_DURATION " = strftime('%s', 'now') - " KEY_UNIV_TIME \ + " SET " KEY_DURATION " = strftime('%s', 'now') - (" KEY_UNIV_TIME " + " << __timeDiff << ")" \ " WHERE " KEY_COL_ROW_ID " = (" \ "SELECT MAX(" KEY_COL_ROW_ID ") FROM " APP_TABLE_USAGE_LOG \ " WHERE " KEY_APP_ID " = '" << appId << "'" \ @@ -203,3 +207,14 @@ void ctx::AppUseMonitor::__removeExpired() KEY_UNIV_TIME " < strftime('%s', 'now') - " << LOG_RETENTION_PERIOD; __dbManager.execute(0, query.str().c_str(), NULL); } + +void ctx::AppUseMonitor::__timeChangeCb(keynode_t* node, void* userData) +{ + int timeDiff = vconf_keynode_get_int(node); + IF_FAIL_VOID(timeDiff != 0); + + _D("Time changed. Related timestamps will be modified."); + + AppUseMonitor* instance = static_cast(userData); + instance->__timeDiff = instance->__timeDiff + timeDiff; +} diff --git a/src/app-stats/ActiveWindowMonitor.h b/src/app-stats/ActiveWindowMonitor.h index 64f0d34..3170c5b 100644 --- a/src/app-stats/ActiveWindowMonitor.h +++ b/src/app-stats/ActiveWindowMonitor.h @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -30,6 +31,7 @@ namespace ctx { int __lastCleanupTime; DBusSignalWatcher __dbusWatcher; DatabaseManager __dbManager; + int __timeDiff; bool __startLogging(void); void __stopLogging(void); @@ -40,6 +42,8 @@ namespace ctx { void __removeExpired(); void onSignal(const char *sender, const char *path, const char *iface, const char *name, GVariant *param); + static void __timeChangeCb(keynode_t* node, void* userData); + public: AppUseMonitor(); ~AppUseMonitor(); diff --git a/src/app-stats/CMakeLists.txt b/src/app-stats/CMakeLists.txt index a11dec1..55de1df 100644 --- a/src/app-stats/CMakeLists.txt +++ b/src/app-stats/CMakeLists.txt @@ -6,6 +6,7 @@ SET(DEPS ${DEPS} capi-appfw-app-manager pkgmgr pkgmgr-info + vconf ) FILE(GLOB SRCS *.cpp) diff --git a/src/battery-stats/BatteryMonitor.cpp b/src/battery-stats/BatteryMonitor.cpp index 0bb5097..bee0c26 100644 --- a/src/battery-stats/BatteryMonitor.cpp +++ b/src/battery-stats/BatteryMonitor.cpp @@ -136,6 +136,24 @@ void BatteryMonitor::__chargerChangeCb(device_callback_e type, void* value, void } } +void BatteryMonitor::__timeChangeCb(keynode_t* node, void* userData) +{ + int timeDiff = vconf_keynode_get_int(node); + IF_FAIL_VOID(timeDiff != 0); + + _D("Time changed. Related timestamps will be modified."); + + BatteryMonitor* instance = static_cast(userData); + __needSync = true; + instance->__lastFullTime = instance->__lastFullTime + timeDiff; + instance->__lastHeartAccessTime = instance->__lastHeartAccessTime + timeDiff; + + bool ret = instance->__updateLastInfo(); + IF_FAIL_VOID_TAG(ret, _E, "Failed to update last reset time and last percent time"); + + __instance->__modifyLastCpuUsage(timeDiff); +} + gboolean BatteryMonitor::__timeoutCb(gpointer data) { BatteryMonitor* instance = static_cast(data); @@ -154,6 +172,9 @@ int BatteryMonitor::start() int error = device_add_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb, this); IF_FAIL_RETURN_TAG(error == DEVICE_ERROR_NONE, ERR_OPERATION_FAILED, _E, "Failed to set battery charging change cb"); + error = vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, __timeChangeCb, this); + IF_FAIL_RETURN_TAG(error == VCONF_OK, ERR_OPERATION_FAILED, _E, "Failed to set time changed cb"); + _D("Start timer to request HEART data"); g_timeout_add(HEART_DB_QUERY_INTERVAL, __timeoutCb, this); @@ -170,6 +191,9 @@ int BatteryMonitor::stop() int error = device_remove_callback(DEVICE_CALLBACK_BATTERY_CHARGING, __chargerChangeCb); IF_FAIL_RETURN_TAG(error == DEVICE_ERROR_NONE, ERR_OPERATION_FAILED, _E, "Failed to remove callback for charger status"); + error = vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, __timeChangeCb); + IF_FAIL_RETURN_TAG(error == VCONF_OK, ERR_OPERATION_FAILED, _E, "Failed to remove callback for time changed"); + return ERR_NONE; } @@ -206,13 +230,6 @@ bool BatteryMonitor::__getLastCpuUsageTable(CpuUsageMap* lastHeartCpuLog) bool BatteryMonitor::__processBatteryUsage() { - if (__lastHeartAccessTime > CURRENT_TIME) { - __lastHeartAccessTime = CURRENT_TIME - DEFAULT_TIME_DIFF; - __lastFullTime = CURRENT_TIME - DEFAULT_TIME_DIFF; - __updateLastInfo(); - __dbMgr.executeSync("DELETE FROM " BATTERY_LAST_CPU_USAGE_TABLE, NULL); - } - // Read from heart cpu table bool ret = __heartReader->dbOpen(); IF_FAIL_RETURN_TAG(ret, true, _E, "Failed to open heart db"); @@ -301,7 +318,7 @@ void BatteryMonitor::__removeExpiredLog() bool BatteryMonitor::__updateLastCpuUsageLog(CpuUsageMap& usage) { - _D("Delete all rows from app last times table"); + _D("Delete all rows from last cpu usage table"); __dbMgr.executeSync("DELETE FROM " BATTERY_LAST_CPU_USAGE_TABLE, NULL); IF_FAIL_RETURN_TAG(usage.size(), true, _W, "No data"); @@ -351,3 +368,12 @@ void BatteryMonitor::prepareData() __processBatteryUsage(); } + +void BatteryMonitor::__modifyLastCpuUsage(int timeDiff) +{ + char *query = sqlite3_mprintf("UPDATE Temp_LastCpuUsagePerApp SET Timestamp = Timestamp + (%d)", timeDiff); + __dbMgr.executeSync(query, NULL); + sqlite3_free(query); + + _D("Modified timestamp of LastCpuUsage"); +} diff --git a/src/battery-stats/BatteryMonitor.h b/src/battery-stats/BatteryMonitor.h index f87dc3b..bb6092a 100644 --- a/src/battery-stats/BatteryMonitor.h +++ b/src/battery-stats/BatteryMonitor.h @@ -18,6 +18,7 @@ #define _CONTEXT_BATTERY_MONITOR_H_ #include +#include #include #include "BatteryUsageAnalyzer.h" #include "HeartDbReader.h" @@ -47,8 +48,10 @@ namespace ctx { bool __updateLastCpuUsageLog(CpuUsageMap& usage); bool __getLastCpuUsageTable(CpuUsageMap* lastCpuUsage); void __removeExpiredLog(); + void __modifyLastCpuUsage(int timeDiff); static void __chargerChangeCb(device_callback_e type, void* value, void* userData); + static void __timeChangeCb(keynode_t* node, void* userData); static int __timeoutCb(void* data); static BatteryMonitor* __instance; diff --git a/src/battery-stats/BatteryUsageAnalyzer.cpp b/src/battery-stats/BatteryUsageAnalyzer.cpp index bb08d8b..cdc0d39 100644 --- a/src/battery-stats/BatteryUsageAnalyzer.cpp +++ b/src/battery-stats/BatteryUsageAnalyzer.cpp @@ -64,11 +64,19 @@ void BatteryUsageAnalyzer::calculateBatteryUsage(std::vector& cpuLog, CpuU } } + // Process duplicated logs if (utime - prevUtime == 0 && stime - prevStime == 0) { recentCpuUsageMap[appId].timestamp = timestamp; continue; } + // Process invalid logs + if (utime - prevUtime < 0 || stime - prevStime < 0) + continue; + + if (prevTimestamp > timestamp) + prevTimestamp = timestamp; + Json row; row.set(NULL, BATTERY_APP_ID, appId); row.set(NULL, BATTERY_START_TIME, prevTimestamp); diff --git a/src/battery-stats/CMakeLists.txt b/src/battery-stats/CMakeLists.txt index 00fbdf8..736984f 100644 --- a/src/battery-stats/CMakeLists.txt +++ b/src/battery-stats/CMakeLists.txt @@ -2,6 +2,7 @@ SET(target "${target_prefix}-battery-stats") SET(DEPS ${DEPS} capi-system-device + vconf ) FILE(GLOB SRCS *.cpp) -- 2.7.4 From 98532e1e70504622b7afda1a5284464b3d18fe51 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Tue, 21 Feb 2017 15:12:53 +0900 Subject: [PATCH 10/16] Disable my-place detection Change-Id: I3c506c2fdd4e734f0fdd019be59dcf6f2afa0ff7 Signed-off-by: Mu-Woong Lee --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a137021..babd7c3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,7 +20,7 @@ ADD_SUBDIRECTORY(geofence) ADD_SUBDIRECTORY(headphone) ADD_SUBDIRECTORY(media-stats) ADD_SUBDIRECTORY(message) -ADD_SUBDIRECTORY(my-place) +#ADD_SUBDIRECTORY(my-place) ADD_SUBDIRECTORY(social-stats) ADD_SUBDIRECTORY(wifi) ENDIF("${FEATURES}" STREQUAL "extended") -- 2.7.4 From 86f6d1500a3659a3dacb55646079fa9de67ea51f Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Thu, 30 Mar 2017 13:46:58 +0900 Subject: [PATCH 11/16] Integrate the legacy context-common code and headers (1/2) This patch just imports the legacy code files. Change-Id: I6acd7303a4792faf864ef3e77e84bff35217fe64 Signed-off-by: Mu-Woong Lee --- common/client/CMakeLists.txt | 13 + common/client/DBusClient.cpp | 350 +++++++++++++ common/client/IDBusClientListener.cpp | 23 + common/include/ContextProvider.h | 67 +++ common/include/CustomRegister.h | 48 ++ common/include/DBusClient.h | 69 +++ common/include/DBusSignalWatcher.h | 64 +++ common/include/DBusTypes.h | 53 ++ common/include/DatabaseManager.h | 92 ++++ common/include/ErrorTypes.h | 44 ++ common/include/EventDrivenThread.h | 50 ++ common/include/IContextManager.h | 37 ++ common/include/ICustomRegister.h | 37 ++ common/include/IDBusClientListener.h | 37 ++ common/include/IDBusSignalListener.h | 42 ++ common/include/IDatabaseListener.h | 56 ++ common/include/ITimerListener.h | 39 ++ common/include/Json.h | 122 +++++ common/include/MyPlaceTypes.h | 85 ++++ common/include/ProviderTypes.h | 184 +++++++ common/include/ScopeMutex.h | 35 ++ common/include/SensorRecorderTypes.h | 55 ++ common/include/SharedVars.h | 50 ++ common/include/TimerManager.h | 105 ++++ common/include/TriggerRuleTypes.h | 70 +++ common/include/TriggerTypes.h | 62 +++ common/include/Types.h | 72 +++ common/server/CMakeLists.txt | 13 + common/server/ContextProvider.cpp | 85 ++++ common/server/CustomRegistser.cpp | 45 ++ common/server/DBusSignalWatcher.cpp | 111 ++++ common/server/DatabaseManager.cpp | 105 ++++ common/server/DatabaseThread.cpp | 353 +++++++++++++ common/server/DatabaseThread.h | 80 +++ common/server/EventDrivenThread.cpp | 136 +++++ common/server/IContextManager.cpp | 22 + common/server/IDBusSignalListener.cpp | 21 + common/server/IDatabaseListener.cpp | 21 + common/server/ITimerListener.cpp | 21 + common/server/SharedVars.cpp | 59 +++ common/server/TimerManager.cpp | 231 +++++++++ common/shared/CMakeLists.txt | 12 + common/shared/Json.cpp | 925 ++++++++++++++++++++++++++++++++++ common/shared/MyPlaceTypes.cpp | 45 ++ common/shared/ScopeMutex.cpp | 29 ++ 45 files changed, 4275 insertions(+) create mode 100644 common/client/CMakeLists.txt create mode 100644 common/client/DBusClient.cpp create mode 100644 common/client/IDBusClientListener.cpp create mode 100644 common/include/ContextProvider.h create mode 100644 common/include/CustomRegister.h create mode 100644 common/include/DBusClient.h create mode 100644 common/include/DBusSignalWatcher.h create mode 100644 common/include/DBusTypes.h create mode 100644 common/include/DatabaseManager.h create mode 100644 common/include/ErrorTypes.h create mode 100644 common/include/EventDrivenThread.h create mode 100644 common/include/IContextManager.h create mode 100644 common/include/ICustomRegister.h create mode 100644 common/include/IDBusClientListener.h create mode 100644 common/include/IDBusSignalListener.h create mode 100644 common/include/IDatabaseListener.h create mode 100644 common/include/ITimerListener.h create mode 100644 common/include/Json.h create mode 100644 common/include/MyPlaceTypes.h create mode 100644 common/include/ProviderTypes.h create mode 100644 common/include/ScopeMutex.h create mode 100644 common/include/SensorRecorderTypes.h create mode 100644 common/include/SharedVars.h create mode 100644 common/include/TimerManager.h create mode 100644 common/include/TriggerRuleTypes.h create mode 100644 common/include/TriggerTypes.h create mode 100644 common/include/Types.h create mode 100644 common/server/CMakeLists.txt create mode 100644 common/server/ContextProvider.cpp create mode 100644 common/server/CustomRegistser.cpp create mode 100644 common/server/DBusSignalWatcher.cpp create mode 100644 common/server/DatabaseManager.cpp create mode 100644 common/server/DatabaseThread.cpp create mode 100644 common/server/DatabaseThread.h create mode 100644 common/server/EventDrivenThread.cpp create mode 100644 common/server/IContextManager.cpp create mode 100644 common/server/IDBusSignalListener.cpp create mode 100644 common/server/IDatabaseListener.cpp create mode 100644 common/server/ITimerListener.cpp create mode 100644 common/server/SharedVars.cpp create mode 100644 common/server/TimerManager.cpp create mode 100644 common/shared/CMakeLists.txt create mode 100644 common/shared/Json.cpp create mode 100644 common/shared/MyPlaceTypes.cpp create mode 100644 common/shared/ScopeMutex.cpp diff --git a/common/client/CMakeLists.txt b/common/client/CMakeLists.txt new file mode 100644 index 0000000..0b99d48 --- /dev/null +++ b/common/client/CMakeLists.txt @@ -0,0 +1,13 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-client") + +FILE(GLOB_RECURSE SRCS *.cpp) +MESSAGE("Sources: ${SRCS}") + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${LIB_PKG_LDFLAGS}) +TARGET_LINK_LIBRARIES(${target} ctx-shared) +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/common/client/DBusClient.cpp b/common/client/DBusClient.cpp new file mode 100644 index 0000000..85c9d75 --- /dev/null +++ b/common/client/DBusClient.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +using namespace ctx; + +static const gchar __introspection[] = + "" + " " + " " + " " + " " + " " + " " + " " + " " + ""; + +GDBusConnection *DBusClient::__connection = NULL; +GDBusNodeInfo *DBusClient::__nodeInfo = NULL; +std::atomic_int DBusClient::__instanceCount(0); +std::map DBusClient::__listenerMap; + +SO_EXPORT DBusClient::DBusClient() +{ + ++__instanceCount; +} + +SO_EXPORT DBusClient::~DBusClient() +{ + if (--__instanceCount == 0) + __release(); +} + +void DBusClient::__onMethodCalled(GDBusConnection *conn, const gchar *sender, + const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer userData) +{ + IF_FAIL_VOID_TAG(STR_EQ(name, METHOD_RESPOND), _W, "Invalid method: %s", name); + + gint reqId = 0; + const gchar *subject = NULL; + gint error = 0; + const gchar *data = NULL; + + g_variant_get(param, "(i&si&s)", &reqId, &subject, &error, &data); + _D("[Response] ReqId: %d, Subject: %s, Error: %d", reqId, subject, error); + IF_FAIL_VOID_TAG(subject && data, _W, "Invalid parameter"); + + auto it = __listenerMap.find(subject); + it->second->onPublish(subject, reqId, error, data); + + g_dbus_method_invocation_return_value(invocation, NULL); +} + +bool DBusClient::__init() +{ + static GMutex mutex; + ScopeMutex sm(&mutex); + + if (__connection) + return true; + + GError *gerr = NULL; + gchar *addr = NULL; + GDBusInterfaceVTable vtable; + guint regId; + + __nodeInfo = g_dbus_node_info_new_for_xml(__introspection, NULL); + IF_FAIL_RETURN_TAG(__nodeInfo != NULL, false, _E, "Initialization failed"); + + addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SESSION, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_CATCH_TAG(addr != NULL, _E, "Getting address failed"); + _SD("Address: %s", addr); + + __connection = g_dbus_connection_new_for_address_sync(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, &gerr); + g_free(addr); + HANDLE_GERROR(gerr); + IF_FAIL_CATCH_TAG(__connection != NULL, _E, "Connection failed"); + + vtable.method_call = __onMethodCalled; + vtable.get_property = NULL; + vtable.set_property = NULL; + + regId = g_dbus_connection_register_object(__connection, DBUS_PATH, + __nodeInfo->interfaces[0], &vtable, NULL, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_CATCH_TAG(regId > 0, _E, "Object registration failed"); + + _I("DBus connection established"); + _D("DBus name: %s", g_dbus_connection_get_unique_name(__connection)); + return true; + +CATCH: + __release(); + return false; +} + +void DBusClient::__release() +{ + if (__connection) { + g_dbus_connection_flush_sync(__connection, NULL, NULL); + g_dbus_connection_close_sync(__connection, NULL, NULL); + g_object_unref(__connection); + __connection = NULL; + } + + if (__nodeInfo) { + g_dbus_node_info_unref(__nodeInfo); + __nodeInfo = NULL; + } + + _I("DBus connection released"); +} + +int DBusClient::__request(int type, int reqId, const char *subject, const char *input, + std::string *result, std::string *outputData) +{ + _D("Requesting: %d, %d, %s", type, reqId, subject); + + if (input == NULL) + input = EMPTY_JSON_OBJECT; + + GVariant *param = g_variant_new("(isiss)", type, "", reqId, subject, input); + IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + GVariant *response = g_dbus_connection_call_sync(__connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err); + HANDLE_GERROR(err); + IF_FAIL_RETURN_TAG(response, ERR_OPERATION_FAILED, _E, "Method call failed"); + + gint error = ERR_OPERATION_FAILED; + const gchar *resultStr = NULL; + const gchar *dataStr = NULL; + + g_variant_get(response, "(i&s&s)", &error, &resultStr, &dataStr); + + if (result && resultStr) + *result = resultStr; + + if (outputData && dataStr) + *outputData = dataStr; + + g_variant_unref(response); + + return error; +} + +int DBusClient::__request(int type, int reqId, const char* subject, const char* input) +{ + _D("Requesting: %d, %d, %s", type, reqId, subject); + + if (input == NULL) + input = EMPTY_JSON_OBJECT; + + GVariant *param = g_variant_new("(isiss)", type, "", reqId, subject, input); + IF_FAIL_RETURN_TAG(param, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed"); + + GError *err = NULL; + g_dbus_connection_call(__connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + METHOD_REQUEST, param, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, NULL, &err); + + if (err) { + HANDLE_GERROR(err); + return ERR_OPERATION_FAILED; + } + + return ERR_NONE; +} + +int DBusClient::__generateReqId() +{ + static GMutex mutex; + static int reqId = 0; + + ctx::ScopeMutex sm(&mutex); + + /* Overflow handling */ + if (++reqId < 0) + reqId = 1; + + return reqId; +} + +SO_EXPORT void DBusClient::addListener(std::string subject, IDBusClientListener *listener) +{ + _D("Registering the listener for '%s'", subject.c_str()); + + static GMutex mutex; + ctx::ScopeMutex sm(&mutex); + + __listenerMap[subject] = listener; +} + +SO_EXPORT int DBusClient::isSupported(std::string subject) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + return __request(REQ_SUPPORT, __generateReqId(), subject.c_str(), NULL, NULL, NULL); +} + +SO_EXPORT int DBusClient::subscribe(std::string subject, Json option, int *reqId, Json *result) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + ASSERT_NOT_NULL(reqId); + + *reqId = __generateReqId(); + + _I("[Subscribe] ReqId: %d, Subject: %s", *reqId, subject.c_str()); + + std::string resultStr; + int error = __request(REQ_SUBSCRIBE, *reqId, subject.c_str(), option.str().c_str(), &resultStr, NULL); + + if (result) + *result = resultStr; + + _D("Error: %#x", error); + _SD("Result: %s", resultStr.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::unsubscribe(std::string subject, int reqId) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + _I("[Unsubscribe] ReqId: %d, Subject: %s", reqId, subject.c_str()); + + return __request(REQ_UNSUBSCRIBE, reqId, subject.c_str(), NULL, NULL, NULL); +} + +SO_EXPORT int DBusClient::read(std::string subject, Json option, int *reqId, Json *result) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + ASSERT_NOT_NULL(reqId); + + *reqId = __generateReqId(); + + _I("[Read] ReqId: %d, Subject: %s", *reqId, subject.c_str()); + + std::string resultStr; + int error = __request(REQ_READ, *reqId, subject.c_str(), option.str().c_str(), &resultStr, NULL); + + if (result) + *result = resultStr; + + _D("Error: %#x", error); + _SD("Result: %s", resultStr.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::readSync(std::string subject, Json option, int *reqId, Json *outputData) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + ASSERT_NOT_NULL(reqId); + ASSERT_NOT_NULL(outputData); + + *reqId = __generateReqId(); + + _I("[ReadSync] ReqId: %d, Subject: %s", *reqId, subject.c_str()); + + std::string output; + int error = __request(REQ_READ_SYNC, *reqId, subject.c_str(), option.str().c_str(), NULL, &output); + + *outputData = output; + + _D("Error: %#x", error); + _SD("Data: %s", output.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::write(std::string subject, Json inputData) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + int reqId = __generateReqId(); + + _I("[Write] ReqId: %d, Subject: %s", reqId, subject.c_str()); + _SD("Data: %s", inputData.str().c_str()); + + int error = __request(REQ_WRITE, reqId, subject.c_str(), inputData.str().c_str()); + _D("Error: %#x", error); + + return error; +} + +SO_EXPORT int DBusClient::write(std::string subject, Json inputData, Json *result) +{ + IF_FAIL_RETURN(__init(), ERR_OPERATION_FAILED); + + int reqId = __generateReqId(); + + _I("[Write with reply] ReqId: %d, Subject: %s", reqId, subject.c_str()); + _SD("Data: %s", inputData.str().c_str()); + + std::string resultStr; + int error = __request(REQ_WRITE, reqId, subject.c_str(), inputData.str().c_str(), &resultStr, NULL); + + if (result) + *result = resultStr; + + _D("Error: %#x", error); + _SD("Result: %s", resultStr.c_str()); + + return error; +} + +SO_EXPORT int DBusClient::call(const char *method) +{ + int ret = ERR_NONE; + GError *err = NULL; + + GVariant *response = g_dbus_connection_call_sync(__connection, DBUS_DEST, DBUS_PATH, DBUS_IFACE, + method, NULL, NULL, G_DBUS_CALL_FLAGS_NONE, DBUS_TIMEOUT, NULL, &err); + + if (response) { + g_variant_unref(response); + return ERR_NONE; + } + + ret = ERR_OPERATION_FAILED; + if (err->code == G_DBUS_ERROR_ACCESS_DENIED) + ret = ERR_PERMISSION_DENIED; + + HANDLE_GERROR(err); + return ret; +} diff --git a/common/client/IDBusClientListener.cpp b/common/client/IDBusClientListener.cpp new file mode 100644 index 0000000..0da37b2 --- /dev/null +++ b/common/client/IDBusClientListener.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +using namespace ctx; + +IDBusClientListener::~IDBusClientListener() +{ +} diff --git a/common/include/ContextProvider.h b/common/include/ContextProvider.h new file mode 100644 index 0000000..2d89262 --- /dev/null +++ b/common/include/ContextProvider.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_CONTEXT_PROVIDER_H_ +#define _CONTEXT_CONTEXT_PROVIDER_H_ + +#include +#include +#include + +#define OPS_SUBSCRIBE 1 +#define OPS_READ 2 +#define OPS_WRITE 4 + +namespace ctx { + + class IContextManager; + + class SO_EXPORT ContextProvider { + public: + virtual ~ContextProvider(); + + const char* getSubject(); + + virtual bool isSupported(); + virtual int subscribe(Json option, Json *requestResult); + virtual int unsubscribe(Json option); + virtual int read(Json option, Json *requestResult); + virtual int write(Json data, Json *requestResult); + + virtual void getPrivilege(std::vector &privilege); + + virtual bool unloadable(); + + bool publish(Json option, int error, Json dataUpdated); + bool replyToRead(Json option, int error, Json dataRead); + + protected: + ContextProvider(const char *subject); + + private: + static void __setContextManager(IContextManager *contextMgr); + + static IContextManager *__contextMgr; + + const char *__subject; + + friend class ContextManager; + + }; /* class ContextProvider */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_CONTEXT_PROVIDER_H_ */ diff --git a/common/include/CustomRegister.h b/common/include/CustomRegister.h new file mode 100644 index 0000000..5134613 --- /dev/null +++ b/common/include/CustomRegister.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_CUSTOM_REGISTER_H_ +#define _CONTEXT_CUSTOM_REGISTER_H_ + +#include +#include + +namespace ctx { + + class ICustomRegister; + + class SO_EXPORT CustomRegister { + public: + virtual ~CustomRegister(); + + bool registerCustomProvider(const char* subject, int operation, Json attribute, Json option, const char* owner = NULL); + bool unregisterCustomProvider(const char* subject); + + protected: + CustomRegister(); + + private: + static void __setCustomRegister(ICustomRegister *customRegister); + + static ICustomRegister *__customRegister; + + friend class ContextManager; + + }; /* class CustomRegister */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_CUSTOM_REGISTER_H_ */ diff --git a/common/include/DBusClient.h b/common/include/DBusClient.h new file mode 100644 index 0000000..c865e80 --- /dev/null +++ b/common/include/DBusClient.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_DBUS_CLIENT_H__ +#define __CONTEXT_DBUS_CLIENT_H__ + +#include +#include +#include +#include +#include +#include + +namespace ctx { + + class DBusClient { + public: + DBusClient(); + ~DBusClient(); + + void addListener(std::string subject, IDBusClientListener *listener); + + int isSupported(std::string subject); + + int subscribe(std::string subject, Json option, int *reqId, Json *result); + int unsubscribe(std::string subject, int reqId); + int read(std::string subject, Json option, int *reqId, Json *result); + int readSync(std::string subject, Json option, int *reqId, Json *outputData); + int write(std::string subject, Json inputData); + int write(std::string subject, Json inputData, Json *result); + + int call(const char *method); + + private: + static void __onMethodCalled(GDBusConnection *conn, const gchar *sender, + const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, GDBusMethodInvocation *invocation, gpointer userData); + + bool __init(); + void __release(); + int __request(int type, int reqId, const char *subject, const char *input, + std::string *result, std::string *outputData); + int __request(int type, int reqId, const char *subject, const char *input); + int __generateReqId(); + + + static GDBusConnection *__connection; + static GDBusNodeInfo *__nodeInfo; + static std::atomic_int __instanceCount; + static std::map __listenerMap; + + }; /* class ctx::DBusClient */ + +} /* namespace ctx */ + +#endif // __CONTEXT_DBUS_CLIENT_H__ diff --git a/common/include/DBusSignalWatcher.h b/common/include/DBusSignalWatcher.h new file mode 100644 index 0000000..6b035ed --- /dev/null +++ b/common/include/DBusSignalWatcher.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DBUS_SIGNAL_WATCHER_H_ +#define _CONTEXT_DBUS_SIGNAL_WATCHER_H_ + +#include +#include +#include + +namespace ctx { + + enum class DBusType { + SYSTEM, + SESSION + }; + + class DBusSignalWatcher { + public: + DBusSignalWatcher(DBusType type); + ~DBusSignalWatcher(); + + /** + * @brief Subscribes to signals. + * @param[in] sender Sensor name to match on. NULL to listen from all senders. + * @param[in] path Object path to match on. NULL to match on all object paths. + * @param[in] iface D-Bus interface name to match on. NULL to match on all interfaces. + * @param[in] name D-Bus signal name to match on. NULL to match on all signals. + * @param[in] listener Listener object to receive matching signals. + * @return A subscription identifier that can be used with signal_unsubscribe(). + * If failed, a negative value. + */ + int64_t watch(const char *sender, const char *path, const char *iface, const char *name, IDBusSignalListener *listener); + void unwatch(int64_t signal_id); + + private: + void __openBus(GBusType type, GDBusConnection *&bus); + void __closeBus(GDBusConnection *&bus); + + static GMutex __mutex; + static unsigned int __systemBusCnt; + static unsigned int __sessionBusCnt; + static GDBusConnection *__systemBus; + static GDBusConnection *__sessionBus; + + DBusType __busType; + }; + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_DBUS_SIGNAL_WATCHER_H_ */ diff --git a/common/include/DBusTypes.h b/common/include/DBusTypes.h new file mode 100644 index 0000000..1921e30 --- /dev/null +++ b/common/include/DBusTypes.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DBUS_TYPES_H_ +#define _CONTEXT_DBUS_TYPES_H_ + +#define DBUS_DEST "org.tizen.context" +#define DBUS_PATH "/org/tizen/context" +#define DBUS_IFACE "org.tizen.context" +#define DBUS_TIMEOUT 3000 + +#define METHOD_REQUEST "Request" +#define METHOD_RESPOND "Respond" +#define SIGNAL_LAUNCHED "Launched" + +#define METHOD_CHK_PRIV "ChkPriv" +#define METHOD_CHK_PRIV_APPLAUNCH METHOD_CHK_PRIV "AppLaunch" +#define METHOD_CHK_PRIV_CALL METHOD_CHK_PRIV "Call" +#define METHOD_CHK_PRIV_NOTIFICATION METHOD_CHK_PRIV "Notification" + +#define ARG_REQTYPE "type" +#define ARG_COOKIE "cookie" +#define ARG_REQID "req_id" +#define ARG_SUBJECT "subject" +#define ARG_INPUT "input" + +#define ARG_RESULT_ERR "r_err" +#define ARG_RESULT_ADD "r_add" +#define ARG_OUTPUT "output" + +enum RequestType { + REQ_SUBSCRIBE = 1, + REQ_UNSUBSCRIBE, + REQ_READ, + REQ_READ_SYNC, + REQ_WRITE, + REQ_SUPPORT, +}; + +#endif /* _CONTEXT_DBUS_TYPES_H_ */ diff --git a/common/include/DatabaseManager.h b/common/include/DatabaseManager.h new file mode 100644 index 0000000..a0fe0ad --- /dev/null +++ b/common/include/DatabaseManager.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DATABASE_MANAGER_H_ +#define _CONTEXT_DATABASE_MANAGER_H_ + +#include + +namespace ctx { + + class DatabaseManager { + public: + DatabaseManager(); + ~DatabaseManager(); + + /** + * @brief Creates a table if not exists. Async. + * @details The column @c rowId is created by default, thus do not use the same column name. + * It is the primary of the auto-increment integer type. + * @param[in] queryId This number will be returned through IDatabaseListener::onTableCreated(). + * @param[in] tableName A table name to be created. + * @param[in] columns Columns. In SQL format. INTEGER, REAL, and TEXT types are allowed. + * @param[in] option Additional options. Allows NULL. + * @param[in] listener A listener object to receive the result. Allows NULL. + */ + bool createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option = NULL, IDatabaseListener *listener = NULL); + + /** + * @brief Inserts a record to a table. Async. + * @param[in] queryId This number will be returned through IDatabaseListener::onInserted(). + * @param[in] tableName A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[in] listener A listener object to receive the result. Allows NULL. + */ + bool insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener = NULL); + + /** + * @brief Executes a SQL query. Async. + * @param[in] queryId This number will be returned through IDatabaseListener::onExecuted(). + * @param[in] query A query to be executed. + * @param[in] listener A listener object to receive the result. + */ + bool execute(unsigned int queryId, const char *query, IDatabaseListener *listener = NULL); + + /** + * @brief creates a table if not exists. Async. + * @param[in] tableName A table name to be created. + * @param[in] columns Columns. In SQL format. INTEGER, REAL, and TEXT types are allowed. + * @param[in] option Additional options. Allows NULL. + */ + bool createTableSync(const char *tableName, const char *columns, const char *option = NULL); + + /** + * @brief Inserts a record to a table. Sync. + * @attention This blocks the current thread. + * @param[in] tableName A table name in which the record is inserted. + * @param[in] record A json object containing key, value pairs. + * @param[out] rowId The row id of the inserted record. If fails, a negative integer. + */ + bool insertSync(const char *tableName, Json record, int64_t *rowId); + + /** + * @brief Executes a SQL query. Sync. + * @attention This blocks the current thread. + * @param[in] query A query to be executed. + * @param[out] records Query result. + */ + bool executeSync(const char *query, std::vector *records); + + private: + static bool __init(); + static void __release(); + + friend class Server; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_DATABASE_MANAGER_H_ */ diff --git a/common/include/ErrorTypes.h b/common/include/ErrorTypes.h new file mode 100644 index 0000000..1e2e81c --- /dev/null +++ b/common/include/ErrorTypes.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_ERROR_TYPES_H_ +#define _CONTEXT_ERROR_TYPES_H_ + +#include + +/* Internal Error Codes + * Please define the necessary error codes here. + * Note that, these error codes must be aligned with the error enums defined in all API headers. + */ +#define ERR_NONE TIZEN_ERROR_NONE +#define ERR_INVALID_PARAMETER TIZEN_ERROR_INVALID_PARAMETER +#define ERR_INVALID_OPERATION TIZEN_ERROR_INVALID_OPERATION +#define ERR_OUT_OF_MEMORY TIZEN_ERROR_OUT_OF_MEMORY +#define ERR_PERMISSION_DENIED TIZEN_ERROR_PERMISSION_DENIED +#define ERR_NOT_SUPPORTED TIZEN_ERROR_NOT_SUPPORTED +#define ERR_NO_DATA TIZEN_ERROR_NO_DATA +#define ERR_ALREADY_STARTED (TIZEN_ERROR_CONTEXT | 0x01) +#define ERR_NOT_STARTED (TIZEN_ERROR_CONTEXT | 0x02) +#define ERR_OUT_OF_RANGE (TIZEN_ERROR_CONTEXT | 0x03) +#define ERR_OPERATION_FAILED (TIZEN_ERROR_CONTEXT | 0x04) +#define ERR_RULE_ENABLED (TIZEN_ERROR_CONTEXT | 0x05) +#define ERR_RULE_NOT_ENABLED (TIZEN_ERROR_CONTEXT | 0x06) +#define ERR_INVALID_RULE (TIZEN_ERROR_CONTEXT | 0x07) +#define ERR_RULE_NOT_EXIST (TIZEN_ERROR_CONTEXT | 0x08) +#define ERR_DATA_EXIST (TIZEN_ERROR_CONTEXT | 0X09) +#define ERR_INVALID_DATA (TIZEN_ERROR_CONTEXT | 0X0a) + +#endif /* _CONTEXT_ERROR_TYPES_H_ */ diff --git a/common/include/EventDrivenThread.h b/common/include/EventDrivenThread.h new file mode 100644 index 0000000..54b6efa --- /dev/null +++ b/common/include/EventDrivenThread.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _EVENT_DRIVEN_THREAD_H_ +#define _EVENT_DRIVEN_THREAD_H_ + +#include +#include + +class SO_EXPORT EventDrivenThread { + + typedef struct thread_info_s* thread_info_t; + +public: + virtual ~EventDrivenThread(); + + bool start(); + bool stop(); + bool isRunning(); + +protected: + EventDrivenThread(); + + virtual void onEvent(int type, void* data) = 0; + + bool pushEvent(int type, void* data); + +private: + static gpointer __threadFunc(gpointer data); + + void __run(); + + thread_info_t __threadInfo; + +}; /* class EventDrivenThread */ + +#endif /* _EVENT_DRIVEN_THREAD_H_ */ diff --git a/common/include/IContextManager.h b/common/include/IContextManager.h new file mode 100644 index 0000000..4bb2561 --- /dev/null +++ b/common/include/IContextManager.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_CONTEXT_MANAGER_H_ +#define _CONTEXT_I_CONTEXT_MANAGER_H_ + +#include +#include + +namespace ctx { + + class ContextProvider; + + class SO_EXPORT IContextManager { + public: + virtual ~IContextManager(); + + virtual bool publish(const char *subject, Json &option, int error, Json &dataUpdated) = 0; + virtual bool replyToRead(const char *subject, Json &option, int error, Json &dataRead) = 0; + }; /* class IContextManager */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_CONTEXT_MANAGER_H_ */ diff --git a/common/include/ICustomRegister.h b/common/include/ICustomRegister.h new file mode 100644 index 0000000..eca3596 --- /dev/null +++ b/common/include/ICustomRegister.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_CUSTOM_REGISTER_H_ +#define _CONTEXT_I_CUSTOM_REGISTER_H_ + +#include +#include + +namespace ctx { + + class CustomRegister; + + class SO_EXPORT ICustomRegister { + public: + virtual ~ICustomRegister(){}; + + virtual bool registerCustomProvider(const char *subject, int operation, Json &attribute, Json &option, const char* owner = NULL) = 0; + virtual bool unregisterCustomProvider(const char *subject) = 0; + }; /* class ICustomRegister */ + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_CUSTOM_REGISTER_H_ */ diff --git a/common/include/IDBusClientListener.h b/common/include/IDBusClientListener.h new file mode 100644 index 0000000..1463425 --- /dev/null +++ b/common/include/IDBusClientListener.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_DBUS_CLIENT_LISTENER_H_ +#define _CONTEXT_I_DBUS_CLIENT_LISTENER_H_ + +#ifndef SO_EXPORT +#define SO_EXPORT __attribute__ ((visibility("default"))) +#endif + +#include +#include + +namespace ctx { + + class SO_EXPORT IDBusClientListener { + public: + virtual ~IDBusClientListener(); + virtual void onPublish(std::string subject, int reqId, int error, Json event) = 0; + }; + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_I_DBUS_CLIENT_LISTENER_H_ */ diff --git a/common/include/IDBusSignalListener.h b/common/include/IDBusSignalListener.h new file mode 100644 index 0000000..ed70efe --- /dev/null +++ b/common/include/IDBusSignalListener.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_DBUS_SIGNAL_LISTENER_H_ +#define _CONTEXT_I_DBUS_SIGNAL_LISTENER_H_ + +#include +#include + +namespace ctx { + + class SO_EXPORT IDBusSignalListener { + public: + virtual ~IDBusSignalListener(); + + /** + * @brief Called when receiving a signal. + * @param[in] sender The unique bus name of the sender of the signal. + * @param[in] path The object path that the signal was emitted on. + * @param[in] iface The name of the interface. + * @param[in] name The name of the signal. + * @param[in] param A GVariant tuple with parameters of the signal. + */ + virtual void onSignal(const char *sender, const char *path, const char *iface, const char *name, GVariant *param) = 0; + }; + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_I_DBUS_SIGNAL_LISTENER_H_ */ diff --git a/common/include/IDatabaseListener.h b/common/include/IDatabaseListener.h new file mode 100644 index 0000000..96205cb --- /dev/null +++ b/common/include/IDatabaseListener.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_DATABASE_LISTENER_H_ +#define _CONTEXT_I_DATABASE_LISTENER_H_ + +#include +#include +#include + +namespace ctx { + + class SO_EXPORT IDatabaseListener { + public: + virtual ~IDatabaseListener(); + + /** + * @brief Called when a table creation is done. + * @param[in] queryId The query id passed through ctx::DatabaseManager::createTable(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + */ + virtual void onTableCreated(unsigned int queryId, int error) = 0; + + /** + * @brief Called when a record insertion is done. + * @param[in] queryId The query id passed through ctx::DatabaseManager::insert(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] rowId The row id of the inserted record. + */ + virtual void onInserted(unsigned int queryId, int error, int64_t rowId) = 0; + + /** + * @brief Called when a query execution is done. + * @param[in] queryId The query id passed through ctx::DatabaseManager::execute(). + * @param[in] error Error code. If success, 0. Otherwise, a negative value. + * @param[in] records Data records retreived. + */ + virtual void onExecuted(unsigned int queryId, int error, std::vector& records) = 0; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_DATABASE_LISTENER_H_ */ diff --git a/common/include/ITimerListener.h b/common/include/ITimerListener.h new file mode 100644 index 0000000..a8bbe9f --- /dev/null +++ b/common/include/ITimerListener.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_I_TIMER_LISTENER_H_ +#define _CONTEXT_I_TIMER_LISTENER_H_ + +#include + +namespace ctx { + + class SO_EXPORT ITimerListener { + public: + virtual ~ITimerListener(); + + /** + * @brief Called when a timer is expired. + * @param[in] timer_id The expired timers' ID + * @return @c true, if the timer needs to be repeated.@n + * @c false, if the timer does not need to be repeated anymore. + */ + virtual bool onTimerExpired(int timerId) = 0; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_I_TIMER_LISTENER_H_ */ diff --git a/common/include/Json.h b/common/include/Json.h new file mode 100644 index 0000000..31a9d11 --- /dev/null +++ b/common/include/Json.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_JSON_H_ +#define _CONTEXT_JSON_H_ + +#include +#include +#include +#include + +#define _J(cmt, jobj) \ +do { \ + _SD("%s: %s", (cmt), jobj.str().c_str()); \ +} while (0) + +#define EMPTY_JSON_OBJECT "{}" + +namespace ctx { + + class Json { + public: + Json(); + Json(const char *s); + Json(const std::string &s); + + /* This Json(const Json &j) only copies the reference to the underlying Json node. + * Therefore, changes applied to a Json object affect the other. + * If you need to create a 'real' copy of a Json, which can be manipulated separately, + * utilize the str() function, e.g., ctx::Json copy(original.str()); + */ + Json(const Json &j); + + ~Json(); + + Json& operator=(const char *s); + Json& operator=(const std::string &s); + + /* This operator=(const Json &j) only copies the reference to the underlying Json node. + * Therefore, changes applied to a Json object affect the other. + * If you need to create a 'real' copy of a Json, which can be manipulated separately, + * utilize the str() function, e.g., ctx::Json copy = original.str(); + */ + Json& operator=(const Json &j); + + bool operator==(const Json &rhs); + bool operator!=(const Json &rhs); + + std::string str(); + + bool getKeys(std::list *list); + bool valid(); + + bool set(const char *path, const char *key, Json &val); + bool set(const char *path, const char *key, int val); + bool set(const char *path, const char *key, int64_t val); + bool set(const char *path, const char *key, double val); + bool set(const char *path, const char *key, std::string val); + bool set(const char *path, const char *key, GVariant *val); + + bool get(const char *path, const char *key, Json *val); + bool get(const char *path, const char *key, int *val); + bool get(const char *path, const char *key, int64_t *val); + bool get(const char *path, const char *key, double *val); + bool get(const char *path, const char *key, std::string *val); + bool get(const char *path, const char *key, GVariant **val); + + bool remove(const char *path, const char *key); + + /* Array operations */ + int getSize(const char *path, const char *key); + + bool append(const char *path, const char *key, Json &val); + bool append(const char *path, const char *key, int val); + bool append(const char *path, const char *key, int64_t val); + bool append(const char *path, const char *key, double val); + bool append(const char *path, const char *key, std::string val); + + bool setAt(const char *path, const char *key, int index, Json &val); + bool setAt(const char *path, const char *key, int index, int val); + bool setAt(const char *path, const char *key, int index, int64_t val); + bool setAt(const char *path, const char *key, int index, double val); + bool setAt(const char *path, const char *key, int index, std::string val); + + bool getAt(const char *path, const char *key, int index, Json *val); + bool getAt(const char *path, const char *key, int index, int *val); + bool getAt(const char *path, const char *key, int index, int64_t *val); + bool getAt(const char *path, const char *key, int index, double *val); + bool getAt(const char *path, const char *key, int index, std::string *val); + + private: + typedef struct _JsonNode json_node_t; + json_node_t *__jsonNode; + + void __parse(const char *s); + void __release(); + char* __strDup(); + + /* For json vs json comparison */ + bool __getMembers(json_node_t *node, std::list &list); + bool __nodeEq(json_node_t *lhs, json_node_t *rhs); + bool __valueEq(json_node_t *lhs, json_node_t *rhs); + bool __objectEq(json_node_t *lhs, json_node_t *rhs); + bool __arrayEq(json_node_t *lhs, json_node_t *rhs); + }; + +} /* namespace ctx */ + +#endif // _CONTEXT_JSON_H_ diff --git a/common/include/MyPlaceTypes.h b/common/include/MyPlaceTypes.h new file mode 100644 index 0000000..2593649 --- /dev/null +++ b/common/include/MyPlaceTypes.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_MYPLACE_TYPES_H_ +#define _CONTEXT_MYPLACE_TYPES_H_ + +#include +#include +#include +#include + +#define PLACE_DETECTION_SUBJECT SUBJ_PLACE_DETECTION + +#define PLACE_DETECTION_REQUEST "Request" +#define PLACE_DETECTION_REQUEST_CONSENT "UserConsent" +#define PLACE_DETECTION_REQUEST_LIST "PlacesList" + +#define MYPLACE_SETTING_VALUE_TRUE "true" +#define MYPLACE_SETTING_VALUE_FALSE "false" + +#define PLACE_DATA_READ "PlacesList" +#define PLACE_CATEG_ID "CategId" +#define PLACE_CATEG_CONFIDENCE "CategConfidence" +#define PLACE_NAME "Name" +#define PLACE_LOCATION "Location" +#define PLACE_LOCATION_LATITUDE "Latitude" +#define PLACE_LOCATION_LONGITUDE "Longitude" +#define PLACE_LOCATION_ACCURACY "Accuracy" +#define PLACE_WIFI_APS "WifiAPs" +#define PLACE_WIFI_AP_MAC "Mac" +#define PLACE_WIFI_AP_NETWORK_NAME "Network" +#define PLACE_CREATE_DATE "CreateDate" + +namespace ctx { + + enum PlaceCategId { + PLACE_CATEG_ID_NONE = 0, + PLACE_CATEG_ID_HOME = 1, + PLACE_CATEG_ID_WORK = 2, + PLACE_CATEG_ID_OTHER = 3 + }; + + struct Location { + double latitude; + double longitude; + double accuracy; // [m] + + Location(double latitude_ = 0.0, double longitude_ = 0.0, double accuracy_ = -1.0) + : latitude(latitude_), longitude(longitude_), accuracy(accuracy_) {} + + }; /* struct Location */ + + typedef float confidence_t; + + class Place { + + public: + PlaceCategId categId; // category of a place (work/home/other) + confidence_t categConfidence; // confidence of the above category - between [0,1] + std::string name; // for now: "work"/"home"/"other" + bool locationValid; + Location location; // makes sense if locationValid == true; + std::map wifiAps; // WiFi APs MAC addresses to corresponding network name map + time_t createDate; // The last update time of this place + + }; /* class Place */ + + bool operator==(const Place &p1, const Place &p2); + +} /* namespace ctx */ + +#endif /* End of _CONTEXT_MYPLACE_TYPES_H_ */ diff --git a/common/include/ProviderTypes.h b/common/include/ProviderTypes.h new file mode 100644 index 0000000..d720922 --- /dev/null +++ b/common/include/ProviderTypes.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_PROVIDER_TYPES_H_ +#define _CONTEXT_PROVIDER_TYPES_H_ + +/* Privileges */ +#define PRIV_ALARM "alarm.set" +#define PRIV_NETWORK "network.get" +#define PRIV_TELEPHONY "telephony" +#define PRIV_MESSAGE "message.read" +#define PRIV_CONTACT "contact.read" +#define PRIV_LOCATION "location" +#define PRIV_APP_HISTORY "apphistory.read" +#define PRIV_MEDIA_HISTORY "mediahistory.read" +#define PRIV_CALL_HISTORY "callhistory.read" + + +/* FW-wide Data Logger Parameters */ +#define LOG_RETENTION_PERIOD 7776000 /* 90 days in secs */ + + +/* FW-wide Default Values */ +#define DEFAULT_TIME_SPAN 30 +#define DEFAULT_LIMIT 10 + + +/* Subjects */ +/* TODO: Cleanup the below namings */ +#define SUBJ_STATE_BATTERY "system/battery" +#define SUBJ_STATE_CHARGER "system/charger" +#define SUBJ_STATE_HEADPHONE "system/headphone" +#define SUBJ_STATE_WIFI "system/wifi" +#define SUBJ_STATE_USB "system/usb" +#define SUBJ_STATE_GPS "system/gps" +#define SUBJ_STATE_PSMODE "system/psmode" +#define SUBJ_STATE_ALARM "device/alarm" +#define SUBJ_STATE_TIME "device/time" + +#define SUBJ_STATE_CALL "social/call" +#define SUBJ_STATE_EMAIL "social/email" +#define SUBJ_STATE_MESSAGE "social/message" +#define SUBJ_STATE_CONTACTS "social/contacts" + +#define SUBJ_ACTIVITY "activity/" +#define SUBJ_ACTIVITY_IN_VEHICLE SUBJ_ACTIVITY "in_vehicle" +#define SUBJ_ACTIVITY_RUNNING SUBJ_ACTIVITY "running" +#define SUBJ_ACTIVITY_STATIONARY SUBJ_ACTIVITY "stationary" +#define SUBJ_ACTIVITY_WALKING SUBJ_ACTIVITY "walking" + +#define SUBJ_APP_STATS "stats/app/" +#define SUBJ_APP_LOGGER SUBJ_APP_STATS "logger" +#define SUBJ_APP_RECENTLY_USED SUBJ_APP_STATS "recently" +#define SUBJ_APP_FREQUENTLY_USED SUBJ_APP_STATS "often" +#define SUBJ_APP_RARELY_USED SUBJ_APP_STATS "rarely" +#define SUBJ_APP_PEAK_TIME SUBJ_APP_STATS "peak_time" +#define SUBJ_APP_COMMON_SETTING SUBJ_APP_STATS "setting" +#define SUBJ_APP_FREQUENCY SUBJ_APP_STATS "frequency" + +#define SUBJ_BATTERY_STATS "stats/battery/" +#define SUBJ_BATTERY_LOGGER SUBJ_BATTERY_STATS "logger" +#define SUBJ_BATTERY_USAGE SUBJ_BATTERY_STATS "history" +#define SUBJ_BATTERY_RECENT_USAGE SUBJ_BATTERY_STATS "since_last_charge" + +#define SUBJ_MEDIA_LOGGER "stats/media/logger" +#define SUBJ_MUSIC_STATS "stats/music/" +#define SUBJ_MUSIC_PEAK_TIME SUBJ_MUSIC_STATS "peak_time" +#define SUBJ_MUSIC_COMMON_SETTING SUBJ_MUSIC_STATS "setting" +#define SUBJ_MUSIC_FREQUENCY SUBJ_MUSIC_STATS "frequency" +#define SUBJ_VIDEO_STATS "stats/video/" +#define SUBJ_VIDEO_PEAK_TIME SUBJ_VIDEO_STATS "peak_time" +#define SUBJ_VIDEO_COMMON_SETTING SUBJ_VIDEO_STATS "setting" +#define SUBJ_VIDEO_FREQUENCY SUBJ_VIDEO_STATS "frequency" + +#define SUBJ_SOCIAL_STATS "stats/contact/" +#define SUBJ_SOCIAL_FREQ_ADDRESS SUBJ_SOCIAL_STATS "often" +#define SUBJ_SOCIAL_FREQUENCY SUBJ_SOCIAL_STATS "frequency" + +#define SUBJ_PLACE_GEOFENCE "place/geofence" +#define SUBJ_PLACE_DETECTION "place/myplace" + +#define SUBJ_CUSTOM "custom" + +/* Data & Option Keys */ +#define KEY_CLIENT_PKG_ID "_ClientPkgId_" /* Special key for internal use */ +#define KEY_QUERY_RESULT "QueryResult" +#define KEY_RESULT_SIZE "ResultSize" +#define KEY_COL_ROW_ID "rowId" +#define KEY_TIME_SPAN "TimeSpan" +#define KEY_START_TIME "StartTime" +#define KEY_END_TIME "EndTime" +#define KEY_LAST_TIME "LastTime" +#define KEY_TOTAL_COUNT "TotalCount" +#define KEY_TOTAL_AMOUNT "TotalAmount" +#define KEY_AVERAGE_COUNT "AvgCount" +#define KEY_DURATION "Duration" +#define KEY_TOTAL_DURATION "TotalDuration" +#define KEY_DAY_OF_WEEK "DayOfWeek" +#define KEY_HOUR_OF_DAY "HourOfDay" +#define KEY_TIME_OF_DAY "TimeOfDay" +#define KEY_TOTAL_COUNT "TotalCount" +#define KEY_APP_ID "AppId" +#define KEY_PKG_ID "PkgId" +#define KEY_AUDIO_JACK "AudioJack" +#define KEY_SYSTEM_VOLUME "SystemVolume" +#define KEY_MEDIA_VOLUME "MediaVolume" +#define KEY_BSSID "BSSID" +#define KEY_UNIV_TIME "UTC" +#define KEY_LOCAL_TIME "LocalTime" +#define KEY_RANK "Rank" +#define KEY_COMMUNICATION_TYPE "CommunicationType" +#define KEY_USED_TIME "UsedTime" + +#define KEY_EVENT "Event" +#define KEY_STATE "State" +#define KEY_TYPE "Type" +#define KEY_LEVEL "Level" +#define KEY_ACCURACY "Accuracy" +#define KEY_BSSID "BSSID" +#define KEY_MEDIUM "Medium" +#define KEY_ADDRESS "Address" +#define KEY_IS_CONNECTED "IsConnected" +#define KEY_IS_ENABLED "IsEnabled" +#define KEY_IS_CHARGING "IsCharging" +#define KEY_DETECTED "Detected" +#define KEY_DAY_OF_MONTH "DayOfMonth" +#define KEY_PLACE_ID "PlaceId" + + +/* Data & Option Values */ +#define VAL_TRUE 1 +#define VAL_FALSE 0 +#define VAL_ENTER "Enter" +#define VAL_EXIT "Exit" +#define VAL_DISABLED "Disabled" +#define VAL_CONNECTED "Connected" +#define VAL_UNCONNECTED "Unconnected" +#define VAL_SEARCHING "Searching" +#define VAL_EMPTY "Empty" +#define VAL_CRITICAL "Critical" +#define VAL_LOW "Low" +#define VAL_NORMAL "Normal" +#define VAL_HIGH "High" +#define VAL_FULL "Full" +#define VAL_HEADSET "Headset" +#define VAL_BLUETOOTH "Bluetooth" +#define VAL_IDLE "Idle" +#define VAL_CONNECTING "Connecting" +#define VAL_CONNECTED "Connected" +#define VAL_HELD "Held" +#define VAL_DIALING "Dialing" +#define VAL_VOICE "Voice" +#define VAL_VIDEO "Video" +#define VAL_SENT "Sent" +#define VAL_RECEIVED "Received" +#define VAL_SMS "SMS" +#define VAL_MMS "MMS" +#define VAL_MY_PROFILE "MyProfile" +#define VAL_PERSON "Person" +#define VAL_CHANGED "Changed" +#define VAL_DETECTED "Detected" +#define VAL_UNCERTAIN "Uncertain" +#define VAL_IN "In" +#define VAL_OUT "Out" + +#define VAL_ACTIVE VAL_CONNECTED +#define VAL_ALERTING VAL_CONNECTING +#define VAL_INCOMING VAL_CONNECTING + + +#endif /* _CONTEXT_PROVIDER_TYPES_H_ */ diff --git a/common/include/ScopeMutex.h b/common/include/ScopeMutex.h new file mode 100644 index 0000000..a17bc2a --- /dev/null +++ b/common/include/ScopeMutex.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_SCOPE_MUTEX_H_ +#define _CONTEXT_SCOPE_MUTEX_H_ + +#include + +namespace ctx { + + class ScopeMutex { + private: + GMutex *__mutex; + + public: + ScopeMutex(GMutex *m); + ~ScopeMutex(); + }; + +} /* namespace ctx */ + +#endif // _CONTEXT_SCOPE_MUTEX_H_ diff --git a/common/include/SensorRecorderTypes.h b/common/include/SensorRecorderTypes.h new file mode 100644 index 0000000..7ad6d0c --- /dev/null +++ b/common/include/SensorRecorderTypes.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CONTEXT_SENSOR_RECORDER_TYPES_H__ +#define __CONTEXT_SENSOR_RECORDER_TYPES_H__ + +#include + +/* Sensor Subjects */ +#define SUBJ_SENSOR "sensor/" +#define SUBJ_SENSOR_HEART_RATE SUBJ_SENSOR "heart_rate" +#define SUBJ_SENSOR_PEDOMETER SUBJ_SENSOR "pedometer" +#define SUBJ_SENSOR_SLEEP_MONITOR SUBJ_SENSOR "sleep_monitor" +#define SUBJ_SENSOR_PRESSURE SUBJ_SENSOR "pressure" +#define SUBJ_SENSOR_EXERCISE SUBJ_SENSOR "exercise" + +/* Keys */ +#define KEY_SUBJECT "Subject" +#define KEY_OPERATION "Operation" +#define KEY_OPTION "Option" + +#define KEY_RETENTION "Retention" +#define KEY_INTERVAL "Interval" +#define KEY_ANCHOR "Anchor" + +#define KEY_STEPS "Steps" +#define KEY_WALK_STEPS "WalkSteps" +#define KEY_RUN_STEPS "RunSteps" +#define KEY_DISTANCE "Dist" +#define KEY_CALORIES "Cal" +#define KEY_PRESSURE "Pressure" +#define KEY_AVG_PRESSURE "AvgPressure" +#define KEY_MIN_PRESSURE "MinPressure" +#define KEY_MAX_PRESSURE "MaxPressure" +#define KEY_SLEEP_STATE KEY_STATE +#define KEY_HEART_RATE "HeartRate" + +/* Values */ +#define VAL_START "Start" +#define VAL_STOP "Stop" + +#endif /* __CONTEXT_SENSOR_RECORDER_TYPES_H__ */ diff --git a/common/include/SharedVars.h b/common/include/SharedVars.h new file mode 100644 index 0000000..4171e1a --- /dev/null +++ b/common/include/SharedVars.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_SHARED_VARS_H_ +#define _CONTEXT_SHARED_VARS_H_ + +#include +#include +#include + +namespace ctx { + + /* + * TODO: Maybe later, it would be possible to extend this to support a sort of + * 'update observation' feature, i.e., getting notifications when a variable is updated. + */ + class SharedVars { + public: + enum VarId { + WIFI_BSSID, + }; + + SharedVars(); + ~SharedVars(); + + const std::string& set(VarId id, std::string value) const; + std::string get(VarId id); + void clear(VarId id); + + private: + static GMutex __mutex; + static std::map __varsMap; + }; + +} + +#endif diff --git a/common/include/TimerManager.h b/common/include/TimerManager.h new file mode 100644 index 0000000..d8338f2 --- /dev/null +++ b/common/include/TimerManager.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TIMER_H_ +#define _CONTEXT_TIMER_H_ + +#include +#include +#include +#include +#include + +#define DAYS_PER_WEEK 7 +#define DOW_MON "Mon" +#define DOW_TUE "Tue" +#define DOW_WED "Wed" +#define DOW_THU "Thu" +#define DOW_FRI "Fri" +#define DOW_SAT "Sat" +#define DOW_SUN "Sun" +#define DOW_WEEKDAY "Weekday" +#define DOW_WEEKEND "Weekend" +#define DOW_EVERYDAY "Everyday" + +namespace ctx { + + enum class DayOfWeek { + SUN = 0x01, + MON = 0x02, + TUE = 0x04, + WED = 0x08, + THU = 0x10, + FRI = 0x20, + SAT = 0x40, + WEEKDAY = MON | TUE | WED | THU | FRI, + WEEKEND = SAT | SUN, + EVERYDAY = SUN | MON | TUE | WED | THU | FRI | SAT + }; + + class TimerManager { + public: + TimerManager(); + ~TimerManager(); + + static std::string dowToStr(int dow); + static int dowToInt(std::string dow); + + /** + * @brief Sets a repeated timer for a given interval of time (s). + * @details It is recommended to minize the number of timers initiated, to reduce battery consumptions. + * If it is possible to share a timer for multiple purposes, please do that. + * @param[in] interval Timer interval. The first timer will be expired after @c interval minutes, + * and will be repeated until the listener returns @c false. + * @param[in] listener A listner object to be notified. + * @return Timer ID. A negative integer if failed to set a timer. + */ + int setFor(int interval, ITimerListener *listener); + + /** + * @brief Sets a timer that will be expired at a specific time, at designated days of week. + * @details It is recommended to minize the number of timers initiated, to reduce battery consumptions. + * If it is possible to share a timer for multiple purposes, please do that. + * @param[in] hour Hour + * @param[in] min Minute + * @param[in] dow The timer will expire at hour:min:00, at every day(s) of week designated here. + * @param[in] listener Listener object. + * @return Timer ID. A negative integer if failed to set a timer. + */ + int setAt(int hour, int min, DayOfWeek dow, ITimerListener *listener); + + /** + * @brief Removes the timer specified by @c timerId. + */ + void remove(int timerId); + + private: + static int __onAlarmExpired(int alarmId, void *userdata); + + bool __init(); + void __release(); + void __remove(int timerId); + + static unsigned int __instanceCnt; + static GMutex __mutex; + static std::map> __listenerMap; + + std::set __alarms; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_TIMER_H_ */ diff --git a/common/include/TriggerRuleTypes.h b/common/include/TriggerRuleTypes.h new file mode 100644 index 0000000..886d119 --- /dev/null +++ b/common/include/TriggerRuleTypes.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TRIGGER_RULE_TYPES_H_ +#define _CONTEXT_TRIGGER_RULE_TYPES_H_ + +#include + +#define TRIG_RULE_REF_KEY_PREFIX "?" + +/* Rule Key */ +#define TRIG_RULE_KEY_DESCRIPTION "description" +#define TRIG_RULE_KEY_EVENT "event" +#define TRIG_RULE_KEY_CONDITION "condition" +#define TRIG_RULE_KEY_ACTION "action" +#define TRIG_RULE_KEY_OPTION "option" +#define TRIG_RULE_KEY_COMPARISON "comparison" +#define TRIG_RULE_KEY_OPERATOR "operator" +#define TRIG_RULE_KEY_VALUE "value" +#define TRIG_RULE_KEY_APP_LAUNCH "appLaunch" +#define TRIG_RULE_KEY_APP_LAUNCH_APP_CONTROL "appControl" +#define TRIG_RULE_KEY_NOTIFICATION "notification" +#define TRIG_RULE_KEY_NOTI_TITLE "title" +#define TRIG_RULE_KEY_NOTI_CONTENT "content" +#define TRIG_RULE_KEY_NOTI_ICON_PATH "iconPath" +#define TRIG_RULE_KEY_NOTI_APP_CONTROL "appControl" +#define TRIG_RULE_KEY_DBUS_CALL "dbusCall" +#define TRIG_RULE_KEY_DBUS_NAME "name" +#define TRIG_RULE_KEY_DBUS_OBJECT "object" +#define TRIG_RULE_KEY_DBUS_INTERFACE "interafce" +#define TRIG_RULE_KEY_DBUS_METHOD "method" +#define TRIG_RULE_KEY_DBUS_PARAMETER "parameter" + +/* Internal Rule Key */ +#define _TRIG_RULE_KEY_EXTRA "_extra" +#define _TRIG_RULE_KEY_RULE_LOGICAL_OP "_ruleOp" +#define _TRIG_RULE_KEY_EVENT_LOGICAL_OP "_eventOp" +#define _TRIG_RULE_KEY_CONDITION_LOGICAL_OP "_condOp" + +/* Comparison Operator */ +#define TRIG_RULE_OP_EQUAL_TO "==" +#define TRIG_RULE_OP_NOT_EQUAL_TO "!=" +#define TRIG_RULE_OP_GREATER_THAN ">" +#define TRIG_RULE_OP_GREATER_THAN_OR_EQUAL_TO ">=" +#define TRIG_RULE_OP_LESS_THAN "<" +#define TRIG_RULE_OP_LESS_THAN_OR_EQUAL_TO "<=" +#define TRIG_RULE_OP_ONE_OF "oneOf" +#define TRIG_RULE_OP_NONE_OF "noneOf" +#define TRIG_RULE_OP_IN "in" +#define TRIG_RULE_OP_NOT_IN "notIn" +//#define TRIG_RULE_OP_CONTAIN "contain" + +/* Old Rule Keys */ +#define TRIG_RULE_LOGICAL_CONJUNCTION "and" +#define TRIG_RULE_LOGICAL_DISJUNCTION "or" + +#endif /* _CONTEXT_TRIGGER_RULE_TYPES_H_ */ diff --git a/common/include/TriggerTypes.h b/common/include/TriggerTypes.h new file mode 100644 index 0000000..85f688b --- /dev/null +++ b/common/include/TriggerTypes.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TRIGGER_TYPES_H_ +#define _CONTEXT_TRIGGER_TYPES_H_ + +/* Request Subject */ +#define SUBJ_TRIGGER_ADD "trigger/add" +#define SUBJ_TRIGGER_REMOVE "trigger/remove" +#define SUBJ_TRIGGER_ENABLE "trigger/enable" +#define SUBJ_TRIGGER_DISABLE "trigger/disable" +#define SUBJ_TRIGGER_GET "trigger/get" +#define SUBJ_TRIGGER_GET_RULE_IDS "trigger/getRuleIds" +#define SUBJ_TRIGGER_GET_TEMPLATE "trigger/tepmlate/get" +#define SUBJ_TRIGGER_CUSTOM "custom" + +/* Response Types */ +#define TRIG_KEY_RULE_ID "id" +#define TRIG_KEY_ENABLED_IDS "enabledRuleIds" +#define TRIG_KEY_DISABLED_IDS "disabledRuleIds" + +/* Template Types */ +#define TRIG_TMPL_KEY_SUBJECT "subject" +#define TRIG_TMPL_KEY_OWNER "owner" +#define TRIG_TMPL_KEY_OPTION "options" +#define TRIG_TMPL_KEY_ATTRIBUTE "attributes" +#define TRIG_TMPL_KEY_MIN "minimum" +#define TRIG_TMPL_KEY_MAX "maximum" +#define TRIG_TMPL_KEY_TYPE "type" +#define TRIG_TMPL_TYPE_INTEGER "integer" +#define TRIG_TMPL_TYPE_STRING "string" +#define TRIG_TMPL_TYPE_ENUM "enum" +#define TRIG_TMPL_TYPE_DOUBLE "double" + +/* Custom Request Types */ +#define TRIG_CUSTOM_PREFIX SUBJ_TRIGGER_CUSTOM +#define TRIG_CUSTOM_KEY_REQ "req" +#define TRIG_CUSTOM_REQ_ADD "add" +#define TRIG_CUSTOM_REQ_REMOVE "remove" +#define TRIG_CUSTOM_REQ_PUBLISH "publish" + +/* Custom Fact Types */ +#define TRIG_CUSTOM_KEY_NAME "name" +#define TRIG_CUSTOM_KEY_FACT "fact" + +/* Etc */ +#define TRIG_SUBJECT_SEPERATOR "/" + +#endif /* _CONTEXT_TRIGGER_TYPES_H_ */ diff --git a/common/include/Types.h b/common/include/Types.h new file mode 100644 index 0000000..aaadd57 --- /dev/null +++ b/common/include/Types.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_TYPES_H_ +#define _CONTEXT_TYPES_H_ + +#include +#include + +#define SO_EXPORT __attribute__ ((visibility("default"))) + +/* Logging and Error Handling */ +#define _I SLOGI +#define _D SLOGD +#define _W SLOGW +#define _E SLOGE +#define _SI SECURE_SLOGI +#define _SD SECURE_SLOGD +#define _SW SECURE_LOGW +#define _SE SECURE_SLOGE + +/* Color code for dlog */ +#define RED(X) "\033[0;31m" X "\033[0m" +#define GREEN(X) "\033[0;32m" X "\033[0m" +#define YELLOW(X) "\033[0;33m" X "\033[0m" +#define BLUE(X) "\033[0;34m" X "\033[0m" +#define PURPLE(X) "\033[0;35m" X "\033[0m" +#define CYAN(X) "\033[0;36m" X "\033[0m" + +#define REPLACE_NULL(X) ((X) ? (X) : "") +#define STR_EQ(X, Y) (g_strcmp0((X), (Y)) == 0) + +#define IF_FAIL_RETURN_TAG(cond, ret, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); return ret; } } while (0) + +#define IF_FAIL_RETURN(cond, ret) \ + do { if (!(cond)) { return ret; } } while (0) + +#define IF_FAIL_VOID_TAG(cond, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); return; } } while (0) + +#define IF_FAIL_VOID(cond) \ + do { if (!(cond)) { return; } } while (0) + +#define IF_FAIL_CATCH_TAG(cond, tag, fmt, arg...) \ + do { if (!(cond)) { tag(fmt, ##arg); goto CATCH; } } while (0) + +#define IF_FAIL_CATCH(cond) \ + do { if (!(cond)) { goto CATCH; } } while (0) + +#define IS_FAILED(X) ((X) != ERR_NONE) + +#define ASSERT_ALLOC(X) IF_FAIL_RETURN_TAG(X, ERR_OUT_OF_MEMORY, _E, "Memory allocation failed") +#define ASSERT_NOT_NULL(X) IF_FAIL_RETURN_TAG(X, ERR_INVALID_PARAMETER, _E, "Parameter null") + +#define HANDLE_GERROR(Err) \ + do { if ((Err)) { _E("GError: %s", Err->message); g_error_free(Err); Err = NULL; } } while (0) + +#endif /* _CONTEXT_TYPES_H_ */ diff --git a/common/server/CMakeLists.txt b/common/server/CMakeLists.txt new file mode 100644 index 0000000..31c854b --- /dev/null +++ b/common/server/CMakeLists.txt @@ -0,0 +1,13 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-server") + +FILE(GLOB_RECURSE SRCS *.cpp) +MESSAGE("Sources: ${SRCS}") + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${LIB_PKG_LDFLAGS}) +TARGET_LINK_LIBRARIES(${target} ctx-shared) +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/common/server/ContextProvider.cpp b/common/server/ContextProvider.cpp new file mode 100644 index 0000000..ac2758c --- /dev/null +++ b/common/server/ContextProvider.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +using namespace ctx; + +IContextManager *ContextProvider::__contextMgr = NULL; + +ContextProvider::ContextProvider(const char *subject) : + __subject(subject) +{ +} + +ContextProvider::~ContextProvider() +{ +} + +const char* ContextProvider::getSubject() +{ + return __subject; +} + +bool ContextProvider::isSupported() +{ + return true; +} + +int ContextProvider::subscribe(Json option, Json *requestResult) +{ + return ERR_NOT_SUPPORTED; +} + +int ContextProvider::unsubscribe(Json option) +{ + return ERR_NOT_SUPPORTED; +} + +int ContextProvider::read(Json option, Json *requestResult) +{ + return ERR_NOT_SUPPORTED; +} + +int ContextProvider::write(Json data, Json *requestResult) +{ + return ERR_NOT_SUPPORTED; +} + +void ContextProvider::getPrivilege(std::vector &privilege) +{ +} + +bool ContextProvider::unloadable() +{ + return true; +} + +bool ContextProvider::publish(Json option, int error, Json dataUpdated) +{ + return __contextMgr->publish(__subject, option, error, dataUpdated); +} + +bool ContextProvider::replyToRead(Json option, int error, Json dataRead) +{ + return __contextMgr->replyToRead(__subject, option, error, dataRead); +} + +void ContextProvider::__setContextManager(IContextManager *contextMgr) +{ + __contextMgr = contextMgr; +} diff --git a/common/server/CustomRegistser.cpp b/common/server/CustomRegistser.cpp new file mode 100644 index 0000000..313d685 --- /dev/null +++ b/common/server/CustomRegistser.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +using namespace ctx; + +ICustomRegister *CustomRegister::__customRegister = NULL; + +CustomRegister::CustomRegister() +{ +} + +CustomRegister::~CustomRegister() +{ +} + +bool CustomRegister::registerCustomProvider(const char* subject, int operation, Json attribute, Json option, const char* owner) +{ + return __customRegister->registerCustomProvider(subject, operation, attribute, option, owner); +} + +bool CustomRegister::unregisterCustomProvider(const char* subject) +{ + return __customRegister->unregisterCustomProvider(subject); +} + +void CustomRegister::__setCustomRegister(ICustomRegister *customRegister) +{ + __customRegister = customRegister; +} diff --git a/common/server/DBusSignalWatcher.cpp b/common/server/DBusSignalWatcher.cpp new file mode 100644 index 0000000..c03c781 --- /dev/null +++ b/common/server/DBusSignalWatcher.cpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +using namespace ctx; + +GMutex DBusSignalWatcher::__mutex; +unsigned int DBusSignalWatcher::__systemBusCnt = 0; +unsigned int DBusSignalWatcher::__sessionBusCnt = 0; +GDBusConnection *DBusSignalWatcher::__systemBus = NULL; +GDBusConnection *DBusSignalWatcher::__sessionBus = NULL; + +static void __signal_cb(GDBusConnection *conn, const gchar *sender, + const gchar *path, const gchar *iface, const gchar *name, + GVariant *param, gpointer userdata) +{ + IF_FAIL_VOID_TAG(userdata, _W, "user_data cannot be null"); + IDBusSignalListener *listener = static_cast(userdata); + listener->onSignal(sender, path, iface, name, param); +} + +SO_EXPORT DBusSignalWatcher::DBusSignalWatcher(DBusType type) : + __busType(type) +{ + ScopeMutex sm(&__mutex); + + if (__busType == DBusType::SYSTEM) { + if (__systemBusCnt++ == 0) + __openBus(G_BUS_TYPE_SYSTEM, __systemBus); + } else { + if (__sessionBusCnt++ == 0) + __openBus(G_BUS_TYPE_SESSION, __sessionBus); + } +} + +SO_EXPORT DBusSignalWatcher::~DBusSignalWatcher() +{ + ScopeMutex sm(&__mutex); + + if (__busType == DBusType::SYSTEM) { + if (--__systemBusCnt == 0) + __closeBus(__systemBus); + } else { + if (--__sessionBusCnt == 0) + __closeBus(__sessionBus); + } +} + +SO_EXPORT int64_t DBusSignalWatcher::watch(const char *sender, const char *path, const char *iface, const char *name, IDBusSignalListener *listener) +{ + GDBusConnection *bus = (__busType == DBusType::SYSTEM ? __systemBus : __sessionBus); + IF_FAIL_RETURN_TAG(bus, -1, _E, "Dbus not connected"); + + guint sid = g_dbus_connection_signal_subscribe(bus, + sender, iface, name, path, NULL, G_DBUS_SIGNAL_FLAGS_NONE, + __signal_cb, listener, NULL); + + return static_cast(sid); +} + +SO_EXPORT void DBusSignalWatcher::unwatch(int64_t signal_id) +{ + IF_FAIL_VOID_TAG(signal_id >= 0, _W, "Invalid parameter"); + GDBusConnection *bus = (__busType == DBusType::SYSTEM ? __systemBus : __sessionBus); + g_dbus_connection_signal_unsubscribe(bus, static_cast(signal_id)); +} + +void DBusSignalWatcher::__openBus(GBusType type, GDBusConnection *&bus) +{ + GError *gerr = NULL; + gchar *addr = g_dbus_address_get_for_bus_sync(type, NULL, &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_VOID(addr); + + bus = g_dbus_connection_new_for_address_sync(addr, + (GDBusConnectionFlags)(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION), + NULL, NULL, &gerr); + g_free(addr); + HANDLE_GERROR(gerr); + IF_FAIL_VOID(bus); + + _D("%s Bus Connected", type == G_BUS_TYPE_SYSTEM ? "SYSTEM" : "SESSION"); +} + +void DBusSignalWatcher::__closeBus(GDBusConnection *&bus) +{ + IF_FAIL_VOID(bus); + + g_dbus_connection_close_sync(bus, NULL, NULL); + g_object_unref(bus); + bus = NULL; + + _D("%s Bus Closed", __busType == DBusType::SYSTEM ? "SYSTEM" : "SESSION"); +} diff --git a/common/server/DatabaseManager.cpp b/common/server/DatabaseManager.cpp new file mode 100644 index 0000000..008c450 --- /dev/null +++ b/common/server/DatabaseManager.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "DatabaseThread.h" + +#define CONTEXT_DB_PATH tzplatform_mkpath(TZ_USER_DB, ".context-service.db") + +using namespace ctx; + +static unsigned int __refCount = 0; +static GMutex __mutex; +static DatabaseThread *__databaseThread = NULL; + +SO_EXPORT DatabaseManager::DatabaseManager() +{ + ScopeMutex sm(&__mutex); + + if (++__refCount > 1) + return; + + if (!__databaseThread->start()) + _E("Failed to start Database thread"); +} + +SO_EXPORT DatabaseManager::~DatabaseManager() +{ + ScopeMutex sm(&__mutex); + + if (--__refCount > 0) + return; + + __databaseThread->stop(); +} + +SO_EXPORT bool DatabaseManager::__init() +{ + __databaseThread = new(std::nothrow) DatabaseThread(); + IF_FAIL_RETURN_TAG(__databaseThread, false, _E, "Memory allocation failed"); + + if (__databaseThread->open(CONTEXT_DB_PATH)) + return true; + + _E("Database initialization failed"); + delete __databaseThread; + __databaseThread = NULL; + return false; +} + +SO_EXPORT void DatabaseManager::__release() +{ + if (!__databaseThread) + return; + + __databaseThread->stop(); + __databaseThread->close(); + + delete __databaseThread; + __databaseThread = NULL; +} + +SO_EXPORT bool DatabaseManager::createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option, IDatabaseListener *listener) +{ + return __databaseThread->createTable(queryId, tableName, columns, option, listener); +} + +SO_EXPORT bool DatabaseManager::insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener) +{ + return __databaseThread->insert(queryId, tableName, record, listener); +} + +SO_EXPORT bool DatabaseManager::execute(unsigned int queryId, const char *query, IDatabaseListener *listener) +{ + return __databaseThread->execute(queryId, query, listener); +} + +SO_EXPORT bool DatabaseManager::createTableSync(const char *tableName, const char *columns, const char *option) +{ + return __databaseThread->createTableSync(tableName, columns, option); +} + +SO_EXPORT bool DatabaseManager::insertSync(const char *tableName, Json record, int64_t *rowId) +{ + return __databaseThread->insertSync(tableName, record, rowId); +} + +SO_EXPORT bool DatabaseManager::executeSync(const char *query, std::vector *records) +{ + return __databaseThread->executeSync(query, records); +} diff --git a/common/server/DatabaseThread.cpp b/common/server/DatabaseThread.cpp new file mode 100644 index 0000000..66e622e --- /dev/null +++ b/common/server/DatabaseThread.cpp @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "DatabaseThread.h" + +using namespace ctx; + +DatabaseThread::DatabaseThread() : + __databaseHandle(NULL) +{ + g_mutex_init(&__execMutex); +} + +DatabaseThread::~DatabaseThread() +{ + g_mutex_clear(&__execMutex); +} + +bool DatabaseThread::open(const char *dbPath) +{ + sqlite3 *db = NULL; + char *err = NULL; + int ret; + + ret = sqlite3_open(dbPath, &db); + IF_FAIL_RETURN_TAG(ret == SQLITE_OK, false, _E, "Path: %s / Error: %s", dbPath, sqlite3_errmsg(db)); + + ret = sqlite3_exec(db, "PRAGMA journal_mode = WAL", NULL, NULL, &err); + if (ret != SQLITE_OK) { + _E("Setting journal mode failed: %s", err); + sqlite3_free(err); + sqlite3_close(db); + return false; + } + + __databaseHandle = db; + return true; +} + +void DatabaseThread::close() +{ + sqlite3_close(__databaseHandle); +} + +bool DatabaseThread::createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option, IDatabaseListener *listener) +{ + QueryInfo *info = new(std::nothrow) QueryInfo; + IF_FAIL_RETURN_TAG(info, false, _E, "Memory allocation failed"); + + info->query = __composeCreate(tableName, columns, option); + info->id = queryId; + info->listener = listener; + + if (!pushEvent(QUERY_CREATE_TABLE, info)) { + delete info; + return false; + } + + return true; +} + +bool DatabaseThread::insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener) +{ + std::string query = __composeInsert(tableName, record); + IF_FAIL_RETURN(!query.empty(), false); + + QueryInfo *info = new(std::nothrow) QueryInfo; + IF_FAIL_RETURN_TAG(info, false, _E, "Memory allocation failed"); + + info->query = query; + info->id = queryId; + info->listener = listener; + + if (!pushEvent(QUERY_INSERT, info)) { + delete info; + return false; + } + + return true; +} + +bool DatabaseThread::execute(unsigned int queryId, const char *query, IDatabaseListener *listener) +{ + IF_FAIL_RETURN(query, false); + + QueryInfo *info = new(std::nothrow) QueryInfo; + IF_FAIL_RETURN_TAG(info, false, _E, "Memory allocation failed"); + + info->id = queryId; + info->query = query; + info->listener = listener; + + if (!pushEvent(QUERY_EXECUTE, info)) { + delete info; + return false; + } + + return true; +} + +bool DatabaseThread::createTableSync(const char *tableName, const char *columns, const char *option) +{ + std::string query = __composeCreate(tableName, columns, option); + IF_FAIL_RETURN(!query.empty(), false); + _SD("SQL: %s", query.c_str()); + + char *err = NULL; + int ret; + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query.c_str(), NULL, NULL, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + return false; + } + + return true; +} + +bool DatabaseThread::insertSync(const char *tableName, Json record, int64_t *rowId) +{ + IF_FAIL_RETURN(tableName && rowId, false); + + std::string query = __composeInsert(tableName, record); + IF_FAIL_RETURN(!query.empty(), false); + _SD("SQL: %s", query.c_str()); + + std::vector queryResult; + char *err = NULL; + int ret; + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query.c_str(), __executionCb, &queryResult, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + return false; + } + + IF_FAIL_RETURN_TAG(!queryResult.empty(), false, _E, "No row id"); + + *rowId = -1; + queryResult.at(0).get(NULL, "seq", rowId); + _D("RowId: %lld", *rowId); + + return true; +} + +bool DatabaseThread::executeSync(const char *query, std::vector *records) +{ + IF_FAIL_RETURN(query, false); + + _SD("SQL: %s", query); + + char *err = NULL; + int ret; + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query, __executionCb, records, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + return false; + } + + return true; +} + +void DatabaseThread::onEvent(int type, void* data) +{ + IF_FAIL_VOID(data); + QueryInfo *info = static_cast(data); + + __execute(static_cast(type), info->id, info->query.c_str(), info->listener); + + deleteEvent(type, data); +} + +void DatabaseThread::deleteEvent(int type, void* data) +{ + IF_FAIL_VOID(data); + QueryInfo *info = static_cast(data); + delete info; +} + +std::string DatabaseThread::__composeCreate(const char *tableName, const char *columns, const char *option) +{ + std::string query; + query = "CREATE TABLE IF NOT EXISTS "; + query = query + tableName + " (rowId INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," + columns + ")"; + if (option) { + query = query + " " + option; + } + query += ";"; + return query; +} + +std::string DatabaseThread::__composeInsert(const char *tableName, Json record) +{ + std::string cols; + std::string vals; + std::list keys; + + IF_FAIL_RETURN_TAG(record.getKeys(&keys), "", _E, "Invalid record"); + + for (auto it = keys.begin(); it != keys.end(); ++it) { + std::string s; + int64_t i; + if (record.get(NULL, (*it).c_str(), &s)) { + cols = cols + *it + ","; + + char* buf = sqlite3_mprintf("%Q", s.c_str()); + IF_FAIL_RETURN_TAG(buf, "", _E, "Memory allocation failed"); + + vals = vals + buf + ","; + sqlite3_free(buf); + + } else if (record.get(NULL, (*it).c_str(), &i)) { + cols = cols + *it + ","; + vals = vals + std::to_string(i) + ","; + } + } + + IF_FAIL_RETURN_TAG(!cols.empty(), "", _E, "Invalid record"); + + cols.erase(cols.size() - 1); + vals.erase(vals.size() - 1); + + std::string query = "INSERT INTO "; + query = query + tableName + " (" + cols + ") VALUES (" + vals + ");"; + query = query + "SELECT seq FROM sqlite_sequence WHERE name='" + tableName + "';"; + + return query; +} + +void DatabaseThread::__execute(QueryType type, unsigned int queryId, const char *query, IDatabaseListener *listener) +{ + _SD("SQL(%d): %s", queryId, query); + + std::vector *queryResult = new(std::nothrow) std::vector; + IF_FAIL_VOID_TAG(queryResult, _E, "Memory allocation failed"); + + char *err = NULL; + int ret; + + { + ScopeMutex sm(&__execMutex); + ret = sqlite3_exec(__databaseHandle, query, __executionCb, queryResult, &err); + } + + if (ret != SQLITE_OK) { + _E("DB Error: %s", err); + sqlite3_free(err); + __dispatchResult(type, queryId, listener, ERR_OPERATION_FAILED, queryResult); + return; + } + + __dispatchResult(type, queryId, listener, ERR_NONE, queryResult); + return; +} + +void DatabaseThread::__dispatchResult(QueryType type, unsigned int queryId, IDatabaseListener *listener, int error, std::vector *result) +{ + QueryResult *qr = new(std::nothrow) QueryResult(); + IF_FAIL_VOID_TAG(qr, _E, "Memory allocation failed"); + + qr->type = type; + qr->id = queryId; + qr->listener = listener; + qr->error = error; + qr->result = result; + + g_idle_add(__dispatcher, qr); +} + +int DatabaseThread::__executionCb(void *userData, int dim, char **value, char **column) +{ + IF_FAIL_RETURN(userData, 0); + + std::vector *records = static_cast*>(userData); + Json row; + bool columnNull = false; + + for (int i = 0; i < dim; ++i) { + if (!value[i]) { + columnNull = true; + _W(RED("Null columns exist")); + break; + } + + row.set(NULL, column[i], value[i]); + } + + if (!columnNull) { + records->push_back(row); + } + + return 0; +} + +gboolean DatabaseThread::__dispatcher(gpointer data) +{ + QueryResult *qr = static_cast(data); + + if (qr->listener) { + switch (qr->type) { + case QUERY_CREATE_TABLE: + qr->listener->onTableCreated(qr->id, qr->error); + break; + case QUERY_INSERT: + { + int64_t rowId = -1; + if (qr->error == ERR_NONE && qr->result && !qr->result->empty()) { + qr->result->at(0).get(NULL, "seq", &rowId); + _D("RowId: %d", rowId); + } + qr->listener->onInserted(qr->id, qr->error, rowId); + } + break; + case QUERY_EXECUTE: + qr->listener->onExecuted(qr->id, qr->error, *(qr->result)); + break; + default: + _W("Unknown query type: %d", qr->type); + } + } + + delete qr->result; + delete qr; + return FALSE; +} diff --git a/common/server/DatabaseThread.h b/common/server/DatabaseThread.h new file mode 100644 index 0000000..4e3b608 --- /dev/null +++ b/common/server/DatabaseThread.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _CONTEXT_DATABASE_THREAD_H_ +#define _CONTEXT_DATABASE_THREAD_H_ + +#include +#include +#include + +namespace ctx { + + class DatabaseThread : public EventDrivenThread { + public: + DatabaseThread(); + ~DatabaseThread(); + + bool open(const char *dbPath); + void close(); + + bool createTable(unsigned int queryId, const char *tableName, const char *columns, const char *option = NULL, IDatabaseListener *listener = NULL); + bool insert(unsigned int queryId, const char *tableName, Json record, IDatabaseListener *listener = NULL); + bool execute(unsigned int queryId, const char *query, IDatabaseListener *listener = NULL); + bool createTableSync(const char *tableName, const char *columns, const char *option = NULL); + bool insertSync(const char *tableName, Json record, int64_t *rowId); + bool executeSync(const char *query, std::vector *records); + + private: + enum QueryType { + QUERY_CREATE_TABLE = 1, + QUERY_INSERT, + QUERY_EXECUTE, + }; + + struct QueryInfo { + unsigned int id; + IDatabaseListener *listener; + std::string query; + }; + + struct QueryResult { + int type; + unsigned int id; + int error; + IDatabaseListener *listener; + std::vector *result; + }; + + void onEvent(int type, void* data); + void deleteEvent(int type, void* data); + + std::string __composeCreate(const char *tableName, const char *columns, const char *option); + std::string __composeInsert(const char *tableName, Json record); + + void __execute(QueryType type, unsigned int queryId, const char *query, IDatabaseListener *listener); + void __dispatchResult(QueryType type, unsigned int queryId, IDatabaseListener *listener, int error, std::vector *result); + + static int __executionCb(void *userData, int dim, char **value, char **column); + static gboolean __dispatcher(gpointer data); + + sqlite3 *__databaseHandle; + GMutex __execMutex; + }; + +} /* namespace ctx */ + +#endif /* _CONTEXT_DATABASE_THREAD_H_ */ diff --git a/common/server/EventDrivenThread.cpp b/common/server/EventDrivenThread.cpp new file mode 100644 index 0000000..6718ecc --- /dev/null +++ b/common/server/EventDrivenThread.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +struct thread_info_s { + GThread *thread; + std::atomic_bool isRunning; + GAsyncQueue *eventQueue; + thread_info_s() : thread(NULL), isRunning(false), eventQueue(NULL) {} +}; + +struct event_message_s { + int type; + void* data; + bool term; + event_message_s() : type(-1), data(NULL), term(false) {} +}; + +EventDrivenThread::EventDrivenThread() : + __threadInfo(NULL) +{ +} + +EventDrivenThread::~EventDrivenThread() +{ + if (__threadInfo) { + stop(); + delete __threadInfo; + } +} + +bool EventDrivenThread::start() +{ + if (!__threadInfo) { + __threadInfo = new(std::nothrow) thread_info_s; + } + + IF_FAIL_RETURN_TAG(__threadInfo, false, _E, "Memory allocation failed"); + + if (!isRunning()) { + + __threadInfo->eventQueue = g_async_queue_new(); + + if (__threadInfo->eventQueue == NULL) { + _E("Memory allocation failed"); + return false; + } + + __threadInfo->isRunning = true; + + __threadInfo->thread = g_thread_new(NULL, __threadFunc, static_cast(this)); + + if (__threadInfo->thread == NULL) { + _E(RED("Thread creation failed")); + __threadInfo->isRunning = false; + g_async_queue_unref(__threadInfo->eventQueue); + return false; + } + + _I(PURPLE("A thread initiated")); + } + + return true; +} + +bool EventDrivenThread::stop() +{ + if (!isRunning()) + return true; + + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->term = true; + g_async_queue_push(__threadInfo->eventQueue, event); + g_thread_join(__threadInfo->thread); + g_async_queue_unref(__threadInfo->eventQueue); + return true; +} + +bool EventDrivenThread::isRunning() +{ + return __threadInfo->isRunning.load(); +} + +bool EventDrivenThread::pushEvent(int type, void* data) +{ + if (!isRunning()) + return false; + + event_message_s* event = new(std::nothrow) event_message_s; + IF_FAIL_RETURN_TAG(event, false, _E, "Memory allocation failed"); + + event->type = type; + event->data = data; + g_async_queue_push(__threadInfo->eventQueue, event); + return true; +} + +gpointer EventDrivenThread::__threadFunc(gpointer data) +{ + static_cast(data)->__run(); + return NULL; +} + +void EventDrivenThread::__run() +{ + event_message_s *event = NULL; + + while (isRunning()) { + event = static_cast(g_async_queue_pop(__threadInfo->eventQueue)); + if (event->term) { + __threadInfo->isRunning = false; + } else { + onEvent(event->type, event->data); + } + delete event; + } +} diff --git a/common/server/IContextManager.cpp b/common/server/IContextManager.cpp new file mode 100644 index 0000000..1a02a57 --- /dev/null +++ b/common/server/IContextManager.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +ctx::IContextManager::~IContextManager() +{ +} diff --git a/common/server/IDBusSignalListener.cpp b/common/server/IDBusSignalListener.cpp new file mode 100644 index 0000000..7296733 --- /dev/null +++ b/common/server/IDBusSignalListener.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +ctx::IDBusSignalListener::~IDBusSignalListener() +{ +} diff --git a/common/server/IDatabaseListener.cpp b/common/server/IDatabaseListener.cpp new file mode 100644 index 0000000..9eea63e --- /dev/null +++ b/common/server/IDatabaseListener.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +ctx::IDatabaseListener::~IDatabaseListener() +{ +} diff --git a/common/server/ITimerListener.cpp b/common/server/ITimerListener.cpp new file mode 100644 index 0000000..03f7e79 --- /dev/null +++ b/common/server/ITimerListener.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +ctx::ITimerListener::~ITimerListener() +{ +} diff --git a/common/server/SharedVars.cpp b/common/server/SharedVars.cpp new file mode 100644 index 0000000..dbcc36d --- /dev/null +++ b/common/server/SharedVars.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#define EMPTY_STRING "" + +using namespace ctx; + +GMutex SharedVars::__mutex; +std::map SharedVars::__varsMap; + +SO_EXPORT SharedVars::SharedVars() +{ +} + +SO_EXPORT SharedVars::~SharedVars() +{ +} + +SO_EXPORT const std::string& SharedVars::set(SharedVars::VarId id, std::string value) const +{ + ScopeMutex sm(&__mutex); + _D("var[%d] = %s", id, value.c_str()); + __varsMap[id] = value; + return __varsMap[id]; +} + +SO_EXPORT std::string SharedVars::get(SharedVars::VarId id) +{ + ScopeMutex sm(&__mutex); + auto it = __varsMap.find(id); + if (it != __varsMap.end()) + return it->second; + else + return EMPTY_STRING; +} + +SO_EXPORT void SharedVars::clear(SharedVars::VarId id) +{ + ScopeMutex sm(&__mutex); + _D("Remove var[%d]", id); + __varsMap.erase(id); +} diff --git a/common/server/TimerManager.cpp b/common/server/TimerManager.cpp new file mode 100644 index 0000000..46d2179 --- /dev/null +++ b/common/server/TimerManager.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#define IDENTIFIER "contextd" +#define EMPTY_STRING "" + +using namespace ctx; + +unsigned int TimerManager::__instanceCnt = 0; +GMutex TimerManager::__mutex; +std::map> TimerManager::__listenerMap; + +SO_EXPORT TimerManager::TimerManager() +{ + ScopeMutex sm(&__mutex); + + if (__instanceCnt++ == 0) + __init(); +} + +SO_EXPORT TimerManager::~TimerManager() +{ + ScopeMutex sm(&__mutex); + + for (int i : __alarms) { + __remove(i); + } + + if (--__instanceCnt == 0) + __release(); +} + +SO_EXPORT std::string TimerManager::dowToStr(int dow) +{ + static const char *dowStr[] = { + DOW_SUN, DOW_MON, DOW_TUE, DOW_WED, DOW_THU, DOW_FRI, DOW_SAT + }; + + if (static_cast(dow) == DayOfWeek::WEEKDAY) + return DOW_WEEKDAY; + + if (static_cast(dow) == DayOfWeek::WEEKEND) + return DOW_WEEKEND; + + if (static_cast(dow) == DayOfWeek::EVERYDAY) + return DOW_EVERYDAY; + + int d = log2(static_cast(dow)); + if (d >= 0 && d < DAYS_PER_WEEK) + return dowStr[d]; + + return EMPTY_STRING; +} + +SO_EXPORT int TimerManager::dowToInt(std::string dow) +{ + if (dow == DOW_SUN) return static_cast(DayOfWeek::SUN); + if (dow == DOW_MON) return static_cast(DayOfWeek::MON); + if (dow == DOW_TUE) return static_cast(DayOfWeek::TUE); + if (dow == DOW_WED) return static_cast(DayOfWeek::WED); + if (dow == DOW_THU) return static_cast(DayOfWeek::THU); + if (dow == DOW_FRI) return static_cast(DayOfWeek::FRI); + if (dow == DOW_SAT) return static_cast(DayOfWeek::SAT); + if (dow == DOW_WEEKDAY) return static_cast(DayOfWeek::WEEKDAY); + if (dow == DOW_WEEKEND) return static_cast(DayOfWeek::WEEKEND); + if (dow == DOW_EVERYDAY) return static_cast(DayOfWeek::EVERYDAY); + return 0; +} + +SO_EXPORT int TimerManager::setFor(int interval, ITimerListener *listener) +{ + IF_FAIL_RETURN_TAG(interval > 0 && listener, -1, _E, "Invalid parameter"); + + int alarmId; + int result; + + result = alarmmgr_add_periodic_alarm_withcb(interval, QUANTUMIZE, __onAlarmExpired, NULL, &alarmId); + IF_FAIL_RETURN_TAG(result == ALARMMGR_RESULT_SUCCESS, -1, _E, "Alarm setting failed"); + + ScopeMutex sm(&__mutex); + __listenerMap[alarmId] = std::make_pair(listener, this); + __alarms.insert(alarmId); + + _D("Timer %d was set for %dm interval", alarmId, interval); + return alarmId; +} + +SO_EXPORT int TimerManager::setAt(int hour, int min, DayOfWeek dow, ITimerListener *listener) +{ + IF_FAIL_RETURN_TAG( + hour < 24 && hour >= 0 && + min < 60 && min >= 0 && + static_cast(dow) > 0 && + static_cast(dow) <= static_cast(DayOfWeek::EVERYDAY) && + listener, -1, _E, "Invalid parameter"); + + int repeat = 0; + if (static_cast(dow) & static_cast(DayOfWeek::SUN)) + repeat |= ALARM_WDAY_SUNDAY; + if (static_cast(dow) & static_cast(DayOfWeek::MON)) + repeat |= ALARM_WDAY_MONDAY; + if (static_cast(dow) & static_cast(DayOfWeek::TUE)) + repeat |= ALARM_WDAY_TUESDAY; + if (static_cast(dow) & static_cast(DayOfWeek::WED)) + repeat |= ALARM_WDAY_WEDNESDAY; + if (static_cast(dow) & static_cast(DayOfWeek::THU)) + repeat |= ALARM_WDAY_THURSDAY; + if (static_cast(dow) & static_cast(DayOfWeek::FRI)) + repeat |= ALARM_WDAY_FRIDAY; + if (static_cast(dow) & static_cast(DayOfWeek::SAT)) + repeat |= ALARM_WDAY_SATURDAY; + + alarm_entry_t *alarmInfo = alarmmgr_create_alarm(); + IF_FAIL_RETURN_TAG(alarmInfo, -1, _E, "Memory allocation failed"); + + time_t currentTime; + struct tm currentTm; + time(¤tTime); + tzset(); + localtime_r(¤tTime, ¤tTm); + + alarm_date_t alarmTime; + alarmTime.year = currentTm.tm_year + 1900; + alarmTime.month = currentTm.tm_mon + 1; + alarmTime.day = currentTm.tm_mday; + alarmTime.hour = hour; + alarmTime.min = min; + alarmTime.sec = 0; + + alarmmgr_set_time(alarmInfo, alarmTime); + alarmmgr_set_repeat_mode(alarmInfo, ALARM_REPEAT_MODE_WEEKLY, repeat); + alarmmgr_set_type(alarmInfo, ALARM_TYPE_VOLATILE); + + int alarmId; + int ret = alarmmgr_add_alarm_with_localtime(alarmInfo, NULL, &alarmId); + alarmmgr_free_alarm(alarmInfo); + + IF_FAIL_RETURN_TAG(ret == ALARMMGR_RESULT_SUCCESS, -1, _E, "Alarm setting failed"); + + ScopeMutex sm(&__mutex); + __listenerMap[alarmId] = std::make_pair(listener, this); + __alarms.insert(alarmId); + + _D("Timer %d was set at %02d:%02d:00 (day of week: %#x)", alarmId, hour, min, dow); + return alarmId; +} + +SO_EXPORT void TimerManager::remove(int timerId) +{ + ScopeMutex sm(&__mutex); + __remove(timerId); + __alarms.erase(timerId); +} + +void TimerManager::__remove(int timerId) +{ + auto it = __listenerMap.find(timerId); + if (it != __listenerMap.end()) { + __listenerMap.erase(it); + alarmmgr_remove_alarm(timerId); + _D("Timer %d was removed", timerId); + } +} + +bool TimerManager::__init() +{ + int result = alarmmgr_init(IDENTIFIER); + IF_FAIL_RETURN_TAG(result == ALARMMGR_RESULT_SUCCESS, false, _E, "Alarm manager initialization failed"); + + result = alarmmgr_set_cb(__onAlarmExpired, NULL); + if (result != ALARMMGR_RESULT_SUCCESS) { + alarmmgr_fini(); + _E("Alarm callback registration failed"); + return false; + } + + alarmmgr_remove_all(); + _D("Timer initialized"); + return true; +} + +void TimerManager::__release() +{ + alarmmgr_remove_all(); + alarmmgr_fini(); + __listenerMap.clear(); + _D("Timer released"); +} + +int TimerManager::__onAlarmExpired(int alarmId, void *userdata) +{ + ITimerListener *listener = NULL; + TimerManager *timer = NULL; + + { + ScopeMutex sm(&__mutex); + auto it = __listenerMap.find(alarmId); + IF_FAIL_RETURN_TAG(it != __listenerMap.end(), 0, _W, "Unknown Alarm %d", alarmId); + listener = it->second.first; + timer = it->second.second; + } + + _D("Timer %d expired", alarmId); + + if (listener->onTimerExpired(alarmId)) + return 0; + + _D("Stop repeating TimerManager %d", alarmId); + timer->remove(alarmId); + return 0; +} diff --git a/common/shared/CMakeLists.txt b/common/shared/CMakeLists.txt new file mode 100644 index 0000000..9e52d5b --- /dev/null +++ b/common/shared/CMakeLists.txt @@ -0,0 +1,12 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(target "ctx-shared") + +FILE(GLOB_RECURSE SRCS *.cpp) +MESSAGE("Sources: ${SRCS}") + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${LIB_PKG_LDFLAGS}) +SET_TARGET_PROPERTIES(${target} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${target} PROPERTIES VERSION ${FULLVER}) + +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/common/shared/Json.cpp b/common/shared/Json.cpp new file mode 100644 index 0000000..2f8a1b8 --- /dev/null +++ b/common/shared/Json.cpp @@ -0,0 +1,925 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PATH_DELIM '.' +#define MAX_PRECISION 15 +#define GVAR_VALUES "values" +#define GVAR_TYPES "types" + +using namespace ctx; + +static std::string __double_to_string(double in) +{ + /* Locale-independent double-to-string conversion */ + int prec = MAX_PRECISION; + std::string out; + std::ostringstream ostr; + + ostr.imbue(std::locale("C")); + ostr << std::setprecision(prec) << in; + out = ostr.str(); + + if (out.find('e') == std::string::npos) + return out; + + /* If 'out' is in scientific notation */ + ostr.clear(); + ostr.str(std::string()); + ostr.imbue(std::locale("C")); + + /* Get the number of fraction digits to precisely print the number */ + double number = in * 10; + while (static_cast(number) == 0) { + number *= 10; + ++prec; + } + + ostr << std::fixed << std::setprecision(prec) << in; + out = ostr.str(); + + /* Remove trailing '0' */ + std::size_t found = out.find_last_not_of("0"); + if (found != std::string::npos) + out.erase(found + 1); + + /* If 'out' ends with '.' */ + if (out.back() == '.') + out.erase(out.end() - 1); + + return out; +} + +static double __string_to_double(const char* in) +{ + IF_FAIL_RETURN_TAG(in, 0, _E, "Parameter NULL"); + + double out; + + /* Locale-independent string-to-double conversion */ + std::istringstream istr(in); + istr.imbue(std::locale("C")); + istr >> out; + + return out; +} + +SO_EXPORT Json::Json() : + __jsonNode(NULL) +{ + JsonObject *obj = json_object_new(); + IF_FAIL_VOID_TAG(obj, _E, "Json object construction failed"); + + __jsonNode = json_node_new(JSON_NODE_OBJECT); + if (!__jsonNode) { + json_object_unref(obj); + _E("Json object construction failed"); + } + + json_node_set_object(__jsonNode, obj); + json_object_unref(obj); +} + +SO_EXPORT Json::Json(const Json &j) + : __jsonNode(NULL) +{ + __jsonNode = json_node_copy(j.__jsonNode); + IF_FAIL_VOID_TAG(__jsonNode, _E, "Json object construction failed"); +} + +SO_EXPORT Json::Json(const char *s) + : __jsonNode(NULL) +{ + if (s) { + __parse(s); + } else { + __parse(EMPTY_JSON_OBJECT); + } +} + +SO_EXPORT Json::Json(const std::string &s) + : __jsonNode(NULL) +{ + if (s.empty()) { + __parse(EMPTY_JSON_OBJECT); + } else { + __parse(s.c_str()); + } +} + +SO_EXPORT Json::~Json() +{ + __release(); +} + +void Json::__parse(const char *s) +{ + gboolean result; + JsonParser *parser = NULL; + JsonNode *root = NULL; + + parser = json_parser_new(); + IF_FAIL_VOID_TAG(parser, _E, "Memory allocation failed"); + + result = json_parser_load_from_data(parser, s, -1, NULL); + IF_FAIL_CATCH_TAG(result, _E, "Parsing failed"); + + root = json_parser_get_root(parser); + IF_FAIL_CATCH_TAG(root, _E, "Getting root failed"); + + __jsonNode = json_node_copy(root); + IF_FAIL_CATCH_TAG(__jsonNode, _E, "Copying failed"); + +CATCH: + if (parser) + g_object_unref(parser); +} + +void Json::__release() +{ + if (__jsonNode) { + json_node_free(__jsonNode); + __jsonNode = NULL; + } +} + +SO_EXPORT bool Json::valid() +{ + return (__jsonNode != NULL); +} + +SO_EXPORT Json& Json::operator=(const Json &j) +{ + __release(); + __jsonNode = json_node_copy(j.__jsonNode); + if (!__jsonNode) { + _E("Json object copy failed"); + } + return *this; +} + +SO_EXPORT Json& Json::operator=(const char *s) +{ + __release(); + if (s) { + __parse(s); + } else { + __parse(EMPTY_JSON_OBJECT); + } + return *this; +} + +SO_EXPORT Json& Json::operator=(const std::string &s) +{ + __release(); + if (s.empty()) { + __parse(EMPTY_JSON_OBJECT); + } else { + __parse(s.c_str()); + } + return *this; +} + +SO_EXPORT bool Json::operator==(const Json &rhs) +{ + return __nodeEq(__jsonNode, rhs.__jsonNode); +} + +SO_EXPORT bool Json::operator!=(const Json &rhs) +{ + return !operator==(rhs); +} + +char* Json::__strDup() +{ + IF_FAIL_RETURN_TAG(__jsonNode, NULL, _E, "Json object not initialized"); + + JsonGenerator *jgen = NULL; + char *output = NULL; + + jgen = json_generator_new(); + IF_FAIL_CATCH(jgen); + + json_generator_set_root(jgen, __jsonNode); + output = json_generator_to_data(jgen, NULL); + IF_FAIL_CATCH(output); + + g_object_unref(jgen); + return output; + +CATCH: + if (jgen) { + g_object_unref(jgen); + } + + _E("Memory allocation failed"); + return NULL; +} + +SO_EXPORT std::string Json::str() +{ + std::string output; + char *_s = __strDup(); + IF_FAIL_RETURN(_s, output = EMPTY_JSON_OBJECT); + + output = _s; + g_free(_s); + + return output; +} + +static std::vector __tokenize_path(std::string path) +{ + std::vector tokens; + std::size_t begin = 0; + std::size_t end = path.find(PATH_DELIM, 0); + + while (end != std::string::npos) { + tokens.push_back(path.substr(begin, end - begin)); + begin = end + 1; + end = path.find(PATH_DELIM, begin); + } + + tokens.push_back(path.substr(begin)); + return tokens; +} + +static JsonObject* __traverse(JsonNode *jnode, const char *path, bool force) +{ + IF_FAIL_RETURN_TAG(jnode, NULL, _E, "Invalid parameter"); + + unsigned int depth = 0; + std::vector pathToken; + JsonObject *jobj = NULL; + JsonObject *childObj = NULL; + JsonNode *childNode = NULL; + + jobj = json_node_get_object(jnode); + IF_FAIL_RETURN(jobj, NULL); + + if (path) + pathToken = __tokenize_path(path); + + for (depth = 0; depth < pathToken.size(); depth++) { + if (!json_object_has_member(jobj, pathToken[depth].c_str())) { + if (!force) { + return NULL; + } + childObj = json_object_new(); + IF_FAIL_RETURN_TAG(childObj, NULL, _E, "Memory allocation failed"); + json_object_set_object_member(jobj, pathToken[depth].c_str(), childObj); + } + childNode = json_object_get_member(jobj, pathToken[depth].c_str()); + IF_FAIL_RETURN(childNode && json_node_get_node_type(childNode) == JSON_NODE_OBJECT, NULL); + + jobj = json_node_get_object(childNode); + IF_FAIL_RETURN(jobj, NULL); + } + + return jobj; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, Json &val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.__jsonNode, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + json_object_set_member(jobj, key, val.__jsonNode); + val.__jsonNode = NULL; + val = Json(); + + return true; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, int val) +{ + return set(path, key, static_cast(val)); +} + +SO_EXPORT bool Json::set(const char *path, const char *key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + json_object_set_int_member(jobj, key, val); + return true; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, double val) +{ + return set(path, key, __double_to_string(val)); +} + +SO_EXPORT bool Json::set(const char *path, const char *key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) { + json_object_remove_member(jobj, key); + } + + json_object_set_string_member(jobj, key, val.c_str()); + return true; +} + +SO_EXPORT bool Json::set(const char *path, const char *key, GVariant *val) +{ +#if JSON_CHECK_VERSION(0, 14, 0) + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + const gchar *typeStr = g_variant_get_type_string(val); + IF_FAIL_RETURN_TAG(typeStr, false, _E, "GVariant manipulation failed"); + + json_node_t *node = json_gvariant_serialize(val); + IF_FAIL_RETURN_TAG(node, false, _E, "GVariant manipulation failed"); + + Json gvarJson; + gvarJson.set(NULL, GVAR_TYPES, std::string(typeStr)); + json_object_set_member(json_node_get_object(gvarJson.__jsonNode), GVAR_VALUES, node); + + return set(path, key, gvarJson); +#else + _E("Insufficient version of json-glib(" JSON_VERSION_S ")"); + return false; +#endif +} + +SO_EXPORT bool Json::get(const char *path, const char *key, Json *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonObject *jobj = NULL; + JsonNode *node = NULL; + + jobj = __traverse(__jsonNode, path, false); + IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), false); + + node = json_object_dup_member(jobj, key); + IF_FAIL_RETURN_TAG(node, false, _E, "Memory allocation failed"); + + if (val->__jsonNode) { + json_node_free(val->__jsonNode); + } + val->__jsonNode = node; + + return true; +} + +static JsonNode* __get_value_node(JsonNode *jnode, const char *path, const char *key) +{ + JsonNode *node = NULL; + JsonObject *jobj = NULL; + JsonNodeType ntype; + + jobj = __traverse(jnode, path, false); + IF_FAIL_RETURN(jobj && json_object_has_member(jobj, key), NULL); + + node = json_object_get_member(jobj, key); + ntype = json_node_get_node_type(node); + IF_FAIL_RETURN(ntype == JSON_NODE_VALUE, NULL); + + return node; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, int *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + int64_t v; + + if (get(path, key, &v)) { + *val = v; + return true; + } + + return false; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, int64_t *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = __get_value_node(__jsonNode, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + //TODO: if the string is not a number? + *val = static_cast(__string_to_double(json_node_get_string(node))); + } else { + return false; + } + + return true; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, double *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = __get_value_node(__jsonNode, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_DOUBLE) { + *val = json_node_get_double(node); + } else if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + *val = __string_to_double(json_node_get_string(node)); + } else { + return false; + } + + return true; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, std::string *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + JsonNode *node = __get_value_node(__jsonNode, path, key); + IF_FAIL_RETURN(node, false); + + GType vtype = json_node_get_value_type(node); + IF_FAIL_RETURN(vtype == G_TYPE_STRING, false); + + const char *str_val = json_node_get_string(node); + IF_FAIL_RETURN_TAG(str_val, false, _E, "Getting string failed"); + + *val = str_val; + return true; +} + +SO_EXPORT bool Json::get(const char *path, const char *key, GVariant **val) +{ +#if JSON_CHECK_VERSION(0, 14, 0) + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val, false, _E, "Invalid parameter"); + + bool ret; + Json gvarJson; + ret = get(path, key, &gvarJson); + IF_FAIL_RETURN(ret, false); + + std::string gvarTypes; + ret = gvarJson.get(NULL, GVAR_TYPES, &gvarTypes); + IF_FAIL_RETURN(ret, false); + + Json gvarValues; + ret = gvarJson.get(NULL, GVAR_VALUES, &gvarValues); + IF_FAIL_RETURN(ret, false); + + GError *gerr = NULL; + *val = json_gvariant_deserialize(gvarValues.__jsonNode, gvarTypes.c_str(), &gerr); + HANDLE_GERROR(gerr); + IF_FAIL_RETURN(*val, false); + + return true; +#else + _E("Insufficient version of json-glib(" JSON_VERSION_S ")"); + *val = NULL; + return false; +#endif +} + +SO_EXPORT bool Json::remove(const char *path, const char *key) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonObject *jobj = __traverse(__jsonNode, path, true); + IF_FAIL_RETURN(jobj, false); + + if (json_object_has_member(jobj, key)) + json_object_remove_member(jobj, key); + + return true; +} + +static JsonArray* __get_array(JsonNode *jnode, const char *path, const char *key, bool force) +{ + JsonNode *node = NULL; + JsonArray *arr = NULL; + JsonObject *jobj = NULL; + + jobj = __traverse(jnode, path, force); + IF_FAIL_RETURN(jobj, NULL); + + if (!json_object_has_member(jobj, key)) { + if (force) { + arr = json_array_new(); + IF_FAIL_RETURN_TAG(arr, NULL, _E, "Memory allocation failed"); + json_object_set_array_member(jobj, key, arr); + } else { + return NULL; + } + } + node = json_object_get_member(jobj, key); + IF_FAIL_RETURN_TAG(node && json_node_get_node_type(node) == JSON_NODE_ARRAY, + NULL, _W, "Type mismatched: %s", key); + + return json_node_get_array(node); +} + +SO_EXPORT int Json::getSize(const char *path, const char *key) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, -1, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, -1, _E, "Invalid parameter"); + + JsonArray *jarr = __get_array(__jsonNode, path, key, false); + IF_FAIL_RETURN_TAG(jarr, -1, _D, "Mismatched data type"); + + return json_array_get_length(jarr); +} + +SO_EXPORT bool Json::append(const char *path, const char *key, Json &val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val.__jsonNode, false, _E, "Invalid parameter"); + + JsonArray *arr = __get_array(__jsonNode, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_element(arr, val.__jsonNode); + val.__jsonNode = NULL; + val = Json(); + + return true; +} + +SO_EXPORT bool Json::append(const char *path, const char *key, int val) +{ + return append(path, key, static_cast(val)); +} + +SO_EXPORT bool Json::append(const char *path, const char *key, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = __get_array(__jsonNode, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_int_element(arr, val); + return true; +} + +SO_EXPORT bool Json::append(const char *path, const char *key, double val) +{ + return append(path, key, __double_to_string(val)); +} + +SO_EXPORT bool Json::append(const char *path, const char *key, std::string val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key, false, _E, "Invalid parameter"); + + JsonArray *arr = __get_array(__jsonNode, path, key, true); + IF_FAIL_RETURN(arr, false); + + json_array_add_string_element(arr, val.c_str()); + return true; +} + +static JsonNode* __get_array_elem(JsonNode *jnode, const char *path, const char *key, int index) +{ + JsonArray *jarr = __get_array(jnode, path, key, false); + IF_FAIL_RETURN_TAG(jarr, NULL, _W, "Mismatched data type"); + + int size = json_array_get_length(jarr); + IF_FAIL_RETURN(size > index, NULL); + + JsonNode *node = json_array_get_element(jarr, index); + IF_FAIL_RETURN_TAG(node, NULL, _E, "Failed to get an array element"); + + return node; +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, Json &val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(val.__jsonNode && key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + + JsonObject *obj = json_node_get_object(val.__jsonNode); + IF_FAIL_RETURN_TAG(obj, false, _E, "Getting object failed"); + + json_node_set_object(node, obj); + json_node_free(val.__jsonNode); + val.__jsonNode = NULL; + val = Json(); + + return true; +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, int val) +{ + return setAt(path, key, index, static_cast(val)); +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, int64_t val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_int(node, val); + return true; +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, double val) +{ + return setAt(path, key, index, __double_to_string(val)); +} + +SO_EXPORT bool Json::setAt(const char *path, const char *key, int index, std::string val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN_TAG(node, false, _W, "Out of range"); + IF_FAIL_RETURN_TAG(json_node_get_node_type(node) == JSON_NODE_VALUE, false, _E, "Type mismatched: %s[%d]", key, index); + + json_node_set_string(node, val.c_str()); + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, Json *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNode *nodeCopy = json_node_copy(node); + IF_FAIL_RETURN_TAG(nodeCopy, false, _E, "Memory allocation failed"); + + if (val->__jsonNode) { + json_node_free(val->__jsonNode); + } + val->__jsonNode = nodeCopy; + + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, int *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + int64_t v; + if (getAt(path, key, index, &v)) { + *val = v; + return true; + } + + return false; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, int64_t *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + *val = static_cast(__string_to_double(json_node_get_string(node))); + } else { + _E("Type mismatched: %s", key); + return false; + } + + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, double *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + if (vtype == G_TYPE_DOUBLE) { + *val = json_node_get_double(node); + } else if (vtype == G_TYPE_INT64) { + *val = json_node_get_int(node); + } else if (vtype == G_TYPE_STRING) { + *val = __string_to_double(json_node_get_string(node)); + } else { + _E("Type mismatched: %s", key); + return false; + } + + return true; +} + +SO_EXPORT bool Json::getAt(const char *path, const char *key, int index, std::string *val) +{ + IF_FAIL_RETURN_TAG(this->__jsonNode, false, _E, "Json object not initialized"); + IF_FAIL_RETURN_TAG(key && val && index >= 0, false, _E, "Invalid parameter"); + + JsonNode *node = __get_array_elem(__jsonNode, path, key, index); + IF_FAIL_RETURN(node, false); + + JsonNodeType ntype = json_node_get_node_type(node); + IF_FAIL_RETURN_TAG(ntype == JSON_NODE_VALUE, false, _E, "Type mismatched: %s", key); + + GType vtype = json_node_get_value_type(node); + IF_FAIL_RETURN_TAG(vtype == G_TYPE_STRING, false, _E, "Type mismatched: %s", key); + + const char *str_val = json_node_get_string(node); + IF_FAIL_RETURN_TAG(str_val, false, _E, "Getting string failed"); + + *val = str_val; + return true; +} + +bool Json::__getMembers(json_node_t *node, std::list &list) +{ + IF_FAIL_RETURN(node, false); + list.clear(); + + JsonObject *jobj = json_node_get_object(node); + IF_FAIL_RETURN_TAG(jobj, false, _E, "Getting Json object failed"); + + GList *members = json_object_get_members(jobj); + IF_FAIL_RETURN(members, true); + + for (GList *it = g_list_first(members); it; it = g_list_next(it)) { + const char *key = static_cast(it->data); + if (!key) { + list.clear(); + g_list_free(members); + _E("Member list extraction failed"); + return false; + } + + list.push_back(key); + } + + g_list_free(members); + return true; +} + +SO_EXPORT bool Json::getKeys(std::list* list) +{ + IF_FAIL_RETURN_TAG(list, false, _E, "Invalid parameter"); + return __getMembers(__jsonNode, *list); +} + +bool Json::__nodeEq(json_node_t *lhs, json_node_t *rhs) +{ + IF_FAIL_RETURN(lhs && rhs, false); + + JsonNodeType ltype = json_node_get_node_type(lhs); + JsonNodeType rtype = json_node_get_node_type(rhs); + IF_FAIL_RETURN(ltype == rtype, false); + + switch (ltype) { + case JSON_NODE_VALUE: + IF_FAIL_RETURN(__valueEq(lhs, rhs), false); + break; + case JSON_NODE_OBJECT: + IF_FAIL_RETURN(__objectEq(lhs, rhs), false); + break; + case JSON_NODE_ARRAY: + IF_FAIL_RETURN(__arrayEq(lhs, rhs), false); + break; + default: + _W("Unsupported type"); + return false; + } + + return true; +} + +bool Json::__valueEq(json_node_t *lhs, json_node_t *rhs) +{ + GType ltype = json_node_get_value_type(lhs); + GType rtype = json_node_get_value_type(rhs); + IF_FAIL_RETURN(ltype == rtype, false); + + switch (ltype) { + case G_TYPE_INT64: + return json_node_get_int(lhs) == json_node_get_int(rhs); + case G_TYPE_DOUBLE: + return json_node_get_double(lhs) == json_node_get_double(rhs); + case G_TYPE_STRING: + return STR_EQ(json_node_get_string(lhs), json_node_get_string(rhs)); + default: + _W("Unsupported type"); + return false; + } +} + +bool Json::__objectEq(json_node_t *lhs, json_node_t *rhs) +{ + std::list lm, rm; + IF_FAIL_RETURN(__getMembers(lhs, lm), false); + IF_FAIL_RETURN(__getMembers(rhs, rm), false); + IF_FAIL_RETURN(lm.size() == rm.size(), false); + + lm.sort(); + rm.sort(); + + std::list::iterator lit, rit; + lit = lm.begin(); + rit = rm.begin(); + + while (lit != lm.end()) { + IF_FAIL_RETURN(*lit == *rit, false); + + json_node_t *lhsChild = json_object_get_member(json_node_get_object(lhs), (*lit).c_str()); + json_node_t *rhsChild = json_object_get_member(json_node_get_object(rhs), (*rit).c_str()); + IF_FAIL_RETURN(__nodeEq(lhsChild, rhsChild), false); + + ++lit; + ++rit; + } + + return true; +} + +bool Json::__arrayEq(json_node_t *lhs, json_node_t *rhs) +{ + JsonArray *larr = json_node_get_array(lhs); + JsonArray *rarr = json_node_get_array(rhs); + + int size = json_array_get_length(larr); + IF_FAIL_RETURN(size == static_cast(json_array_get_length(rarr)), false); + + for (int i = 0; i < size; ++i) { + json_node_t *lhsChild = json_array_get_element(larr, i); + json_node_t *rhsChild = json_array_get_element(rarr, i); + IF_FAIL_RETURN(__nodeEq(lhsChild, rhsChild), false); + } + + return true; +} diff --git a/common/shared/MyPlaceTypes.cpp b/common/shared/MyPlaceTypes.cpp new file mode 100644 index 0000000..c5c2600 --- /dev/null +++ b/common/shared/MyPlaceTypes.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +SO_EXPORT bool ctx::operator==(const ctx::Place &p1, const ctx::Place &p2) +{ + bool ret = p1.categId == p2.categId + && p1.categConfidence == p2.categConfidence + && p1.name == p2.name + && p1.createDate == p2.createDate + && p1.locationValid == p2.locationValid; + if (ret && p1.locationValid) { + // Check location only if it is valid / filled + if (p1.location.latitude != p2.location.latitude + || p1.location.longitude != p2.location.longitude + || p1.location.accuracy != p2.location.accuracy) { + ret = false; + } + } + if (ret) { + for (std::pair ap : p1.wifiAps) { + // Check only MAC addresses because network names are only addition. + if (p2.wifiAps.find(ap.first) == p2.wifiAps.end()) { + ret = false; + break; + } + } + } + return ret; +} diff --git a/common/shared/ScopeMutex.cpp b/common/shared/ScopeMutex.cpp new file mode 100644 index 0000000..8bc0b51 --- /dev/null +++ b/common/shared/ScopeMutex.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +SO_EXPORT ctx::ScopeMutex::ScopeMutex(GMutex *m) : + __mutex(m) +{ + g_mutex_lock(__mutex); +} + +SO_EXPORT ctx::ScopeMutex::~ScopeMutex() +{ + g_mutex_unlock(__mutex); +} -- 2.7.4 From 4d1f4dfe6aa30270e933cd264476f9161c5069c3 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Thu, 30 Mar 2017 13:49:02 +0900 Subject: [PATCH 12/16] Integrate the legacy context-common code and headers (2/2) This patch enables to build the imported legacy code and include built libraries and headers to the produced RPMs. Change-Id: I1103fcea1ab1891a00995609b1ae05a0a8612359 Signed-off-by: Mu-Woong Lee --- CMakeLists.txt | 13 ++++++++++++- common/CMakeLists.txt | 31 +++++++++++++++++++++++++++++++ common/include/DBusTypes.h | 6 +++--- packaging/context-provider.spec | 32 ++++++++++++++++++++------------ pkg-config.pc.in | 13 +++++++++++++ src/CMakeLists.txt | 16 +++++++--------- 6 files changed, 86 insertions(+), 25 deletions(-) create mode 100644 common/CMakeLists.txt create mode 100644 pkg-config.pc.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c21cb6..a38dc22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,12 @@ SET(target_dir "context-service") # Common Options INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/common/include ${CMAKE_CURRENT_SOURCE_DIR}/src/shared ) + +SET(DEPS "glib-2.0 gio-2.0 json-glib-1.0 sqlite3 capi-base-common dlog alarm-service libtzplatform-config") + ADD_DEFINITIONS(-O2 -Wall -fPIC -fdata-sections -ffunction-sections) ADD_DEFINITIONS(-fvisibility=hidden) ADD_DEFINITIONS(-DLOG_TAG="CONTEXT") @@ -17,8 +21,15 @@ SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIC -Wl,--as-needed -Wl, INSTALL( DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${target_dir}/internal + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${target_dir}/legacy + FILES_MATCHING PATTERN "*.h" +) + +INSTALL( + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/common/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${target_dir}/legacy FILES_MATCHING PATTERN "*.h" ) +ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(src) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 0000000..5168e02 --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,31 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +INCLUDE(FindPkgConfig) +pkg_check_modules(LIB_PKG REQUIRED ${DEPS}) + +FOREACH(flag ${LIB_PKG_CFLAGS}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}") +ENDFOREACH(flag) + +SET(PC_NAME "context-common-legacy") +SET(VERSION ${FULLVER}) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(PC_INCLUDE "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/context-service/legacy") +SET(PC_LIBDIR "${CMAKE_INSTALL_LIBDIR}") +SET(PC_DESCRIPTION "Tizen Context-Service Shared Library") +SET(PC_REQUIRED "${DEPS}") +SET(PC_LDFLAGS "-lctx-shared -lctx-server -lctx-client") +CONFIGURE_FILE( + ${CMAKE_SOURCE_DIR}/pkg-config.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${PC_NAME}.pc + @ONLY +) + +INSTALL( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PC_NAME}.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig +) + +ADD_SUBDIRECTORY(shared) +ADD_SUBDIRECTORY(client) +ADD_SUBDIRECTORY(server) diff --git a/common/include/DBusTypes.h b/common/include/DBusTypes.h index 1921e30..ae6af3c 100644 --- a/common/include/DBusTypes.h +++ b/common/include/DBusTypes.h @@ -17,9 +17,9 @@ #ifndef _CONTEXT_DBUS_TYPES_H_ #define _CONTEXT_DBUS_TYPES_H_ -#define DBUS_DEST "org.tizen.context" -#define DBUS_PATH "/org/tizen/context" -#define DBUS_IFACE "org.tizen.context" +#define DBUS_DEST "org.tizen.contextagent" +#define DBUS_PATH "/org/tizen/contextagent/Legacy" +#define DBUS_IFACE "org.tizen.contextagent.Legacy" #define DBUS_TIMEOUT 3000 #define METHOD_REQUEST "Request" diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index 8cf4fde..3325cb2 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -1,6 +1,6 @@ Name: context-provider Summary: Context Provider -Version: 0.9.14 +Version: 0.10.0 Release: 1 Group: Service/Context License: Apache-2.0 @@ -16,24 +16,31 @@ Provides: context-provider-profile_ivi = %{version}-%{release} BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(gmodule-2.0) -BuildRequires: pkgconfig(context-common) +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(alarm-service) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-device) BuildRequires: pkgconfig(capi-system-runtime-info) BuildRequires: pkgconfig(capi-media-sound-manager) BuildRequires: pkgconfig(capi-network-wifi) -BuildRequires: pkgconfig(sensor) -BuildRequires: pkgconfig(motion) +#BuildRequires: pkgconfig(sensor) +#BuildRequires: pkgconfig(motion) # TODO TEMPORARY STATEMENT # if it is mobile or BASE2 (when we have migrated everything into BASE2, we can remove this if statement) # Common also supports extension mode. %if "%{?BUILD_PROFILE}" != "tv" && "%{?BUILD_PROFILE}" != "wearable" && "%{?BUILD_PROFILE}" != "ivi" -BuildRequires: pkgconfig(capi-appfw-package-manager) -BuildRequires: pkgconfig(capi-appfw-application) -BuildRequires: pkgconfig(capi-appfw-app-manager) +#BuildRequires: pkgconfig(capi-appfw-package-manager) +#BuildRequires: pkgconfig(capi-appfw-application) +#BuildRequires: pkgconfig(capi-appfw-app-manager) BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) @@ -42,9 +49,9 @@ BuildRequires: pkgconfig(contacts-service2) BuildRequires: pkgconfig(tapi) BuildRequires: pkgconfig(capi-telephony) BuildRequires: pkgconfig(capi-messaging-email) -BuildRequires: pkgconfig(capi-content-media-content) +#BuildRequires: pkgconfig(capi-content-media-content) BuildRequires: pkgconfig(libmedia-utils) -BuildRequires: pkgconfig(capi-location-manager) +#BuildRequires: pkgconfig(capi-location-manager) BuildRequires: pkgconfig(capi-geofence-manager) %endif @@ -86,9 +93,9 @@ rm -rf %{buildroot} %files %manifest packaging/%{name}.manifest %{_libdir}/*.so* -%{_libdir}/context-service/*activity.so* +#%{_libdir}/context-service/*activity.so* %{_libdir}/context-service/*custom.so* -%{_libdir}/context-service/*sensor.so* +#%{_libdir}/context-service/*sensor.so* %{_libdir}/context-service/*system.so* %{_libdir}/context-service/*time.so* %license LICENSE @@ -103,7 +110,8 @@ Context Provider Shared Header (DEV) %files devel %manifest packaging/%{name}.manifest -%{_includedir}/context-service/internal/*.h +%{_includedir}/context-service/legacy/*.h +%{_libdir}/pkgconfig/*.pc # TODO TEMPORARY STATEMENT # if it is mobile or BASE2 (when we have migrated everything into BASE2, we can remove this if statement) diff --git a/pkg-config.pc.in b/pkg-config.pc.in new file mode 100644 index 0000000..378b991 --- /dev/null +++ b/pkg-config.pc.in @@ -0,0 +1,13 @@ +#Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=@PREFIX@ +libdir=@PC_LIBDIR@ +includedir=@PC_INCLUDE@ + +Name: @PC_NAME@ +Description: @PC_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index babd7c3..2472289 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,26 +1,24 @@ SET(target_shared "${target_prefix}-shared") -SET(DEPS - context-common -) +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lctx-shared -lctx-server") ADD_SUBDIRECTORY(shared) -ADD_SUBDIRECTORY(activity) +#ADD_SUBDIRECTORY(activity) ADD_SUBDIRECTORY(custom) -ADD_SUBDIRECTORY(sensor) +#ADD_SUBDIRECTORY(sensor) ADD_SUBDIRECTORY(system) ADD_SUBDIRECTORY(time) IF("${FEATURES}" STREQUAL "extended") -ADD_SUBDIRECTORY(app-stats) -ADD_SUBDIRECTORY(battery-stats) +#ADD_SUBDIRECTORY(app-stats) +#ADD_SUBDIRECTORY(battery-stats) ADD_SUBDIRECTORY(call) ADD_SUBDIRECTORY(contacts) ADD_SUBDIRECTORY(email) ADD_SUBDIRECTORY(geofence) ADD_SUBDIRECTORY(headphone) -ADD_SUBDIRECTORY(media-stats) +#ADD_SUBDIRECTORY(media-stats) ADD_SUBDIRECTORY(message) #ADD_SUBDIRECTORY(my-place) -ADD_SUBDIRECTORY(social-stats) +#ADD_SUBDIRECTORY(social-stats) ADD_SUBDIRECTORY(wifi) ENDIF("${FEATURES}" STREQUAL "extended") -- 2.7.4 From 846e3f484582db759232a334ce6054c34cd4a3cf Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Tue, 11 Apr 2017 11:02:38 +0900 Subject: [PATCH 13/16] Remove a redundant member variable from message.h Change-Id: I95875ce94a41bb5a1280cb791abcdc5f71c2b430 Signed-off-by: Mu-Woong Lee --- src/message/Message.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/message/Message.h b/src/message/Message.h index 0553cdc..b202588 100644 --- a/src/message/Message.h +++ b/src/message/Message.h @@ -38,7 +38,6 @@ namespace ctx { private: msg_handle_t __messageHandle; - bool __beingSubscribed; bool __setCallback(); void __unsetCallback(); -- 2.7.4 From 15cfe61b7406828f617a12107b040d3fa2cf6bb9 Mon Sep 17 00:00:00 2001 From: Somin Kim Date: Tue, 11 Apr 2017 11:30:47 +0900 Subject: [PATCH 14/16] Modified secure log macro Change-Id: Ia16f7628255fc20fdc8b9162ecbab4a802e8e864 Signed-off-by: Somin Kim --- common/include/Types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/include/Types.h b/common/include/Types.h index aaadd57..054639b 100644 --- a/common/include/Types.h +++ b/common/include/Types.h @@ -29,7 +29,7 @@ #define _E SLOGE #define _SI SECURE_SLOGI #define _SD SECURE_SLOGD -#define _SW SECURE_LOGW +#define _SW SECURE_SLOGW #define _SE SECURE_SLOGE /* Color code for dlog */ -- 2.7.4 From 59dad3e7e11f29d1c5a6066ae3e8d1ed1e71da9c Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Tue, 11 Apr 2017 15:59:23 +0900 Subject: [PATCH 15/16] Disable WiFi context provider It uses deprecated wifi APIs, and they will be obsoleted. Anyway, the new job-scheduler will replace all of this package, I thus simply disable the wifi-related code for now. Change-Id: I28fcb768db78ab09ad4441ccdc96bbc7ef214310 Signed-off-by: Mu-Woong Lee --- packaging/context-provider.spec | 2 +- src/CMakeLists.txt | 2 +- src/shared/CMakeLists.txt | 1 - src/shared/WifiWrapper.cpp | 189 ---------------------------------------- src/shared/WifiWrapper.h | 76 ---------------- 5 files changed, 2 insertions(+), 268 deletions(-) delete mode 100644 src/shared/WifiWrapper.cpp delete mode 100644 src/shared/WifiWrapper.h diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index 3325cb2..3dbd146 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -30,7 +30,7 @@ BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(capi-system-device) BuildRequires: pkgconfig(capi-system-runtime-info) BuildRequires: pkgconfig(capi-media-sound-manager) -BuildRequires: pkgconfig(capi-network-wifi) +#BuildRequires: pkgconfig(capi-network-wifi) #BuildRequires: pkgconfig(sensor) #BuildRequires: pkgconfig(motion) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2472289..fecf577 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,5 +20,5 @@ ADD_SUBDIRECTORY(headphone) ADD_SUBDIRECTORY(message) #ADD_SUBDIRECTORY(my-place) #ADD_SUBDIRECTORY(social-stats) -ADD_SUBDIRECTORY(wifi) +#ADD_SUBDIRECTORY(wifi) ENDIF("${FEATURES}" STREQUAL "extended") diff --git a/src/shared/CMakeLists.txt b/src/shared/CMakeLists.txt index 7abe206..fc20fe4 100644 --- a/src/shared/CMakeLists.txt +++ b/src/shared/CMakeLists.txt @@ -2,7 +2,6 @@ SET(DEPS ${DEPS} capi-system-info capi-system-runtime-info capi-media-sound-manager - capi-network-wifi ) FILE(GLOB SRCS *.cpp) diff --git a/src/shared/WifiWrapper.cpp b/src/shared/WifiWrapper.cpp deleted file mode 100644 index c3097bf..0000000 --- a/src/shared/WifiWrapper.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "WifiWrapper.h" - -#define SET_CALLBACK(type, setFunc) \ - __cb##type = callback; \ - __cbData##type = userData; \ - if (__enabled##type) \ - return WIFI_ERROR_NONE; \ - int err = setFunc(__cbFunc##type, NULL); \ - if (err == WIFI_ERROR_NONE) \ - __enabled##type = true; \ - return err; - -#define UNSET_CALLBACK(type, unsetFunc) \ - __cb##type = NULL; \ - __cbData##type = NULL; \ - if (!__enabled##type) \ - return WIFI_ERROR_NONE; \ - for (auto it : __instances) { \ - if (it->__cb##type != NULL) \ - return WIFI_ERROR_NONE; \ - } \ - unsetFunc(); \ - return WIFI_ERROR_NONE; - -using namespace ctx; - -std::set WifiWrapper::__instances; -bool WifiWrapper::__enabledDeviceState = false; -bool WifiWrapper::__enabledConnectionState = false; -bool WifiWrapper::__enabledBackgroundScan = false; - -SO_EXPORT WifiWrapper::WifiWrapper() : - __cbDeviceState(NULL), - __cbConnectionState(NULL), - __cbBackgroundScan(NULL), - __cbDataDeviceState(NULL), - __cbDataConnectionState(NULL), - __cbDataBackgroundScan(NULL) -{ - if (__instances.empty()) - __init(); - - __instances.insert(this); - - _D("#instances = %d", __instances.size()); -} - -SO_EXPORT WifiWrapper::~WifiWrapper() -{ - if (__cbDeviceState) - unsetDeviceStateChangedCb(); - - if (__cbConnectionState) - unsetConnectionStateChangedCb(); - - if (__cbBackgroundScan) - unsetBackgroundScanCb(); - - __instances.erase(this); - - if (__instances.empty()) - __release(); - - _D("#instances = %d", __instances.size()); -} - -SO_EXPORT int WifiWrapper::isActivated(bool *activated) -{ - return wifi_is_activated(activated); -} - -SO_EXPORT int WifiWrapper::getConnectionState(wifi_connection_state_e *state) -{ - return wifi_get_connection_state(state); -} - -SO_EXPORT int WifiWrapper::getConnectedAP(wifi_ap_h *ap) -{ - return wifi_get_connected_ap(ap); -} - -SO_EXPORT int WifiWrapper::getEssidFromAP(wifi_ap_h ap, char **essid) -{ - return wifi_ap_get_essid(ap, essid); -} - -SO_EXPORT int WifiWrapper::getBssidFromAP(wifi_ap_h ap, char **bssid) -{ - return wifi_ap_get_bssid(ap, bssid); -} - -SO_EXPORT int WifiWrapper::destroyAP(wifi_ap_h ap) -{ - return wifi_ap_destroy(ap); -} - -SO_EXPORT int WifiWrapper::setDeviceStateChangedCb(wifi_device_state_changed_cb callback, void *userData) -{ - SET_CALLBACK(DeviceState, wifi_set_device_state_changed_cb) -} - -SO_EXPORT int WifiWrapper::unsetDeviceStateChangedCb() -{ - UNSET_CALLBACK(DeviceState, wifi_unset_device_state_changed_cb) -} - -SO_EXPORT int WifiWrapper::setConnectionStateChangedCb(wifi_connection_state_changed_cb callback, void *userData) -{ - SET_CALLBACK(ConnectionState, wifi_set_connection_state_changed_cb) -} - -SO_EXPORT int WifiWrapper::unsetConnectionStateChangedCb() -{ - UNSET_CALLBACK(ConnectionState, wifi_unset_connection_state_changed_cb) -} - -SO_EXPORT int WifiWrapper::setBackgroundScanCb(wifi_scan_finished_cb callback, void *userData) -{ - SET_CALLBACK(BackgroundScan, wifi_set_background_scan_cb) -} - -SO_EXPORT int WifiWrapper::unsetBackgroundScanCb() -{ - UNSET_CALLBACK(BackgroundScan, wifi_unset_background_scan_cb) -} - -SO_EXPORT int WifiWrapper::scan(wifi_scan_finished_cb callback, void *userData) -{ - return wifi_scan(callback, userData); -} - -SO_EXPORT int WifiWrapper::foreachFoundAP(wifi_found_ap_cb callback, void *userData) -{ - return wifi_foreach_found_aps(callback, userData); -} - -void WifiWrapper::__init() -{ - _D("Initialize"); - int err = wifi_initialize(); - IF_FAIL_VOID_TAG(err == WIFI_ERROR_NONE, _E, "wifi_initialize() failed"); -} - -void WifiWrapper::__release() -{ - _D("Deinitialize"); - wifi_deinitialize(); -} - -void WifiWrapper::__cbFuncDeviceState(wifi_device_state_e state, void *userData) -{ - for (auto it : __instances) { - if (it->__cbDeviceState) - it->__cbDeviceState(state, it->__cbDataDeviceState); - } -} - -void WifiWrapper::__cbFuncConnectionState(wifi_connection_state_e state, wifi_ap_h ap, void *userData) -{ - for (auto it : __instances) { - if (it->__cbConnectionState) - it->__cbConnectionState(state, ap, it->__cbDataConnectionState); - } -} - -void WifiWrapper::__cbFuncBackgroundScan(wifi_error_e error_code, void *userData) -{ - for (auto it : __instances) { - if (it->__cbBackgroundScan) - it->__cbBackgroundScan(error_code, it->__cbDataBackgroundScan); - } -} diff --git a/src/shared/WifiWrapper.h b/src/shared/WifiWrapper.h deleted file mode 100644 index 3dcd354..0000000 --- a/src/shared/WifiWrapper.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CONTEXT_WIFI_WRAPPER_H_ -#define _CONTEXT_WIFI_WRAPPER_H_ - -#include -#include - -namespace ctx { - - /* Wifi API does not support multiple sessions in one process. - This is a wrapper class to walkaround the linitation of Wifi API. */ - class WifiWrapper { - public: - WifiWrapper(); - ~WifiWrapper(); - - int isActivated(bool *activated); - - int getConnectionState(wifi_connection_state_e *state); - int getConnectedAP(wifi_ap_h *ap); - - int getEssidFromAP(wifi_ap_h ap, char **essid); - int getBssidFromAP(wifi_ap_h ap, char **bssid); - int destroyAP(wifi_ap_h ap); - - int setDeviceStateChangedCb(wifi_device_state_changed_cb callback, void *userData); - int unsetDeviceStateChangedCb(); - - int setConnectionStateChangedCb(wifi_connection_state_changed_cb callback, void *userData); - int unsetConnectionStateChangedCb(); - - int setBackgroundScanCb(wifi_scan_finished_cb callback, void *userData); - int unsetBackgroundScanCb(); - - int scan(wifi_scan_finished_cb callback, void *userData); - int foreachFoundAP(wifi_found_ap_cb callback, void *userData); - - private: - void __init(); - void __release(); - - static void __cbFuncDeviceState(wifi_device_state_e state, void *userData); - static void __cbFuncConnectionState(wifi_connection_state_e state, wifi_ap_h ap, void *userData); - static void __cbFuncBackgroundScan(wifi_error_e error_code, void *userData); - - wifi_device_state_changed_cb __cbDeviceState; - wifi_connection_state_changed_cb __cbConnectionState; - wifi_scan_finished_cb __cbBackgroundScan; - - void *__cbDataDeviceState; - void *__cbDataConnectionState; - void *__cbDataBackgroundScan; - - static std::set __instances; - static bool __enabledDeviceState; - static bool __enabledConnectionState; - static bool __enabledBackgroundScan; - }; -} - -#endif /* _CONTEXT_WIFI_WRAPPER_H_ */ -- 2.7.4 From bc44185b4cd7ee308ecca6ab771a5ae701c34c4e Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Wed, 12 Apr 2017 10:26:13 +0900 Subject: [PATCH 16/16] Enable the legacy app/social stats providers Change-Id: Ia85db0d4c46985c4aaad05cfc8eac8aa12e01bdd Signed-off-by: Mu-Woong Lee --- packaging/context-provider.spec | 6 +++--- src/CMakeLists.txt | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index 3dbd146..f4988ad 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -38,9 +38,9 @@ BuildRequires: pkgconfig(capi-media-sound-manager) # if it is mobile or BASE2 (when we have migrated everything into BASE2, we can remove this if statement) # Common also supports extension mode. %if "%{?BUILD_PROFILE}" != "tv" && "%{?BUILD_PROFILE}" != "wearable" && "%{?BUILD_PROFILE}" != "ivi" -#BuildRequires: pkgconfig(capi-appfw-package-manager) -#BuildRequires: pkgconfig(capi-appfw-application) -#BuildRequires: pkgconfig(capi-appfw-app-manager) +BuildRequires: pkgconfig(capi-appfw-package-manager) +BuildRequires: pkgconfig(capi-appfw-application) +BuildRequires: pkgconfig(capi-appfw-app-manager) BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(pkgmgr) BuildRequires: pkgconfig(pkgmgr-info) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fecf577..a39ccc1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,7 @@ ADD_SUBDIRECTORY(system) ADD_SUBDIRECTORY(time) IF("${FEATURES}" STREQUAL "extended") -#ADD_SUBDIRECTORY(app-stats) +ADD_SUBDIRECTORY(app-stats) #ADD_SUBDIRECTORY(battery-stats) ADD_SUBDIRECTORY(call) ADD_SUBDIRECTORY(contacts) @@ -19,6 +19,6 @@ ADD_SUBDIRECTORY(headphone) #ADD_SUBDIRECTORY(media-stats) ADD_SUBDIRECTORY(message) #ADD_SUBDIRECTORY(my-place) -#ADD_SUBDIRECTORY(social-stats) +ADD_SUBDIRECTORY(social-stats) #ADD_SUBDIRECTORY(wifi) ENDIF("${FEATURES}" STREQUAL "extended") -- 2.7.4