From 78bc353fc42499e47696cbb20f4a50a7bb965a60 Mon Sep 17 00:00:00 2001 From: Lukasz Bardeli Date: Wed, 9 Aug 2017 10:47:39 +0200 Subject: [PATCH 01/16] [version] 1.94 Change-Id: I753bfbe604e766f46a55ef671900d178bf47227f Signed-off-by: Lukasz Bardeli --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 3f76fdf..9a3f04d 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.93 +Version: 1.94 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From 6192a68b8f65365593244c0a268ce237fffff4ec Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Thu, 10 Aug 2017 10:58:27 +0200 Subject: [PATCH 02/16] [Application] Fixing type of returned objects The method getBatteryUsageInfo should provide objects of type ApplicationBatteryUsage, not simply Object. Change-Id: I8371464bf55e3c18fba63bebd050d57521efcd12 Signed-off-by: Szymon Jastrzebski --- src/application/application_api.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/application/application_api.js b/src/application/application_api.js index 12bfeef..7366398 100755 --- a/src/application/application_api.js +++ b/src/application/application_api.js @@ -535,7 +535,12 @@ ApplicationManager.prototype.getBatteryUsageInfo = function() { if (native.isFailure(result)) { native.callIfPossible(args.errorCallback, native.getErrorObject(result)); } else { - args.successCallback(native.getResultObject(result)); + var data = native.getResultObject(result); + var resultArray = []; + data.forEach(function (i) { + resultArray.push(new ApplicationBatteryUsage(i)); + }); + args.successCallback(resultArray); } }; @@ -1260,7 +1265,7 @@ function ApplicationCertificate(data) { }); } -// class ApplicationMetaData //////////////////////////////////////////////////// +// class ApplicationMetaData /////////////////////////////////////////////////////// function ApplicationMetaData(data) { Object.defineProperties(this, { key : { -- 2.7.4 From 64ec756593351f22231276a56253e4c08698cc9a Mon Sep 17 00:00:00 2001 From: Tomasz Marciniak Date: Thu, 10 Aug 2017 10:26:32 +0200 Subject: [PATCH 03/16] [Systeminfo] Get status and mac address if WiFi is off [Feature] Status and mac address of the WiFi interface were retrieved only if device was connected to some AP. Now they are retrieved always. [Verification] Code compiles. TCT pass rate 100% Change-Id: Ia16d22f204a71d4084e13ce5ab647b60c7acee60 Signed-off-by: Tomasz Marciniak --- src/systeminfo/systeminfo_properties_manager.cc | 132 +++++++++++------------- 1 file changed, 62 insertions(+), 70 deletions(-) diff --git a/src/systeminfo/systeminfo_properties_manager.cc b/src/systeminfo/systeminfo_properties_manager.cc index 75bb33c..724e0f1 100644 --- a/src/systeminfo/systeminfo_properties_manager.cc +++ b/src/systeminfo/systeminfo_properties_manager.cc @@ -681,106 +681,98 @@ PlatformResult SysteminfoPropertiesManager::ReportWifiNetwork(picojson::object* }; // check if wifi is activated - bool activated = false; - error = wifi_manager_is_activated(wifi_manager, &activated); + error = wifi_manager_is_activated(wifi_manager, &result_status); if (WIFI_MANAGER_ERROR_NONE != error) { std::string log_msg = "Checking if wifi is activated failed: " + std::string(get_error_message(error)); return LogAndCreateResult( ErrorCode::UNKNOWN_ERR, log_msg, ("wifi_manager_is_activated error: %d (%s)", error, get_error_message(error))); + } + + //gathering mac address + char* mac = nullptr; + error = wifi_manager_get_mac_address(wifi_manager, &mac); + if (WIFI_MANAGER_ERROR_NONE == error && nullptr != mac) { + SLoggerD("MAC address fetched: %s", mac); + result_mac_address = mac; + free(mac); } else { - LoggerD("WIFI activated check succeed"); + std::string log_msg = "Failed to get mac address: " + std::string(get_error_message(error)); + return LogAndCreateResult( + ErrorCode::UNKNOWN_ERR, log_msg, + ("wifi_manager_get_mac_address error: %d (%s)", error, get_error_message(error))); } wifi_manager_ap_h wifi_ap_handle = nullptr; - if (activated) { + if (result_status) { LoggerD("Wifi is activated"); error = wifi_manager_get_connected_ap(wifi_manager, &wifi_ap_handle); - if (WIFI_MANAGER_ERROR_NONE != error) { + if (WIFI_MANAGER_ERROR_NONE != error && WIFI_MANAGER_ERROR_NO_CONNECTION != error) { LoggerD("Error while wifi_get_connnected_ap: %s", get_error_message(error)); - // in case of no connection, ignore error and leave status as false - if (WIFI_MANAGER_ERROR_NO_CONNECTION != error) { - std::string log_msg = "Cannot get connected access point handle: " + + std::string log_msg = "Cannot get connected access point handle: " + std::string(get_error_message(error)); return LogAndCreateResult( ErrorCode::UNKNOWN_ERR, log_msg, ("wifi_manager_get_connected_ap error: %d (%s)", error, get_error_message(error))); } - } else { - //if getting connected AP succeed, set status on true - result_status = true; - } - } - if (result_status) { std::unique_ptr::type, int(*)(wifi_manager_ap_h)> wifi_ap_handle_ptr(wifi_ap_handle, &wifi_manager_ap_destroy); // automatically release the memory - //gathering mac address - char* mac = nullptr; - error = wifi_manager_get_mac_address(wifi_manager, &mac); - if (WIFI_MANAGER_ERROR_NONE == error && nullptr != mac) { - SLoggerD("MAC address fetched: %s", mac); - result_mac_address = mac; - free(mac); - } else { - std::string log_msg = "Failed to get mac address: " + std::string(get_error_message(error)); - return LogAndCreateResult( - ErrorCode::UNKNOWN_ERR, log_msg, - ("wifi_manager_get_mac_address error: %d (%s)", error, get_error_message(error))); - } - - //refreshing access point information - error = wifi_manager_ap_refresh(wifi_ap_handle); - if (WIFI_MANAGER_ERROR_NONE != error) { - std::string log_msg = "Failed to refresh access point information: " + - std::string(get_error_message(error)); - return LogAndCreateResult( - ErrorCode::UNKNOWN_ERR, log_msg, - ("wifi_manager_ap_refresh error: %d (%s)", error, get_error_message(error))); - } - - //gathering ssid - char* essid = nullptr; - error = wifi_manager_ap_get_essid(wifi_ap_handle, &essid); - if (WIFI_MANAGER_ERROR_NONE == error) { - result_ssid = essid; - free(essid); - } else { - std::string log_msg = "Failed to get network ssid: " + std::string(get_error_message(error)); - return LogAndCreateResult( - ErrorCode::UNKNOWN_ERR, log_msg, - ("wifi_manager_ap_get_essid error: %d (%s)", error, get_error_message(error))); - } - - //gathering ips - PlatformResult ret = GetIpsWifi(wifi_ap_handle, &result_ip_address, &result_ipv6_address); - if (ret.IsError()) { - return ret; - } + if (WIFI_MANAGER_ERROR_NO_CONNECTION != error) { + //refreshing access point information + error = wifi_manager_ap_refresh(wifi_ap_handle); + if (WIFI_MANAGER_ERROR_NONE != error) { + std::string log_msg = "Failed to refresh access point information: " + + std::string(get_error_message(error)); + return LogAndCreateResult( + ErrorCode::UNKNOWN_ERR, log_msg, + ("wifi_manager_ap_refresh error: %d (%s)", error, get_error_message(error))); + } - //gathering strength - wifi_manager_rssi_level_e rssi_level = manager_.GetWifiLevel(); - // this mean that level was not initialized or wifi not connected - if (WIFI_MANAGER_RSSI_LEVEL_0 == rssi_level) { - // so try to gather rssi level with dedicated function - int rssi = 0; - error = wifi_manager_ap_get_rssi(wifi_ap_handle, &rssi); + //gathering ssid + char* essid = nullptr; + error = wifi_manager_ap_get_essid(wifi_ap_handle, &essid); if (WIFI_MANAGER_ERROR_NONE == error) { - result_signal_strength = ((double) abs(rssi))/kWifiSignalStrengthDivideValue; + result_ssid = essid; + free(essid); } else { - std::string log_msg = "Failed to get signal strength: " + - std::string(get_error_message(error)); + std::string log_msg = "Failed to get network ssid: " + std::string(get_error_message(error)); return LogAndCreateResult( - ErrorCode::UNKNOWN_ERR, log_msg, - ("wifi_manager_ap_get_rssi error: %d (%s)", error, get_error_message(error))); + ErrorCode::UNKNOWN_ERR, log_msg, + ("wifi_manager_ap_get_essid error: %d (%s)", error, get_error_message(error))); + } + + //gathering ips + PlatformResult ret = GetIpsWifi(wifi_ap_handle, &result_ip_address, &result_ipv6_address); + if (ret.IsError()) { + return ret; + } + + //gathering strength + wifi_manager_rssi_level_e rssi_level = manager_.GetWifiLevel(); + // this mean that level was not initialized or wifi not connected + if (WIFI_MANAGER_RSSI_LEVEL_0 == rssi_level) { + // so try to gather rssi level with dedicated function + int rssi = 0; + error = wifi_manager_ap_get_rssi(wifi_ap_handle, &rssi); + if (WIFI_MANAGER_ERROR_NONE == error) { + result_signal_strength = ((double) abs(rssi))/kWifiSignalStrengthDivideValue; + } else { + std::string log_msg = "Failed to get signal strength: " + + std::string(get_error_message(error)); + return LogAndCreateResult( + ErrorCode::UNKNOWN_ERR, log_msg, + ("wifi_manager_ap_get_rssi error: %d (%s)", error, get_error_message(error))); + } + } else { + result_signal_strength = ((double) rssi_level)/WIFI_MANAGER_RSSI_LEVEL_4; } - } else { - result_signal_strength = ((double) rssi_level)/WIFI_MANAGER_RSSI_LEVEL_4; } } + //building result object out->insert(std::make_pair("status", picojson::value(result_status ? kWifiStatusOn : kWifiStatusOff))); out->insert(std::make_pair("ssid", picojson::value(result_ssid))); -- 2.7.4 From 31adc7ebd9809d86043590aee0ff25612fe1016a Mon Sep 17 00:00:00 2001 From: Tomasz Marciniak Date: Thu, 10 Aug 2017 13:01:13 +0200 Subject: [PATCH 04/16] [version] 1.95 Change-Id: I2da7ee4bcf674c0e740473b0c58d03af1e47e50e Signed-off-by: Tomasz Marciniak --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 9a3f04d..8109553 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.94 +Version: 1.95 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From d2823f17cc6ac973f6126813f33f43034456af36 Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Fri, 11 Aug 2017 13:38:57 +0200 Subject: [PATCH 05/16] [Application] Implementation for getAppsUsageInfo method [Verification] Code compiles. Manually tested in Web Console. Change-Id: I743397bf67e6da504c75e96dbda344f6e0103b54 Signed-off-by: Szymon Jastrzebski --- src/application/application_api.js | 127 +++++++++++++++++++++++++ src/application/application_instance.cc | 8 ++ src/application/application_instance.h | 1 + src/application/application_manager.cc | 161 +++++++++++++++++++++++++++++++- src/application/application_manager.h | 4 + 5 files changed, 299 insertions(+), 2 deletions(-) diff --git a/src/application/application_api.js b/src/application/application_api.js index 12bfeef..0db0248 100755 --- a/src/application/application_api.js +++ b/src/application/application_api.js @@ -26,6 +26,11 @@ var ApplicationControlLaunchMode = { GROUP: 'GROUP' }; +var ApplicationUsageMode = { + RECENTLY: 'RECENTLY', + FREQUENTLY: 'FREQUENTLY' +}; + // TODO: Please uncomment below lines when system events is ready //var SystemEvent = { // BATTERY_CHARGER_STATUS: 'BATTERY_CHARGER_STATUS', @@ -545,6 +550,102 @@ ApplicationManager.prototype.getBatteryUsageInfo = function() { } }; +ApplicationManager.prototype.getAppsUsageInfo = function() { + var args = AV.validateMethod(arguments, [ + { + name: 'successCallback', + type: AV.Types.FUNCTION + }, + { + name: 'errorCallback', + type: AV.Types.FUNCTION, + optional: true, + nullable: true + }, + { + name: 'mode', + type: AV.Types.ENUM, + values: T.getValues(ApplicationUsageMode), + optional: true, + nullable: true + }, + { + name: 'filter', + type: AV.Types.DICTIONARY, + optional: true, + nullable: true + }, + { + name: 'limit', + type: AV.Types.LONG, + optional: true, + nullable: true + }]); + + var callArgs = {}; + + if (!T.isNullOrUndefined(args.mode)) { + callArgs.mode = args.mode; + } + + if (!T.isNullOrUndefined(args.filter) && typeof args.filter !== 'object') { + setTimeout(function() { + native.callIfPossible(args.errorCallback, + new WebAPIException(WebAPIException.INVALID_VALUES_ERR, + 'filter must be an object.')); + }, 0); + return; + } + + callArgs.filter = {}; + if (!T.isNullOrUndefined(args.filter)) { + var filter = args.filter; + if (!T.isNullOrUndefined(filter.timeSpan)) { + callArgs.filter.timeSpan = Converter.toLong(filter.timeSpan); + } else { + if (!T.isNullOrUndefined(filter.startTime)) { + if (filter.startTime instanceof Date) { + callArgs.filter.startTime = filter.startTime.getTime() / 1000; + } else { + throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, + 'startTime given with invalid type.'); + } + } + + if (!T.isNullOrUndefined(filter.endTime)) { + if (filter.endTime instanceof Date) { + callArgs.filter.endTime = filter.endTime.getTime() / 1000; + } else { + throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, + 'endTime given with invalid type.'); + } + } + } + } + + if (!T.isNullOrUndefined(args.limit)) { + callArgs.limit = args.limit; + } + + var callback = function(result) { + if (native.isFailure(result)) { + native.callIfPossible(args.errorCallback, native.getErrorObject(result)); + } else { + var data = native.getResultObject(result); + var resultArray = []; + data.forEach(function(i) { + resultArray.push(new ApplicationUsage(i)); + }); + args.successCallback(resultArray); + } + }; + + var result = native.call('ApplicationManager_getAppsUsageInfo', callArgs, callback); + if (native.isFailure(result)) { + throw native.getErrorObject(result); + } +}; + function ListenerManager(native, listenerName) { this.listeners = {}; this.nextId = 1; @@ -1292,5 +1393,31 @@ function ApplicationBatteryUsage(data) { }); } +//class ApplicationUsage //////////////////////////////////////////////////////// +function ApplicationUsage(data) { + Object.defineProperties(this, { + appId : { + value : data.appId, + writable : false, + enumerable : true + }, + totalCount : { + value : data.totalCount, + writable : false, + enumerable : true + }, + totalDuration : { + value : data.totalDuration, + writable : false, + enumerable : true + }, + lastTime : { + value : new Date(data.lastTime * 1000), + writable : false, + enumerable : true + } + }); +} + // exports //////////////////////////////////////////////////// exports = new ApplicationManager(); diff --git a/src/application/application_instance.cc b/src/application/application_instance.cc index 0de967a..44a51f6 100755 --- a/src/application/application_instance.cc +++ b/src/application/application_instance.cc @@ -89,6 +89,7 @@ ApplicationInstance::ApplicationInstance() : REGISTER_ASYNC("ApplicationManager_findAppControl", FindAppControl); REGISTER_ASYNC("ApplicationManager_getAppsContext", GetAppsContext); REGISTER_ASYNC("ApplicationManager_getAppsInfo", GetAppsInfo); + REGISTER_ASYNC("ApplicationManager_getAppsUsageInfo", GetAppsUsageInfo); REGISTER_ASYNC("ApplicationManager_getBatteryUsageInfo", GetBatteryUsageInfo); #undef REGISTER_ASYNC } @@ -168,6 +169,13 @@ void ApplicationInstance::GetBatteryUsageInfo(const picojson::value& args, picoj manager_.GetBatteryUsageInfo(args, &out); } +void ApplicationInstance::GetAppsUsageInfo(const picojson::value& args, picojson::object& out) { + LoggerD("Entered"); + CHECK_PRIVILEGE_ACCESS(kPrivilegeAppHistoryRead, &out); + + manager_.GetAppsUsageInfo(args, &out); +} + void ApplicationInstance::AddAppInfoEventListener(const picojson::value& args, picojson::object& out) { LoggerD("Entered"); LoggerW("DEPRECATION WARNING: addAppInfoEventListener() is deprecated and will be removed from next release. " diff --git a/src/application/application_instance.h b/src/application/application_instance.h index 3ae6c32..69cf042 100755 --- a/src/application/application_instance.h +++ b/src/application/application_instance.h @@ -39,6 +39,7 @@ class ApplicationInstance: public common::ParsedInstance { void GetAppSharedURI(const picojson::value& args, picojson::object& out); void GetAppMetaData(const picojson::value& args, picojson::object& out); void GetBatteryUsageInfo(const picojson::value& args, picojson::object& out); + void GetAppsUsageInfo(const picojson::value& args, picojson::object& out); void AddAppInfoEventListener(const picojson::value& args, picojson::object& out); void RemoveAppInfoEventListener(const picojson::value& args, picojson::object& out); void GetRequestedAppControl(const picojson::value& args, picojson::object& out); diff --git a/src/application/application_manager.cc b/src/application/application_manager.cc index 354582d..c1b94af 100755 --- a/src/application/application_manager.cc +++ b/src/application/application_manager.cc @@ -71,6 +71,8 @@ const std::string kStatusType = "statusType"; const std::string kAppId = "appId"; const std::string kListenerId = "listenerId"; const std::string kAppStatusChangeListener = "AppStatusChangeListener"; +const std::string kAppUsageModeFrequently = "FREQUENTLY"; +const std::string kAppUsageModeRecently = "RECENTLY"; const std::map event_map_ = { {SYSTEM_EVENT_BATTERY_CHARGER_STATUS, EVENT_KEY_BATTERY_CHARGER_STATUS}, @@ -98,7 +100,9 @@ const std::map event_map_ = { }; #ifdef TIZEN_MOBILE -const int kMaximumRetrievedObjects = 30; +const int kMaximumBatteryRetrievedObjects = 30; +const int kMaximumAppsRetrievedObjects = 10; +const int kDefaultPeriodOfTime = 30; #endif } @@ -1164,7 +1168,7 @@ PlatformResult ApplicationManager::BatteryUsageFilter(const picojson::value& arg context_history_data_e* data_type_out) { LoggerD("Entered"); int ret = CONTEXT_HISTORY_ERROR_NONE; - int limit = kMaximumRetrievedObjects; + int limit = kMaximumBatteryRetrievedObjects; if (args.contains("limit")) { limit = static_cast(args.get("limit").get()); } @@ -1223,6 +1227,122 @@ PlatformResult ApplicationManager::BatteryUsageAttributes(const context_history_ return PlatformResult(ErrorCode::NO_ERROR); } + +PlatformResult ApplicationManager::AppsUsageFilter(const picojson::value& args, + const context_history_filter_h filter, + context_history_data_e* data_type_out) { + LoggerD("Entered"); + int ret = CONTEXT_HISTORY_ERROR_NONE; + int limit = kMaximumAppsRetrievedObjects; + if (args.contains("limit")) { + limit = static_cast(args.get("limit").get()); + } + + ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_RESULT_SIZE, limit); + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::INVALID_VALUES_ERR, "limit given with invalid value.", + ("limit given with invalid value: %d (%s)", ret, get_error_message(ret))); + } + + context_history_data_e data_type_in = CONTEXT_HISTORY_FREQUENTLY_USED_APP; + if (args.contains("mode") && kAppUsageModeRecently == args.get("mode").get()) { + data_type_in = CONTEXT_HISTORY_RECENTLY_USED_APP; + } + + int time_span = kDefaultPeriodOfTime; + const picojson::object &JS_filter = args.get("filter").get(); + auto time_span_iter = JS_filter.find("timeSpan"); + if (JS_filter.end() != time_span_iter + || (JS_filter.end() == JS_filter.find("startTime") + && JS_filter.end() == JS_filter.find("endTime"))) { + //In the second case, we treat the filter object just like an empty object. + //The default value of filter will be used instead. + if (JS_filter.end() != time_span_iter) { + time_span = static_cast(time_span_iter->second.get()); + } + ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_TIME_SPAN, time_span); + //context_history_filter_set_int may return only success or CONTEXT_HISTORY_ERROR_INVALID_PARAMETER + //Although this should never happen, it's better to check ret's value + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::ABORT_ERR, "Error while setting the default TIME_SPAN value.", + ("Error while setting the default TIME_SPAN value: %d (%s)", ret, get_error_message(ret))); + } + } else { + auto start_time_iter = JS_filter.find("startTime"); + auto end_time_iter = JS_filter.find("endTime"); + if (start_time_iter != JS_filter.end()) { + int start_time = static_cast(start_time_iter->second.get()); + ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_START_TIME, start_time); + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::INVALID_VALUES_ERR, "startTime given with invalid value.", + ("startTime given with invalid value: %d (%s)", ret, get_error_message(ret))); + } + } + if (end_time_iter != JS_filter.end()) { + int end_time = static_cast(end_time_iter->second.get()); + ret = context_history_filter_set_int(filter, CONTEXT_HISTORY_FILTER_END_TIME, end_time); + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::INVALID_VALUES_ERR, "endTime given with invalid value.", + ("endTime given with invalid value: %d (%s)", ret, get_error_message(ret))); + } + } + } + + *data_type_out = data_type_in; + + return PlatformResult(ErrorCode::NO_ERROR); +} + +PlatformResult ApplicationManager::AppsUsageAttributes(const context_history_record_h record, + picojson::object* object) { + LoggerD("Entered"); + + int ret = CONTEXT_HISTORY_ERROR_NONE; + int total_count = 0; + int total_duration = 0; + int last_time = 0; + char* app_id = nullptr; + SCOPE_EXIT { + free(app_id); + }; + + ret = context_history_record_get_string(record, CONTEXT_HISTORY_APP_ID, &app_id); + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get string.", + ("Failed to get string: %d (%s)", ret, get_error_message(ret))); + } + + ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_COUNT, &total_count); + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get total count.", + ("Failed to get total count: %d (%s)", ret, get_error_message(ret))); + } + + ret = context_history_record_get_int(record, CONTEXT_HISTORY_TOTAL_DURATION, &total_duration); + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult( + ErrorCode::ABORT_ERR, "Failed to get total duration.", + ("Failed to get total duration: %d (%s)", ret, get_error_message(ret))); + } + + ret = context_history_record_get_int(record, CONTEXT_HISTORY_LAST_TIME, &last_time); + if (CONTEXT_HISTORY_ERROR_NONE != ret) { + return LogAndCreateResult(ErrorCode::ABORT_ERR, "Failed to get last time.", + ("Failed to get last time: %d (%s)", ret, get_error_message(ret))); + } + + object->insert(std::make_pair("appId", picojson::value(app_id))); + object->insert(std::make_pair("totalCount", picojson::value(static_cast(total_count)))); + object->insert( + std::make_pair("totalDuration", picojson::value(static_cast(total_duration)))); + object->insert(std::make_pair("lastTime", picojson::value(static_cast(last_time)))); + + return PlatformResult(ErrorCode::NO_ERROR); +} #endif void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojson::object* out) { @@ -1266,6 +1386,43 @@ void ApplicationManager::GetBatteryUsageInfo(const picojson::value& args, picojs #endif } +void ApplicationManager::GetAppsUsageInfo(const picojson::value& args, picojson::object* out) { + LoggerD("Entered"); + +#ifdef TIZEN_MOBILE + int callback_id = static_cast(args.get(kCallbackId).get()); + + auto get_apps_usage = [args](const std::shared_ptr& response)-> void { + LoggerD("Entered"); + PlatformResult result = ApplicationManager::GetContextHistory(args, &response.get()->get(), + &ApplicationManager::AppsUsageFilter, + &ApplicationManager::AppsUsageAttributes); + if (!result) { + LogAndReportError(result, &response.get()->get()); + } + }; + + auto get_apps_usage_response = [this, callback_id]( + const std::shared_ptr& response) -> void { + LoggerD("Entered"); + picojson::object& obj = response->get(); + obj.insert(std::make_pair(kCallbackId, picojson::value(static_cast(callback_id)))); + Instance::PostMessage(&this->instance_, response->serialize().c_str()); + }; + + auto data = std::shared_ptr(new picojson::value(picojson::object())); + + TaskQueue::GetInstance().Queue( + get_apps_usage, + get_apps_usage_response, + data); +#else + // Context API is supported only for mobile profile, other ones would result with NotSupportedError + LogAndReportError(PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "This feature is not supported on this profile."), out, + ("NOT_SUPPORTED_ERR: This feature is not supported on this profile")); +#endif +} + void ApplicationManager::GetAppMetaData(const std::string& app_id, picojson::object* out) { LoggerD("Entered"); diff --git a/src/application/application_manager.h b/src/application/application_manager.h index ed4a8a1..164fcb5 100755 --- a/src/application/application_manager.h +++ b/src/application/application_manager.h @@ -58,6 +58,7 @@ class ApplicationManager { void GetAppSharedUri(const std::string& app_id, picojson::object* out); void GetAppMetaData(const std::string& app_id, picojson::object* out); void GetBatteryUsageInfo(const picojson::value& args, picojson::object* out); + void GetAppsUsageInfo(const picojson::value& args, picojson::object* out); void StartAppInfoEventListener(picojson::object* out); void StopAppInfoEventListener(); void GetApplicationInformationSize(const picojson::value& args, picojson::object* out); @@ -97,6 +98,9 @@ class ApplicationManager { static common::PlatformResult BatteryUsageFilter(const picojson::value&, const context_history_filter_h, context_history_data_e* data_type); static common::PlatformResult BatteryUsageAttributes(const context_history_record_h, picojson::object*); + + static common::PlatformResult AppsUsageFilter(const picojson::value&, const context_history_filter_h, context_history_data_e* data_type); + static common::PlatformResult AppsUsageAttributes(const context_history_record_h, picojson::object*); #endif }; -- 2.7.4 From d509778f92e78d6fd615458174d532b258d41bee Mon Sep 17 00:00:00 2001 From: Lukasz Bardeli Date: Fri, 11 Aug 2017 13:45:05 +0200 Subject: [PATCH 06/16] [DataControl] Add addChangeListener and removeChangeListener implementation [Verification] Code compiles without error Change-Id: Ifd05e4a4746e64500d4336e1c5598159194c5a6e Signed-off-by: Lukasz Bardeli --- src/datacontrol/datacontrol_api.js | 246 ++++++++++++++++++++++-- src/datacontrol/datacontrol_instance.cc | 319 +++++++++++++++++++++++++++++++- src/datacontrol/datacontrol_instance.h | 38 ++++ 3 files changed, 588 insertions(+), 15 deletions(-) diff --git a/src/datacontrol/datacontrol_api.js b/src/datacontrol/datacontrol_api.js index cb7158e..5d60996 100755 --- a/src/datacontrol/datacontrol_api.js +++ b/src/datacontrol/datacontrol_api.js @@ -18,18 +18,201 @@ tizen.debug = extension; var JSON_ = xwalk.JSON; var validator_ = xwalk.utils.validator; +var converter_ = xwalk.utils.converter; var types_ = validator_.Types; +var type_ = xwalk.utils.type; +var native_ = new xwalk.utils.NativeManager(extension); var callbackId = 0; var callbacks = {}; +var listeners_ = {}; +var DATA_CONTROL_MANAGER_LISTENER_ID = 'DataControlManagerChangeCallback'; + +var DataType = { + 'MAP': 'MAP', + 'SQL': 'SQL' +}; + +var EventType = { + 'SQL_UPDATE': 'SQL_UPDATE', + 'SQL_INSERT': 'SQL_INSERT', + 'SQL_DELETE': 'SQL_DELETE', + 'MAP_SET': 'MAP_SET', + 'MAP_ADD': 'MAP_ADD', + 'MAP_REMOVE': 'MAP_REMOVE' +}; + + +var DataControlListenersManager = (function() { + + function changeEvent(event) { + var successCallback; + + if (DataType.SQL === event.eventType) { + if (type_.isEmptyObject(this._SQLDataControlCallbackMap)) { + return; + } + for (var listenerId in this._SQLDataControlCallbackMap) { + if (this._SQLDataControlCallbackMap.hasOwnProperty(listenerId)) { + if (this._SQLDataControlCallbackMap[listenerId].providerId === event.providerId && + this._SQLDataControlCallbackMap[listenerId].dataId === event.dataId) { + successCallback = this._SQLDataControlCallbackMap[listenerId].changeCallback; + if (type_.isFunction(successCallback)) { + successCallback(event.type, {columns: event.columns, values: event.values}); + } + } + } + } + } else { + if (type_.isEmptyObject(this._MAPDataControlCallbackMap)) { + return; + } + for (var listenerId in this._MAPDataControlCallbackMap) { + if (this._MAPDataControlCallbackMap.hasOwnProperty(listenerId)) { + if (this._MAPDataControlCallbackMap[listenerId].providerId === event.providerId && + this._MAPDataControlCallbackMap[listenerId].dataId === event.dataId) { + successCallback = this._MAPDataControlCallbackMap[listenerId].changeCallback; + if (type_.isFunction(successCallback)) { + successCallback(event.type, {columns: event.columns, values: event.values}); + } + } + } + } + } + } + + function _DataControlListenerManager() { + this._SQLDataControlCallbackMap = {}; + this._MAPDataControlCallbackMap = {}; + this.lastListenerId = 0; + this.changeEvent = changeEvent.bind(this); + } + + _DataControlListenerManager.prototype.addChangeListener = function(type, providerId, dataId, changeCallback, errorCallback) { + var _realWatchId = 0; + if (DataType.SQL === type) { + for (var i in this._SQLDataControlCallbackMap) { + if (this._SQLDataControlCallbackMap.hasOwnProperty(i) && + this._SQLDataControlCallbackMap[i].providerId === providerId && + this._SQLDataControlCallbackMap[i].dataId === dataId) { + _realWatchId = this._SQLDataControlCallbackMap[i].realWatchId; + } + } + } else { + for (var i in this._MAPDataControlCallbackMap) { + if (this._MAPDataControlCallbackMap.hasOwnProperty(i) && + this._MAPDataControlCallbackMap[i].providerId === providerId && + this._MAPDataControlCallbackMap[i].dataId === dataId) { + _realWatchId = this._MAPDataControlCallbackMap[i].realWatchId; + } + } + } + + if (!_realWatchId) { + var callback = function(result) { + if (native_.isFailure(result)) { + native_.callIfPossible(errorCallback, native_.getErrorObject(result)); + return; + } + } + var result = + callNativeWithCallback('DataControlConsumerObject_addChangeListener', { + providerId: providerId, + dataId: dataId, + type: type + }, callback); + + if (native_.isFailure(result)) { + throw native_.getErrorObject(result); + } else { + _realWatchId = converter_.toLong(result.watchId, true); + } + if (type_.isEmptyObject(this._SQLDataControlCallbackMap) && + type_.isEmptyObject(this._MAPDataControlCallbackMap)) { + AddListener(DATA_CONTROL_MANAGER_LISTENER_ID, this.changeEvent); + } + } + + if (DataType.SQL === type) { + this._SQLDataControlCallbackMap[++this.lastListenerId] = {'providerId': providerId, + 'dataId': dataId, + 'changeCallback': changeCallback, + 'realWatchId': _realWatchId}; + } else { + this._MAPDataControlCallbackMap[++this.lastListenerId] = {'providerId': providerId, + 'dataId': dataId, + 'changeCallback': changeCallback, + 'realWatchId': _realWatchId}; + } + + return this.lastListenerId; + }; + + _DataControlListenerManager.prototype.removeChangeListener = function(type, providerId, dataId, listenerId) { + var _realWatchId = 0; + if (DataType.SQL === type && !type_.isUndefined(this._SQLDataControlCallbackMap[listenerId])) { + _realWatchId = this._SQLDataControlCallbackMap[listenerId].realWatchId; + delete this._SQLDataControlCallbackMap[listenerId]; + for (var i in this._SQLDataControlCallbackMap) { + if (this._SQLDataControlCallbackMap.hasOwnProperty(i) && + this._SQLDataControlCallbackMap[i].realWatchId === _realWatchId) { + return; + } + } + } else if (DataType.MAP === type && !type_.isUndefined(this._MAPDataControlCallbackMap[listenerId])) { + _realWatchId = this._MAPDataControlCallbackMap[listenerId].realWatchId; + delete this._MAPDataControlCallbackMap[listenerId]; + for (var i in this._MAPDataControlCallbackMap) { + if (this._MAPDataControlCallbackMap.hasOwnProperty(i) && + this._MAPDataControlCallbackMap[i].realWatchId === _realWatchId) { + return; + } + } + } else { + console.log("Type invalid or listener was not added") + return; + } + + if (0 != _realWatchId) { + callNative('DataControlConsumerObject_removeChangeListener',{ + providerId: providerId, + dataId: dataId, + watchId: _realWatchId, + type: type + }) + + if (type_.isEmptyObject(this._SQLDataControlCallbackMap) && + type_.isEmptyObject(this._MAPDataControlCallbackMap)) { + RemoveListener(DATA_CONTROL_MANAGER_LISTENER_ID); + } + } + }; + + return _DataControlListenerManager; + +})(); + +var listenersManager = new DataControlListenersManager(); + +// TODO refactor setMessageListener to start using common functionality extension.setMessageListener(function(json) { var result = JSON_.parse(json); - var callback = callbacks[result['callbackId']]; - setTimeout(function() { - callback(result); - delete callbacks[result['callbackId']]; - }, 0); + if (result.hasOwnProperty("callbackId")) { + var callback = callbacks[result['callbackId']]; + setTimeout(function() { + callback(result); + delete callbacks[result['callbackId']]; + }, 0); + } + if (result.hasOwnProperty("listenerId")) { + var id = result['listenerId']; + delete result['listenerId']; + var f = listeners_[id]; + setTimeout(function() { + f(result); + }, 0); + } }); function nextCallbackId() { @@ -71,15 +254,24 @@ function callNativeWithCallback(cmd, args, callback) { return callNative(cmd, args); } +function AddListener(name, callback) { + if (!type_.isString(name) || !name.length) { + throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR); + } + + listeners_[name] = callback; +}; + +function RemoveListener(name) { + if (listeners_.hasOwnProperty(name)) { + delete listeners_[name]; + } +}; + function SetReadOnlyProperty(obj, n, v) { Object.defineProperty(obj, n, {value: v, writable: false}); } -var DataType = { - 'MAP': 'MAP', - 'SQL': 'SQL' -}; - function DataControlManager() { // constructor of DataControlManager } @@ -91,15 +283,16 @@ var getDataControlConsumer = function(providerId, dataId, type) { var args = validator_.validateArgs(arguments, [ {'name': 'providerId', 'type': types_.STRING}, {'name': 'dataId', 'type': types_.STRING}, - {'name': 'type', 'type': types_.ENUM, 'values': ['MAP', 'SQL']} + {'name': 'type', 'type': types_.ENUM, 'values': [DataType.SQL, DataType.MAP]} ]); var returnObject = null; - if (type === 'SQL') { + if (DataType.SQL === type) { returnObject = new SQLDataControlConsumer(); - } else if (type === 'MAP') { + } else if (DataType.MAP == type) { returnObject = new MappedDataControlConsumer(); } + SetReadOnlyProperty(returnObject, 'type', args.type); // read only property SetReadOnlyProperty(returnObject, 'providerId', args.providerId); // read only property SetReadOnlyProperty(returnObject, 'dataId', args.dataId); // read only property @@ -116,7 +309,34 @@ function DataControlConsumerObject() { // constructor of DataControlConsumerObject } +DataControlConsumerObject.prototype.addChangeListener = function() { + var args = validator_.validateArgs(arguments, [ + {'name': 'dataChangeCallback', 'type': types_.FUNCTION, optional: false, nullable: false}, + {'name': 'errorCallback', 'type': types_.FUNCTION, optional: true, nullable: true} + ]); + + var type = DataType.SQL; + if (this instanceof MappedDataControlConsumer) { + type = DataType.MAP; + } + + return listenersManager.addChangeListener(type, this.providerId, this.dataId, + args.dataChangeCallback, args.errorCallback); +} + +DataControlConsumerObject.prototype.removeChangeListener = function() { + + var args = validator_.validateArgs(arguments, [ + {'name': 'watchId', 'type': types_.LONG} + ]); + var type = DataType.SQL; + if (this instanceof MappedDataControlConsumer) { + type = DataType.MAP; + } + + listenersManager.removeChangeListener(type, this.providerId, this.dataId, args.watchId); +} function SQLDataControlConsumer() { // constructor of SQLDataControlConsumer diff --git a/src/datacontrol/datacontrol_instance.cc b/src/datacontrol/datacontrol_instance.cc index a55ab14..60adcee 100755 --- a/src/datacontrol/datacontrol_instance.cc +++ b/src/datacontrol/datacontrol_instance.cc @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -38,7 +37,10 @@ namespace datacontrol { namespace { // The privileges that required in Datacontrol API const std::string kPrivilegeDatacontrol = "http://tizen.org/privilege/datacontrol.consumer"; - +const std::string kPrivilegeDatasharing = "http://tizen.org/privilege/datasharing"; +const std::string kPrivilegeAppmanagerLaunch = "http://tizen.org/privilege/appmanager.launch"; +const std::string SQL = "SQL"; +const std::string MAP = "MAP"; } // namespace using common::InvalidValuesException; @@ -47,10 +49,13 @@ using common::IOException; using common::SecurityException; using common::UnknownException; using common::NotFoundException; +using common::AbortException; using common::ScopeExit; using common::operator+; +using namespace common; + struct DatacontrolInformation { int callbackId; int requestId; @@ -79,7 +84,14 @@ DatacontrolInstance::DatacontrolInstance() { REGISTER_SYNC("SQLDataControlConsumer_insert", SQLDataControlConsumerInsert); REGISTER_SYNC("MappedDataControlConsumer_getValue", MappedDataControlConsumerGetvalue); + REGISTER_SYNC("DataControlConsumerObject_removeChangeListener", + RemoveChangeListener); #undef REGISTER_SYNC + #define REGISTER_ASYNC(c, x) \ + RegisterSyncHandler(c, std::bind(&DatacontrolInstance::x, this, _1, _2)); + REGISTER_ASYNC("DataControlConsumerObject_addChangeListener", + AddChangeListener); + #undef REGISTER_ASYNC } DatacontrolInstance::~DatacontrolInstance() { @@ -976,6 +988,309 @@ void DatacontrolInstance::MappedDataControlConsumerUpdatevalue( } } +int DatacontrolInstance::CreateMAPHandle(const std::string& providerId, + const std::string& dataId, + data_control_h *handle) { + LoggerD("Enter"); + int result = DATA_CONTROL_ERROR_NONE; + + result = ::data_control_map_create(handle); + RETURN_IF_FAIL(result, + "Creating map data control handle is failed with error"); + + result = ::data_control_map_set_provider_id(*handle, providerId.c_str()); + RETURN_IF_FAIL(result, + "Setting provider id is failed with error"); + + result = ::data_control_map_set_data_id(*handle, dataId.c_str()); + RETURN_IF_FAIL(result, + "Setting data id is failed the error"); + + return result; +} + +int DatacontrolInstance::CreateSQLHandle(const std::string& providerId, + const std::string& dataId, + data_control_h *handle) { + LoggerD("Enter"); + int result = DATA_CONTROL_ERROR_NONE; + + result = ::data_control_sql_create(handle); + RETURN_IF_FAIL(result, + "Creating sql data control handle is failed with error"); + + result = ::data_control_sql_set_provider_id(*handle, providerId.c_str()); + RETURN_IF_FAIL(result, "Setting provider id is failed with error"); + + result = ::data_control_sql_set_data_id(*handle, dataId.c_str()); + RETURN_IF_FAIL(result, "Setting data id is failed the error"); + + return result; +} + +PlatformResult DatacontrolInstance::ChangeTypeToString(data_control_data_change_type_e type_e, std::string *type) +{ + LoggerD("Enter"); + + switch(type_e) { + case DATA_CONTROL_DATA_CHANGE_SQL_UPDATE: + *type = "SQL_UPDATE"; + break; + case DATA_CONTROL_DATA_CHANGE_SQL_INSERT: + *type = "SQL_INSERT"; + break; + case DATA_CONTROL_DATA_CHANGE_SQL_DELETE: + *type = "SQL_DELETE"; + break; + case DATA_CONTROL_DATA_CHANGE_MAP_SET: + *type = "MAP_SET"; + break; + case DATA_CONTROL_DATA_CHANGE_MAP_ADD: + *type = "MAP_ADD"; + break; + case DATA_CONTROL_DATA_CHANGE_MAP_REMOVE: + *type = "MAP_REMOVE"; + break; + default: + return LogAndCreateResult(ErrorCode::ABORT_ERR, + "Undefined data change type"); + break; + } + return PlatformResult(ErrorCode::NO_ERROR); +} + +void DatacontrolInstance::callback(data_control_h provider, data_control_data_change_type_e type, bundle *bundle_data, void *user_data) +{ + LoggerD("Enter"); + + auto data = static_cast(user_data); + + char *provider_id = nullptr; + char *data_id = nullptr; + int result = DATA_CONTROL_ERROR_NONE; + + if (DATA_CONTROL_DATA_CHANGE_SQL_UPDATE == type || + DATA_CONTROL_DATA_CHANGE_SQL_INSERT == type || + DATA_CONTROL_DATA_CHANGE_SQL_DELETE == type) { + + if (MAP == data->event_type) { + LoggerI("Callback registered for different type"); + return; + } + + result = data_control_sql_get_provider_id(provider, &provider_id); + + if (DATA_CONTROL_ERROR_NONE == result) { + result = data_control_sql_get_data_id(provider, &data_id); + } + } else { + + if (SQL == data->event_type) { + LoggerI("Callback registered for different type"); + return; + } + + result = data_control_map_get_provider_id(provider, &provider_id); + + if (DATA_CONTROL_ERROR_NONE == result) { + result = data_control_map_get_data_id(provider, &data_id); + } + } + + picojson::value event = picojson::value(picojson::object()); + picojson::object& obj = event.get(); + + if (DATA_CONTROL_ERROR_NONE != result) { + obj.insert(std::make_pair("callbackId", picojson::value(std::to_string(data->callbackId)))); + // According to native documentation only IOError can be returned to webapi, other errors are handled earlier + LogAndReportError(PlatformResult(ErrorCode::IO_ERR, "Get callback data failed"), &obj); + Instance::PostMessage(data->_instance, event.serialize().c_str()); + return; + } + + std::string event_type = ""; + PlatformResult status = ChangeTypeToString(type, &event_type); + + if (status.IsError()) { + obj.insert(std::make_pair("callbackId", picojson::value(std::to_string(data->callbackId)))); + LogAndReportError(status, &obj); + Instance::PostMessage(data->_instance, event.serialize().c_str()); + return; + } + + obj.insert(std::make_pair("type", picojson::value(event_type))); + + obj.insert(std::make_pair("providerId", picojson::value(std::string(provider_id)))); + obj.insert(std::make_pair("dataId", picojson::value(std::string(data_id)))); + + obj.insert(std::make_pair("columns", picojson::value(picojson::array()))); + obj.insert(std::make_pair("values", picojson::value(picojson::array()))); + + bundle_foreach(bundle_data, [](const char *key, const int type, const bundle_keyval_t *kv, void *user_data){ + LoggerD("Enter"); + + picojson::object &row_data = *(static_cast(user_data)); + + void *basic_val = NULL; + size_t basic_size = 0; + + LoggerD("Key:%s, Type:%d\n", key, type); + bundle_keyval_get_basic_val(const_cast(kv), &basic_val, &basic_size); + + row_data["columns"].get().push_back(picojson::value(std::string(key))); + row_data["values"].get().push_back(picojson::value(std::string(static_cast(basic_val)))); + }, &obj); + + obj.insert(std::make_pair("listenerId", picojson::value("DataControlManagerChangeCallback"))); + + Instance::PostMessage(data->_instance, event.serialize().c_str()); +} + +// result_callback method is used only for pass information to errorCallback if any error +// occur while adding listener +void DatacontrolInstance::result_callback(data_control_h provider, data_control_error_e result, int callback_id, void *user_data) { + LoggerD("Enter"); + if (DATA_CONTROL_ERROR_NONE != result) { + auto data = static_cast(user_data); + picojson::value event = picojson::value(picojson::object()); + picojson::object& obj = event.get(); + obj.insert(std::make_pair("callbackId", picojson::value(std::to_string(data->callbackId)))); + // According to native documentation only IOError can be returned to webapi, other errors are handled earlier + LogAndReportError(IOException("AddChangeListener failed"), obj); + Instance::PostMessage(data->_instance, event.serialize().c_str()); + if (0 != callback_id) { + data->_instance->EraseMap(callback_id); + } + } +} + + +void DatacontrolInstance::AddChangeListener(const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + + CHECK_PRIVILEGE_ACCESS(kPrivilegeDatasharing, &out); + CHECK_PRIVILEGE_ACCESS(kPrivilegeAppmanagerLaunch, &out); + + CHECK_EXIST(args, "providerId", out) + CHECK_EXIST(args, "dataId", out) + CHECK_EXIST(args, "type", out) + CHECK_EXIST(args, "callbackId", out) + + const std::string& providerId = args.get("providerId").get(); + const std::string& dataId = args.get("dataId").get(); + const std::string& type = args.get("type").get(); + int callbackId = static_cast(args.get("callbackId").get()); + int result = DATA_CONTROL_ERROR_NONE; + data_control_h handle = nullptr; + std::function del; + + if (SQL == type) { + result = CreateSQLHandle(providerId, dataId, &handle); + del = data_control_sql_destroy; + } else { + result = CreateMAPHandle(providerId, dataId, &handle); + del = data_control_map_destroy; + } + + auto deleter = [&del](data_control_h handle) { + if (handle && DATA_CONTROL_ERROR_NONE != del(handle)) { + LoggerE("Destroy handle failed"); + } + }; + + std::unique_ptr::type, decltype(deleter)> handle_ptr( + handle, deleter); + + std::shared_ptr user_data(new ReplyCallbackData()); + user_data->_instance = this; + user_data->callbackId = callbackId; + user_data->event_type = type; + + + if (DATA_CONTROL_ERROR_NONE != result) { + // According to native documentation only IOError can be returned to webapi, other errors are handled earlier + result_callback(handle, DATA_CONTROL_ERROR_IO_ERROR, 0, user_data.get()); + return; + } + + + int watch_id = 0; + result = ::data_control_add_data_change_cb(handle, callback, user_data.get(), result_callback, user_data.get(), &watch_id); + + if (DATA_CONTROL_ERROR_NONE != result) { + // According to native documentation only IOError can be returned to webapi, other errors are handled earlier + result_callback(handle, DATA_CONTROL_ERROR_IO_ERROR, 0, user_data.get()); + return; + } + + reply_map.insert(std::pair(watch_id, user_data)); + + picojson::value return_value = picojson::value(picojson::object()); + picojson::object& return_value_obj = return_value.get(); + + return_value_obj.insert(std::make_pair("watchId", picojson::value(std::to_string(watch_id)))); + ReportSuccess(return_value, out); +} + +void DatacontrolInstance::RemoveChangeListener( + const picojson::value& args, picojson::object& out) { + LoggerD("Enter"); + + CHECK_PRIVILEGE_ACCESS(kPrivilegeDatasharing, &out); + CHECK_PRIVILEGE_ACCESS(kPrivilegeAppmanagerLaunch, &out); + + CHECK_EXIST(args, "providerId", out) + CHECK_EXIST(args, "dataId", out) + CHECK_EXIST(args, "watchId", out) + CHECK_EXIST(args, "type", out) + + const std::string& providerId = args.get("providerId").get(); + const std::string& dataId = args.get("dataId").get(); + const std::string& type = args.get("type").get(); + int watch_id = static_cast(args.get("watchId").get()); + data_control_h handle = nullptr; + std::function del; + int result = DATA_CONTROL_ERROR_NONE; + + if (SQL == type) { + result = CreateSQLHandle(providerId, dataId, &handle); + del = data_control_sql_destroy; + } else { + result = CreateMAPHandle(providerId, dataId, &handle); + del = data_control_map_destroy; + } + + if (DATA_CONTROL_ERROR_NONE != result) { + // According to native documentation only IOError can be returned to webapi, other errors are handled earlier + LogAndReportError(IOException("RemoveChangeListener failed"), out, + ("RemoveChangeListener failed: %d (%s)", result, + get_error_message(result))); + return; + } + + auto deleter = [&del](data_control_h handle){ + if (handle && DATA_CONTROL_ERROR_NONE != del(handle)) { + LoggerE("Destroy handle failed"); + } + }; + + std::unique_ptr::type, decltype(deleter)> handle_ptr( + handle, deleter); + + result = ::data_control_remove_data_change_cb(handle, watch_id); + + if (DATA_CONTROL_ERROR_NONE != result) { + // According to native documentation only IOError can be returned to webapi, other errors are handled earlier + LogAndReportError(IOException("RemoveChangeListener failed"), out, + ("RemoveChangeListener failed: %d (%s)", result, + get_error_message(result))); + return; + } + + reply_map.erase(watch_id); + + ReportSuccess(out); +} #undef CHECK_EXIST diff --git a/src/datacontrol/datacontrol_instance.h b/src/datacontrol/datacontrol_instance.h index e2f2ee3..5b1c341 100755 --- a/src/datacontrol/datacontrol_instance.h +++ b/src/datacontrol/datacontrol_instance.h @@ -19,12 +19,25 @@ #include #include +#include +#include #include "common/extension.h" namespace extension { namespace datacontrol { +class DatacontrolInstance; + +struct ReplyCallbackData { + DatacontrolInstance* _instance; + int callbackId; + std::string event_type; +}; + +typedef std::shared_ptr ReplyCallbackDataPtr; +typedef std::map ReplyCallbackDataMap; + class DatacontrolInstance : public common::ParsedInstance { public: DatacontrolInstance(); @@ -41,6 +54,25 @@ class DatacontrolInstance : public common::ParsedInstance { int callbackId, int userRequestId, DataControlJob job); + int CreateMAPHandle(const std::string& providerId, + const std::string& dataId, + data_control_h *handle); + + int CreateSQLHandle(const std::string& providerId, + const std::string& dataId, + data_control_h *handle); + + void EraseMap(int watch_id) {reply_map.erase(watch_id);}; + + static void callback(data_control_h provider, + data_control_data_change_type_e type, + bundle *bundle_data, void *user_data); + static void result_callback(data_control_h provider, + data_control_error_e result, + int callback_id, void *user_data); + static common::PlatformResult ChangeTypeToString(data_control_data_change_type_e type_e, + std::string *type); + private: void DataControlManagerGetdatacontrolconsumer(const picojson::value& args, picojson::object& out); @@ -60,6 +92,12 @@ class DatacontrolInstance : public common::ParsedInstance { picojson::object& out); void MappedDataControlConsumerUpdatevalue(const picojson::value& args, picojson::object& out); + void AddChangeListener(const picojson::value& args, + picojson::object& out); + void RemoveChangeListener(const picojson::value& args, + picojson::object& out); + + ReplyCallbackDataMap reply_map; }; } // namespace datacontrol -- 2.7.4 From 4113dc2b8430af3d78a6f926fa21da19c8de1e67 Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Wed, 16 Aug 2017 11:06:03 +0200 Subject: [PATCH 07/16] Revert "[Utils] Fix privilege bypass, StringCopy function" This reverts commit 3b71b0bac5e1bb09c50c97168dba1619b3ed40d6. Change-Id: I2e8c2480e2fa3632853ef35d7a457ffed19ae7ce Signed-off-by: Szymon Jastrzebski --- src/filesystem/js/common.js | 2 -- src/utils/utils_api.js | 66 +++++++++++++++------------------------------ 2 files changed, 22 insertions(+), 46 deletions(-) diff --git a/src/filesystem/js/common.js b/src/filesystem/js/common.js index e900cb3..adf52c7 100644 --- a/src/filesystem/js/common.js +++ b/src/filesystem/js/common.js @@ -169,8 +169,6 @@ var commonFS_ = (function() { } function checkPathWithoutDots(aPath) { - aPath = xwalk.utils.StringCopy(aPath); - if (-1 !== aPath.indexOf('/../')) { return false; } diff --git a/src/utils/utils_api.js b/src/utils/utils_api.js index b9a4a83..3c4d46e 100644 --- a/src/utils/utils_api.js +++ b/src/utils/utils_api.js @@ -3,27 +3,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -//We're in a function set up by XWALK which 'use strict' mode, -//so we use below function to get out of the strict mode to get global 'this' -var _global = (new Function('return this'))(); - -var shallow_copy_own_elements = function(orig) { - var copy = {}; - //copy only own properties - var names = Object.getOwnPropertyNames(orig); - for( var i in names ) { - var key = names[i] - copy[key] = orig[key]; - } - return copy; -}; - -//xwalk.JSON: guaranteed to not being modified by the application programmer -exports.JSON = shallow_copy_own_elements(JSON); -Object.freeze(exports.JSON); +//Object xwalk.JSON - guaranteed to not being modified by the application programmer +var JSON_ = {stringify: JSON.stringify, parse: JSON.parse}; +Object.freeze(JSON_); +exports.JSON = JSON_; var _enableJsLogs = false; +var _global = {}; +if (typeof window != 'undefined') { + _global = window; +} +else if (typeof global != 'undefiend') { + _global = global; +} + /** * @deprecated Used only by validateArguments() */ @@ -152,21 +146,6 @@ function Utils() { }); } -var origString = String; -var StringPrototypeCopy = shallow_copy_own_elements(String.prototype); -Object.freeze(StringPrototypeCopy); - -var StringCopy = function(str) { - return Object.setPrototypeOf( new origString(str), StringPrototypeCopy ); -}; -StringCopy.fromCharCode = String.fromCharCode; -StringCopy.fromCodePoint = String.fromCodePoint; -StringCopy.raw = String.raw; -Object.freeze(StringCopy); - -//xwalk.utils.StringCopy: returns a sanitized version of String - user cannot modify its prototype -Utils.prototype.StringCopy = StringCopy; - Utils.prototype.error = console.error.bind(console); Utils.prototype.warn = console.warn.bind(console); Utils.prototype.log = _enableJsLogs ? console.log.bind(console) : function(){}; @@ -352,9 +331,8 @@ Type.prototype.isUndefined = function(obj) { }; Type.prototype.isA = function(obj, type) { - return obj !== undefined && obj !== null && - obj.constructor !== null && obj.constructor !== undefined && - obj.constructor.name === type; + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return (obj !== undefined) && (obj !== null) && (clas === type); }; Type.prototype.isEmptyObject = function(obj) { @@ -497,7 +475,7 @@ Converter.prototype.toDouble = function(val, nullable) { }; function _toString(val) { - return StringCopy(val).toString(); + return String(val); } Converter.prototype.toString = function(val, nullable) { @@ -1040,7 +1018,7 @@ var NativeManager = function(extension) { }); extension_.setMessageListener(function(json) { - var msg = exports.JSON.parse(json); + var msg = JSON_.parse(json); var id; if (msg.hasOwnProperty(this.CALLBACK_ID_KEY)) { @@ -1104,7 +1082,7 @@ NativeManager.prototype.call = function(cmd, args, callback) { }; NativeManager.prototype.callSync = function(cmd, args) { - var request = exports.JSON.stringify({ + var request = JSON_.stringify({ cmd: cmd, args: args || {} }); @@ -1114,7 +1092,7 @@ NativeManager.prototype.callSync = function(cmd, args) { /* C++ extension didn't set sync response using Instance::SendSyncReply */ throw new WebAPIException(WebAPIException.ABORT_ERR, "Internal error"); } - return exports.JSON.parse(response); + return JSON_.parse(response); }; NativeManager.prototype.sendRuntimeMessage = function(msg, body) { @@ -1368,13 +1346,13 @@ var NativeBridge = (function (extension, debug) { var Bridge = function () {}; Bridge.prototype = { sync: function (data) { - var json = exports.JSON.stringify({ + var json = JSON_.stringify({ cmd: data.cmd, args: data }); if (debug) xwalk.utilss.log('bridge.sync, json: ' + json); var result = extension.internal.sendSyncMessage(json); - var obj = exports.JSON.parse(result); + var obj = JSON_.parse(result); if (obj.error) throw new WebAPIException(obj.code, obj.name, obj.message); return obj.result; @@ -1382,7 +1360,7 @@ var NativeBridge = (function (extension, debug) { async: function (data) { var l = new Listener(); data.cid = Listeners.getInstance().add(l); - var json = exports.JSON.stringify({ + var json = JSON_.stringify({ cmd: data.cmd, args: data }); @@ -1420,7 +1398,7 @@ var NativeBridge = (function (extension, debug) { */ if (debug) xwalk.utils.log('bridge.setMessageListener, json: ' + json); - var data = exports.JSON.parse(json); + var data = JSON_.parse(json); if (data.cid && data.action) { setTimeout(function() { Listeners.getInstance().resolve(data.cid, data.action, data.args, data.keep); -- 2.7.4 From 604bcc857716f51b5ea80f48a644c5682d937ca2 Mon Sep 17 00:00:00 2001 From: Lukasz Bardeli Date: Wed, 16 Aug 2017 12:13:47 +0200 Subject: [PATCH 08/16] [version] 1.96 Change-Id: I245b3ee789170f473b94addb7b305144f6d17e9c Signed-off-by: Lukasz Bardeli --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 8109553..2d60819 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.95 +Version: 1.96 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From 83b247d08b567daecc2ffc1233e2f7bcc386603d Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Thu, 17 Aug 2017 09:05:15 +0200 Subject: [PATCH 09/16] [Sensor] Fix for HRM Sensor Currently, successCallback nor errorCallback functions are invoked after calling start() method for HRM sensor. This occurs only on platforms that do not support HRM sensor. Thus, it's better to invoke errorCallback in above case instead of successCallback. [Verification] Code compiles, TCT 100% pass rate (TM1, TW1), except emulators, which do not support HRM sensor. Sensor startSuccessCallbacks are invoked after receiving an event from sensors. Change-Id: I6484b44fd66f966c72b29fbc277b14f9006ca205 Signed-off-by: Szymon Jastrzebski --- src/sensor/sensor_service.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/sensor/sensor_service.cc b/src/sensor/sensor_service.cc index 2a7510a..88f68b2 100755 --- a/src/sensor/sensor_service.cc +++ b/src/sensor/sensor_service.cc @@ -680,15 +680,21 @@ void HrmSensorData::AddSensor(SensorData* sensor) { PlatformResult HrmSensorData::CallMember(PlatformResult (SensorData::*member) ()) { LoggerD("Entered: %s", type_to_string_map[type()].c_str()); + bool is_any_supported = false; for (const auto& sensor : hrm_sensors_) { if (sensor.second->is_supported()) { + is_any_supported = true; auto res = (sensor.second.get()->*member)(); if (!res) { return res; } } } - return PlatformResult(ErrorCode::NO_ERROR); + if (is_any_supported) { + return PlatformResult(ErrorCode::NO_ERROR); + } else { + return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "None HRM LED sensor is supported."); + } } PlatformResult HrmSensorData::CallMember( @@ -698,15 +704,21 @@ PlatformResult HrmSensorData::CallMember( const std::shared_ptr& result, const std::function&)>& work) { LoggerD("Entered: %s", type_to_string_map[type()].c_str()); + bool is_any_supported = false; for (const auto& sensor : hrm_sensors_) { if (sensor.second->is_supported()) { + is_any_supported = true; auto res = (sensor.second.get()->*member)(result, work); if (!res) { return res; } } } - return PlatformResult(ErrorCode::NO_ERROR); + if (is_any_supported) { + return PlatformResult(ErrorCode::NO_ERROR); + } else { + return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "None HRM LED sensor is supported."); + } } PlatformResult HrmSensorData::IsSupportedImpl(bool* supported) const { -- 2.7.4 From 5bd316c50eb740aad0ee8a230f6ed7b18fb21eb0 Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Thu, 17 Aug 2017 09:00:14 +0200 Subject: [PATCH 10/16] [Sensor] Fix for HRM Sensor Change Listener An exception was thrown when trying to call 'tryCall' with data received from C++ layer, making it not possible to set listener for HRM Sensor. sensorType string starts with 'LED_' but there are no any sensor in _sensorListeners object. [Verification] Sensor TCT passed 100% (TW1). Change-Id: I1b4ffe6ac754c6c407ebafea94b1eda48b59844d Signed-off-by: Szymon Jastrzebski --- src/sensor/sensor_api.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sensor/sensor_api.js b/src/sensor/sensor_api.js index 88426a0..5070009 100755 --- a/src/sensor/sensor_api.js +++ b/src/sensor/sensor_api.js @@ -161,6 +161,9 @@ var _sensorListeners = { }; var _listener = function(object) { + if (object.sensorType.startsWith('LED_')) { + object.sensorType = 'HRM_RAW'; + } _sensorListeners[object.sensorType].tryCall(object); }; -- 2.7.4 From 60f5c501f628cbb217c3845653cbd1189811d38d Mon Sep 17 00:00:00 2001 From: Tomasz Marciniak Date: Wed, 16 Aug 2017 14:39:52 +0200 Subject: [PATCH 11/16] [Filesystem] Fix for moving files on different file systems [Verification] Code compiles. Now files can be moved between different mounted file systems. TCT pass rate 100% (286/286/0/0/0) Change-Id: I5b70bc96f14a53bcebd2b2db3f12748949aab410 Signed-off-by: Tomasz Marciniak --- src/filesystem/filesystem_manager.cc | 52 +++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/src/filesystem/filesystem_manager.cc b/src/filesystem/filesystem_manager.cc index 43f7462..15dd88c 100644 --- a/src/filesystem/filesystem_manager.cc +++ b/src/filesystem/filesystem_manager.cc @@ -316,19 +316,53 @@ void FilesystemManager::Rename( const std::function& error_cb) { LoggerD("enter"); + int status = rename(oldPath.c_str(), newPath.c_str()); - if (0 == status) { - FilesystemStat fileStat = FilesystemStat::getStat(newPath); - if (fileStat.valid) { - success_cb(FilesystemStat::getStat(newPath)); - } else { - LoggerE("Cannot perform stat on new path!"); + if (0 != status) { + if(EXDEV != errno) { + LoggerE("Error while moving file"); error_cb(FilesystemError::Other); + return; + } + + LoggerD("Files are not on the same mounted file system"); + //In case of EXDEV we need to copy and remove file + //EXDEV - oldpath and newpath are not on the same mounted file system. + //Linux permits a file system to be mounted at multiple points, but rename() does not work + //across different mount points, even if the same file system is mounted on both. + + if (FilesystemError::None != copyFile(oldPath, newPath)) { + LoggerE("Error while copying file"); + error_cb(FilesystemError::Other); + return; + } + + struct stat fileStat; + if (0 != stat(oldPath.c_str(), &fileStat)) { + LoggerE("Error while getting file status [%s]", GetErrorString(errno).c_str()); + error_cb(FilesystemError::Other); + return; + } + + int ret = 0; + ret |= chmod(newPath.c_str(), fileStat.st_mode); + ret |= chown(newPath.c_str(), fileStat.st_uid, fileStat.st_gid); + if (0 != ret) { + LoggerE("Error while changing ownership/permissions [%s]", GetErrorString(errno).c_str()); + remove(newPath.c_str()); + error_cb(FilesystemError::Other); + return; + } + + if (0 != remove(oldPath.c_str())) { + LoggerE("Error while removing file [%s]", GetErrorString(errno).c_str()); + remove(newPath.c_str()); + error_cb(FilesystemError::Other); + return; } - } else { - LoggerE("Cannot rename file: %s", GetErrorString(errno).c_str()); - error_cb(FilesystemError::Other); } + + success_cb(FilesystemStat::getStat(newPath)); } void FilesystemManager::ReadDir( -- 2.7.4 From c62f7857490af586a3c5d79b287d797f3849d219 Mon Sep 17 00:00:00 2001 From: Tomasz Marciniak Date: Thu, 17 Aug 2017 14:17:20 +0200 Subject: [PATCH 12/16] [version 1.97] Change-Id: I84d1035105246be61f76dc052f626c52fc83faa3 Signed-off-by: Tomasz Marciniak --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 2d60819..41ac187 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.96 +Version: 1.97 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From c4e6756ae3cf081def57b34413404dade926eba2 Mon Sep 17 00:00:00 2001 From: Segwon Date: Wed, 16 Aug 2017 11:56:49 +0900 Subject: [PATCH 13/16] [Convergence] Change to not support convergence feature. The native API is being refactored now. Till the refactoring is not finished, webapi module should be disabled. Signed-off-by: Segwon Change-Id: I0db5b10a4193b9abf28f9ec029d7aefc51f55a69 --- packaging/webapi-plugins.spec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 90f1e44..ae4a9c0 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -157,7 +157,7 @@ Source0: %{name}-%{version}.tar.gz %define tizen_mobile_feature_tvinputdevice_support 0 -%define tizen_mobile_feature_convergence_support 1 +%define tizen_mobile_feature_convergence_support 0 #################################################################### @@ -235,7 +235,7 @@ Source0: %{name}-%{version}.tar.gz %define tizen_wearable_feature_inputdevice_support 1 %define tizen_wearable_feature_tvinputdevice_support 0 -%define tizen_wearable_feature_convergence_support 1 +%define tizen_wearable_feature_convergence_support 0 #################################################################### @@ -291,7 +291,7 @@ Source0: %{name}-%{version}.tar.gz %define tizen_tv_feature_wi_fi_support 1 %define tizen_tv_feature_inputdevice_support 0 %define tizen_tv_feature_tvinputdevice_support 1 -%define tizen_tv_feature_convergence_support 1 +%define tizen_tv_feature_convergence_support 0 # common, or "unified (undefined)" %define unified_build 1 -- 2.7.4 From fbffbbfa405dd67990a58c232335ef603fb2a1e1 Mon Sep 17 00:00:00 2001 From: Szymon Jastrzebski Date: Mon, 21 Aug 2017 11:35:52 +0200 Subject: [PATCH 14/16] [Sensor] Fixing DefaultEventComparator Comparator DefaultEventComparator should iterate through all received values. It should NOT compare timestamps. The amount of received values depend on the type of used sensor. The sensor_value_count_ values are taken from Native Sensor's Guides. [Verification] Code compiles. TCT (TW1) passed 100%. Change-Id: I60d5af338a7feea2dd4fb40cdff0f6bd03f8d650 Signed-off-by: Szymon Jastrzebski --- src/sensor/sensor_service.cc | 60 ++++++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/src/sensor/sensor_service.cc b/src/sensor/sensor_service.cc index 88f68b2..71a3ab2 100755 --- a/src/sensor/sensor_service.cc +++ b/src/sensor/sensor_service.cc @@ -175,21 +175,27 @@ PlatformResult GetSensorPlatformResult(const int error_code, const std::string & } } -bool MagneticEventComparator(sensor_event_s* l, sensor_event_s* r) { - return (l->values[0] == r->values[0] && - l->values[1] == r->values[1] && - l->values[2] == r->values[2] && - l->accuracy == r->accuracy); +bool DefaultEventComparator(sensor_event_s* l, sensor_event_s* r, const unsigned int value_count) { + for (unsigned int i = 0; i < value_count; ++i) { + if (l->values[i] != r->values[i]) { + return false; + } + } + return true; +} + +bool MagneticEventComparator(sensor_event_s* l, sensor_event_s* r, const unsigned int value_count) { + return DefaultEventComparator(l, r, value_count) ? l->accuracy == r->accuracy : false; } } // namespace class SensorData { public: - typedef bool (*EventComparator)(sensor_event_s* l, sensor_event_s* r); + typedef bool (*EventComparator)(sensor_event_s* l, sensor_event_s* r, const unsigned int value_count); SensorData(SensorInstance& instance, sensor_type_e type_enum, - const std::string& name, EventComparator comparator = + const std::string& name, const unsigned int sensor_value_count, EventComparator comparator = DefaultEventComparator); virtual ~SensorData(); @@ -213,10 +219,10 @@ class SensorData { private: static void SensorCallback(sensor_h sensor, sensor_event_s* event, void* user_data); - static bool DefaultEventComparator(sensor_event_s* l, sensor_event_s* r); sensor_type_e type_enum_; EventComparator comparator_; + const unsigned int sensor_value_count_; sensor_h handle_; sensor_listener_h listener_; sensor_event_s previous_event_; @@ -226,9 +232,11 @@ class SensorData { }; SensorData::SensorData(SensorInstance& instance, sensor_type_e type_enum, - const std::string& name, EventComparator comparator) + const std::string& name, const unsigned int sensor_value_count, + EventComparator comparator) : type_enum_(type_enum), comparator_(comparator), + sensor_value_count_(sensor_value_count), handle_(nullptr), listener_(nullptr), previous_event_(), @@ -270,10 +278,6 @@ void SensorData::SensorCallback(sensor_h sensor, sensor_event_s* event, void* us Instance::PostMessage(&that->instance_, result.serialize().c_str()); } -bool SensorData::DefaultEventComparator(sensor_event_s* l, sensor_event_s* r) { - return (l->timestamp == r->timestamp); -} - PlatformResult SensorData::CheckInitialization() { LoggerD("Entered: %s", type_to_string_map[type()].c_str()); @@ -348,7 +352,7 @@ bool SensorData::is_supported() { bool SensorData::UpdateEvent(sensor_event_s* event) { LoggerD("Entered: %s", type_to_string_map[type()].c_str()); - if (comparator_(&previous_event_, event)) { + if (comparator_(&previous_event_, event, sensor_value_count_)) { // previous and current events are the same -> no update return false; } else { @@ -662,11 +666,12 @@ class HrmSensorData : public SensorData { }; HrmSensorData::HrmSensorData(SensorInstance& instance) - : SensorData(instance, SENSOR_CUSTOM, "HRM_RAW") { + : SensorData(instance, SENSOR_CUSTOM, "HRM_RAW", 1) { LoggerD("Entered: %s", type_to_string_map[type()].c_str()); - AddSensor(new SensorData(instance, SENSOR_HRM_LED_IR, "LED_IR")); - AddSensor(new SensorData(instance, SENSOR_HRM_LED_RED, "LED_RED")); - AddSensor(new SensorData(instance, SENSOR_HRM_LED_GREEN, "LED_GREEN")); + // For amount of retrieved values from sensors please refer to native guides. + AddSensor(new SensorData(instance, SENSOR_HRM_LED_IR, "LED_IR", 1)); + AddSensor(new SensorData(instance, SENSOR_HRM_LED_RED, "LED_RED", 1)); + AddSensor(new SensorData(instance, SENSOR_HRM_LED_GREEN, "LED_GREEN", 1)); } HrmSensorData::~HrmSensorData() { @@ -812,16 +817,17 @@ SensorService::SensorService(SensorInstance& instance) : instance_(instance) { LoggerD("Entered"); - AddSensor(new SensorData(instance, SENSOR_LIGHT, "LIGHT")); - AddSensor(new SensorData(instance, SENSOR_MAGNETIC, "MAGNETIC", MagneticEventComparator)); - AddSensor(new SensorData(instance, SENSOR_PRESSURE, "PRESSURE")); - AddSensor(new SensorData(instance, SENSOR_PROXIMITY, "PROXIMITY")); - AddSensor(new SensorData(instance, SENSOR_ULTRAVIOLET, "ULTRAVIOLET")); + // For amount of retrieved values from sensors please refer to native guides. + AddSensor(new SensorData(instance, SENSOR_LIGHT, "LIGHT", 1)); + AddSensor(new SensorData(instance, SENSOR_MAGNETIC, "MAGNETIC", 3, MagneticEventComparator)); + AddSensor(new SensorData(instance, SENSOR_PRESSURE, "PRESSURE", 1)); + AddSensor(new SensorData(instance, SENSOR_PROXIMITY, "PROXIMITY", 1)); + AddSensor(new SensorData(instance, SENSOR_ULTRAVIOLET, "ULTRAVIOLET", 1)); AddSensor(new HrmSensorData(instance)); - AddSensor(new SensorData(instance, SENSOR_GRAVITY, "GRAVITY")); - AddSensor(new SensorData(instance, SENSOR_GYROSCOPE, "GYROSCOPE")); - AddSensor(new SensorData(instance, SENSOR_GYROSCOPE_ROTATION_VECTOR, "GYROSCOPE_ROTATION_VECTOR")); - AddSensor(new SensorData(instance, SENSOR_LINEAR_ACCELERATION, "LINEAR_ACCELERATION")); + AddSensor(new SensorData(instance, SENSOR_GRAVITY, "GRAVITY", 3)); + AddSensor(new SensorData(instance, SENSOR_GYROSCOPE, "GYROSCOPE", 3)); + AddSensor(new SensorData(instance, SENSOR_GYROSCOPE_ROTATION_VECTOR, "GYROSCOPE_ROTATION_VECTOR", 4)); + AddSensor(new SensorData(instance, SENSOR_LINEAR_ACCELERATION, "LINEAR_ACCELERATION", 3)); } SensorService::~SensorService() { -- 2.7.4 From b8c4fb3379446eb639e78fbf00d04644f3cfdac3 Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Mon, 21 Aug 2017 12:30:13 +0200 Subject: [PATCH 15/16] [version] 1.98 Change-Id: I751ce338fdcce6ab1de120b31b427cbbad065b34 Signed-off-by: Piotr Kosko --- packaging/webapi-plugins.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 41ac187..4f453a5 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -10,7 +10,7 @@ %define crosswalk_extensions_path %{_libdir}/%{crosswalk_extensions} Name: webapi-plugins -Version: 1.97 +Version: 1.98 Release: 0 License: Apache-2.0 and BSD-3-Clause and MIT Group: Development/Libraries -- 2.7.4 From d22089605ddd2fbef0c9c1bf651b11efc7dd8798 Mon Sep 17 00:00:00 2001 From: Piotr Kosko Date: Tue, 29 Aug 2017 11:54:08 +0200 Subject: [PATCH 16/16] [Power] removed unneeded deviced dependency [Verification] Code compilese without errors. TCT passrate didn't change. Change-Id: Ie59b8d6e8f94d1727d3c9158d1704835458a2da2 Signed-off-by: Piotr Kosko --- packaging/webapi-plugins.spec | 4 ---- src/power/power.gyp | 1 - 2 files changed, 5 deletions(-) diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index 1032783..eb38508 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -465,10 +465,6 @@ BuildRequires: pkgconfig(chromium-efl) %endif %if "%{?tizen_feature_power_support}" == "1" || "%{?unified_build}" == "1" -BuildRequires: pkgconfig(deviced) -%endif - -%if "%{?tizen_feature_power_support}" == "1" || "%{?unified_build}" == "1" BuildRequires: pkgconfig(capi-appfw-application) %endif diff --git a/src/power/power.gyp b/src/power/power.gyp index 8b6c10f..cb3ff35 100755 --- a/src/power/power.gyp +++ b/src/power/power.gyp @@ -25,7 +25,6 @@ 'variables': { 'packages': [ 'capi-system-device', - 'deviced', 'vconf', ] }, -- 2.7.4