From: Piotr Kosko Date: Thu, 21 Sep 2017 10:13:10 +0000 (+0200) Subject: [Sensor] fixing listener behaviours X-Git-Tag: submit/tizen_3.0/20170921.132449^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Faccepted%2Ftizen_3.0_ivi;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Sensor] fixing listener behaviours [Bug] Listeners are not called in deterministic way, several "api calls order" issues are fixed. [Verification] Code compiles properly TCT passrate 100% - auto & manual Web widget service tests of sensor - 119 pass - 100% passrate Change-Id: I720e23e0f23a9a849fb2d507e8721f196578ac48 Signed-off-by: Piotr Kosko --- diff --git a/src/sensor/sensor_api.js b/src/sensor/sensor_api.js index 7a68684a..8c34e338 100755 --- a/src/sensor/sensor_api.js +++ b/src/sensor/sensor_api.js @@ -49,10 +49,17 @@ var MagneticSensorAccuracy = { VERYGOOD : 'ACCURACY_VERYGOOD' }; +var SensorStates = { + NOT_STARTED : 0, + STARTING : 1, + STARTED : 2 +}; + + // helper class for sensor listeners var SensorListener = function (type, constructor) { this.sensorType = type; - this.isStarted = false; + this.state = SensorStates.NOT_STARTED; this.callback = undefined; this.constructor = constructor; }; @@ -64,8 +71,9 @@ SensorListener.prototype.tryCall = function (object) { }; SensorListener.prototype.start = function (successCallback, errorCallback) { - if (!this.isStarted) { + if (SensorStates.STARTED != this.state) { // sensor not started + this.state = SensorStates.STARTING; var thisObject = this; native_.call('Sensor_start', {'sensorType' : thisObject.sensorType}, function(result) { @@ -74,7 +82,7 @@ SensorListener.prototype.start = function (successCallback, errorCallback) { errorCallback(native_.getErrorObject(result)); } } else { - thisObject.isStarted = true; + thisObject.state = SensorStates.STARTED; successCallback(); } } @@ -86,12 +94,12 @@ SensorListener.prototype.start = function (successCallback, errorCallback) { }; SensorListener.prototype.stop = function () { - if (this.isStarted) { + if (SensorStates.NOT_STARTED != this.state) { var result = native_.callSync('Sensor_stop', {'sensorType' : this.sensorType}); if (native_.isFailure(result)) { throw native_.getErrorObject(result); } - this.isStarted = false; + this.state = SensorStates.NOT_STARTED; } }; @@ -123,7 +131,7 @@ SensorListener.prototype.unsetListener = function () { SensorListener.prototype.getData = function (successCallback, errorCallback) { var thisObj = this; - if (!thisObj.isStarted) { + if (SensorStates.STARTED != this.state) { setTimeout(function() { if (!T_.isNullOrUndefined(errorCallback)) { errorCallback(new WebAPIException( diff --git a/src/sensor/sensor_service.cc b/src/sensor/sensor_service.cc index 71a3ab25..1596ba68 100755 --- a/src/sensor/sensor_service.cc +++ b/src/sensor/sensor_service.cc @@ -219,6 +219,7 @@ class SensorData { private: static void SensorCallback(sensor_h sensor, sensor_event_s* event, void* user_data); + PlatformResult AddDelayedStartSuccessCb(const std::function& successCb); sensor_type_e type_enum_; EventComparator comparator_; @@ -229,6 +230,8 @@ class SensorData { common::optional is_supported_; SensorInstance& instance_; std::mutex initialization_mutex_; + bool is_change_listener_set_; + std::vector> delayed_success_callbacks_; }; SensorData::SensorData(SensorInstance& instance, sensor_type_e type_enum, @@ -239,8 +242,10 @@ SensorData::SensorData(SensorInstance& instance, sensor_type_e type_enum, sensor_value_count_(sensor_value_count), handle_(nullptr), listener_(nullptr), - previous_event_(), - instance_(instance) { + previous_event_{0,0,0,-FLT_MAX}, // setting dumb non-zero value to differ init value from + // "good" zero values from sensor + instance_(instance), + is_change_listener_set_(false) { type_to_string_map.insert(std::make_pair(type_enum, name)); string_to_type_map.insert(std::make_pair(name, type_enum)); @@ -267,6 +272,23 @@ void SensorData::SensorCallback(sensor_h sensor, sensor_event_s* event, void* us LoggerD("Entered: %s", type_to_string_map[that->type()].c_str()); + if (!that->delayed_success_callbacks_.empty()) { + for_each(that->delayed_success_callbacks_.begin(), that->delayed_success_callbacks_.end(), + [](std::function& callback) { + LoggerD("Calling delayed start succcess callback"); + callback(); + }); + that->delayed_success_callbacks_.erase(that->delayed_success_callbacks_.begin(), + that->delayed_success_callbacks_.end()); + if (!that->is_change_listener_set_) { + LoggerD("unregistering temporary listener used to delay start success callback"); + int ret = sensor_listener_unset_event_cb(that->listener_); + if (SENSOR_ERROR_NONE != ret) { + LoggerE("unsetting temporary listener failed: %d", ret); + } + } + } + if (!that->UpdateEvent(event)) { // value didn't change - ignore return; @@ -361,16 +383,23 @@ bool SensorData::UpdateEvent(sensor_event_s* event) { } } -struct DelaySuccessCbData { - DelaySuccessCbData(const std::shared_ptr &_result) - : result(_result), - delay_success_cb_listener(nullptr) { - } +PlatformResult SensorData::AddDelayedStartSuccessCb(const std::function& successCb) { + LoggerD("Entered"); + delayed_success_callbacks_.push_back(successCb); - const std::shared_ptr result; - sensor_listener_h delay_success_cb_listener; - std::function&)> report_result; -}; + if (!is_change_listener_set_) { + LoggerD("Adding temporary listener by hand"); + int ret = sensor_listener_set_event_cb(listener_, 10, // as small interval as possible for tmp listener + SensorCallback, this); + if (SENSOR_ERROR_NONE != ret) { + LoggerE("sensor_listener_set_event_cb returned error: %d", ret); + return GetSensorPlatformResult(ret, "sensor_listener_set_event_cb"); + } + } else { + LoggerD("Temporary listener is not needed"); + } + return PlatformResult(ErrorCode::NO_ERROR); +} PlatformResult SensorData::Start(const std::shared_ptr& result, const std::function&)>& report_result) { @@ -382,75 +411,19 @@ PlatformResult SensorData::Start(const std::shared_ptr& result, return res; } - sensor_listener_h delay_success_cb_listener = nullptr; - int ret = sensor_create_listener(handle_, &delay_success_cb_listener); - if (SENSOR_ERROR_NONE != ret) { - return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, - "Failed to create listener.", - ("sensor_create_listener() error: %d, message: %s", ret, get_error_message(ret))); - } - - ret = sensor_listener_set_option(delay_success_cb_listener, SENSOR_OPTION_ALWAYS_ON); - if (SENSOR_ERROR_NONE != ret) { - sensor_destroy_listener(delay_success_cb_listener); - LoggerE("sensor_listener_set_option : %d", ret); - return GetSensorPlatformResult(ret, "sensor_listener_set_option"); - } - - DelaySuccessCbData *data = new DelaySuccessCbData(result); - data->delay_success_cb_listener = delay_success_cb_listener; - data->report_result = report_result; - - ret = sensor_listener_set_event_cb(delay_success_cb_listener, 10,//as less as possible - [](sensor_h sensor, sensor_event_s* event, void* user_data) -> void { - LoggerD("Enter"); - DelaySuccessCbData *data = static_cast(user_data); - if (nullptr == data) { - LoggerE("data equal to nullptr"); - return; - } - - SCOPE_EXIT { - delete data; - }; - - sensor_listener_h listener = data->delay_success_cb_listener; - ReportSuccess(data->result->get()); - data->report_result(data->result); - - int ret = sensor_listener_unset_event_cb(listener); - if (SENSOR_ERROR_NONE != ret) { - LoggerE("sensor_listener_unset_event_cb : %d", ret); - } - - ret = sensor_destroy_listener(listener); - if (SENSOR_ERROR_NONE != ret) { - LoggerE("sensor_listener_unset_event_cb : %d", ret); - } - }, data); - - if (SENSOR_ERROR_NONE != ret) { - sensor_destroy_listener(delay_success_cb_listener); - delete data; - LoggerE("sensor_listener_set_event_cb : %d", ret); - return GetSensorPlatformResult(ret, "sensor_listener_set_event_cb"); - } - - ret = sensor_listener_start(delay_success_cb_listener); - if (SENSOR_ERROR_NONE != ret) { - sensor_listener_unset_event_cb(delay_success_cb_listener); - sensor_destroy_listener(delay_success_cb_listener); - delete data; - LoggerE("sensor_listener_start : %d", ret); - return GetSensorPlatformResult(ret, "sensor_listener_start"); + auto delayed_success_callback = [this, result, report_result] () { + LoggerD("Delayed success callback"); + ReportSuccess(result->get()); + report_result(result); + }; + res = AddDelayedStartSuccessCb(delayed_success_callback); + if(!res) { + return res; } sensor_listener_set_option(listener_, SENSOR_OPTION_ALWAYS_ON); - ret = sensor_listener_start(listener_); + int ret = sensor_listener_start(listener_); if (SENSOR_ERROR_NONE != ret) { - sensor_listener_unset_event_cb(delay_success_cb_listener); - sensor_destroy_listener(delay_success_cb_listener); - delete data; LoggerE("sensor_listener_start : %d", ret); return GetSensorPlatformResult(ret, "sensor_listener_start"); } @@ -474,6 +447,12 @@ PlatformResult SensorData::Stop() { return GetSensorPlatformResult(ret, "sensor_listener_stop"); } + // reseting delayed success callbacks flag and saved event values + previous_event_ = {0,0,0,-FLT_MAX}; // setting dumb non-zero value to differ init value from + // "good" zero values from sensor + delayed_success_callbacks_.erase(delayed_success_callbacks_.begin(), + delayed_success_callbacks_.end()); + return PlatformResult(ErrorCode::NO_ERROR); } @@ -502,6 +481,8 @@ PlatformResult SensorData::SetChangeListener(unsigned int interval, unsigned int return GetSensorPlatformResult(ret, "sensor_listener_set_event_cb"); } + is_change_listener_set_ = true; + return PlatformResult(ErrorCode::NO_ERROR); } @@ -521,6 +502,8 @@ PlatformResult SensorData::UnsetChangeListener() { return GetSensorPlatformResult(ret, "sensor_listener_unset_event_cb"); } + is_change_listener_set_ = false; + return PlatformResult(ErrorCode::NO_ERROR); }