From: Pawel Wasowski Date: Wed, 16 Sep 2020 04:04:54 +0000 (+0200) Subject: [Bluetooth] Reregister read/write value request callbacks on server start X-Git-Tag: submit/tizen/20200923.101308~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c7d5c5fb5bf3581e6bd5ad90c819365245795064;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Bluetooth] Reregister read/write value request callbacks on server start This commit implements reregistering read/write value callbacks, that were once registered before a BluetoothGATTServer::stop() call. [Verification] Tested in Chrome DevTools, callbacks are reregistered after restarting the server Change-Id: If67ee9ccf56b1aaac65a6c830b0b24ddf6e39b36 Signed-off-by: Pawel Wasowski --- diff --git a/src/bluetooth/bluetooth_api.js b/src/bluetooth/bluetooth_api.js index 152454ff..1e0b5f5f 100755 --- a/src/bluetooth/bluetooth_api.js +++ b/src/bluetooth/bluetooth_api.js @@ -4023,6 +4023,52 @@ var ResultCallbacksAggregator = function(callbacksNum, onAllSucceeded, onFailure }; }; +function _getServicesUnregisteredInNativeLayer() { + var servicesUnregisteredInNativeLayer = []; + for (var i = 0; i < _BluetoothGATTServerServices.length; ++i) { + if ( + !_BluetoothGATTServerServicesRegisteredInNativeLayer[ + _BluetoothGATTServerServices[i]._id + ] + ) { + servicesUnregisteredInNativeLayer.push(_BluetoothGATTServerServices[i]); + } + } + return servicesUnregisteredInNativeLayer; +} + +function _getIdsToReregisterReadWriteCallbacks(servicesUnregisteredInNativeLayer) { + var idsToRegisterWriteValueCallbacks = []; + var idsToRegisterReadValueCallbacks = []; + + for (var i = 0; i < servicesUnregisteredInNativeLayer.length; ++i) { + var serviceComponentIds = _getIncludedServicesAndItsComponentsIdsRecursively( + servicesUnregisteredInNativeLayer[i] + ); + + for (var j = 0; j < serviceComponentIds.length; ++j) { + var _id = serviceComponentIds[j]; + var callbackName = 'ReadValueCallback' + _id; + + /* + * Only some of the serviceComponentIds are characteristics and descriptors + * and within them, only some have read/write callbacks registered. + * We have to check if the callbacks were registered for each id. + */ + if (callbackName in _BluetoothGATTServerReadWriteValueRequestCallbacks) { + idsToRegisterReadValueCallbacks.push(_id); + } + + callbackName = 'WriteValueCallback' + _id; + if (callbackName in _BluetoothGATTServerReadWriteValueRequestCallbacks) { + idsToRegisterWriteValueCallbacks.push(_id); + } + } + } + + return [idsToRegisterReadValueCallbacks, idsToRegisterWriteValueCallbacks]; +} + var BluetoothGATTServer_valid_start_errors = [ 'InvalidStateError', 'NotSupportedError', @@ -4034,6 +4080,33 @@ var BluetoothGATTServer_valid_start_exceptions = [ 'SecurityError' ]; +function _reregisterCallback(_id, nativeFunction, successCallback, errorCallback) { + /* + * This function should only be used to reregister read/write value request + * callbacks in native layer for characteristics/descriptors, that have + * had such callbacks registered before the last server's stop(). + * As JS listeners corresponding to these callbacks already exist in JS, + * only C++ callbacks have to be reregistered. + */ + var callback = function(result) { + if (native.isFailure(result)) { + errorCallback(native.getErrorObject(result)); + } else { + successCallback(); + } + }; + + var result = native.call(nativeFunction, { _id: _id }, callback); + + if (native.isFailure(result)) { + throw native.getErrorObjectAndValidate( + result, + BluetoothGATTServer_valid_start_exceptions, + AbortError + ); + } +} + BluetoothGATTServer.prototype.start = function() { privUtils_.log('Entered BluetoothGATTServer.start()'); var args = AV.validateArgs(arguments, [ @@ -4051,16 +4124,19 @@ BluetoothGATTServer.prototype.start = function() { } ]); - var servicesUnregisteredInNativeLayer = []; - for (var i = 0; i < this.services.length; ++i) { - if (this.services[i]) { - if ( - !_BluetoothGATTServerServicesRegisteredInNativeLayer[this.services[i]._id] - ) { - servicesUnregisteredInNativeLayer.push(this.services[i]); - } - } - } + var servicesUnregisteredInNativeLayer = _getServicesUnregisteredInNativeLayer(); + /* + * Characteristics and descriptors that were registered in the server before the last stop() call + * could have had read/write value request callbacks registered. + * These callbacks have to be reregistered (only) in native layer. + * These arrays contain _ids of characteristics and descriptors, that will have their callbacks + * reregistered. + */ + var idsToReregisterReadWriteValueCallbacks = _getIdsToReregisterReadWriteCallbacks( + servicesUnregisteredInNativeLayer + ); + var idsToReregisterReadValueCallbacks = idsToReregisterReadWriteValueCallbacks[0]; + var idsToReregisterWriteValueCallbacks = idsToReregisterReadWriteValueCallbacks[1]; var startServerCallback = function(result) { if (native.isFailure(result)) { @@ -4078,8 +4154,12 @@ BluetoothGATTServer.prototype.start = function() { }; if (servicesUnregisteredInNativeLayer.length) { + var numberOfCallbacksToWaitFor = + servicesUnregisteredInNativeLayer.length + + idsToReregisterReadValueCallbacks.length + + idsToReregisterWriteValueCallbacks.length; var registerServiceCallbacksAggregator = new ResultCallbacksAggregator( - servicesUnregisteredInNativeLayer.length, + numberOfCallbacksToWaitFor, function onAllSucceeded() { var result = native.call( 'BluetoothGATTServerStart', @@ -4109,13 +4189,7 @@ BluetoothGATTServer.prototype.start = function() { var registerServicesCallback = function(result) { if (native.isFailure(result)) { - registerServiceCallbacksAggregator.errorCallback( - native.getErrorObjectAndValidate( - result, - BluetoothGATTServer_valid_start_errors, - AbortError - ) - ); + registerServiceCallbacksAggregator.errorCallback(result); } else { registerServiceCallbacksAggregator.successCallback(); } @@ -4135,6 +4209,24 @@ BluetoothGATTServer.prototype.start = function() { ); } } + + for (var i = 0; i < idsToReregisterReadValueCallbacks.length; ++i) { + _reregisterCallback( + idsToReregisterReadValueCallbacks[i], + 'BluetoothGATTServerSetReadValueRequestCallback', + registerServiceCallbacksAggregator.successCallback, + registerServiceCallbacksAggregator.errorCallback + ); + } + + for (var i = 0; i < idsToReregisterWriteValueCallbacks.length; ++i) { + _reregisterCallback( + idsToReregisterWriteValueCallbacks[i], + 'BluetoothGATTServerSetWriteValueRequestCallback', + registerServiceCallbacksAggregator.successCallback, + registerServiceCallbacksAggregator.errorCallback + ); + } } else { var result = native.call('BluetoothGATTServerStart', {}, startServerCallback); diff --git a/src/bluetooth/bluetooth_gatt_server_service.cc b/src/bluetooth/bluetooth_gatt_server_service.cc index e39e8580..fe05c028 100644 --- a/src/bluetooth/bluetooth_gatt_server_service.cc +++ b/src/bluetooth/bluetooth_gatt_server_service.cc @@ -450,6 +450,11 @@ PlatformResult BluetoothGATTServerService::SetReadValueRequestCallback( auto _id = static_cast(args.get(kId).get()); LoggerD("Setting read value request callback for a GATT entity with _id: %d", _id); + if (gatt_objects_.find(_id) == gatt_objects_.end()) { + LoggerE("No GATT handle for entity with _id [%d]", _id); + return common::PlatformResult{ErrorCode::ABORT_ERR, "Failed to set read value request callback"}; + } + auto gatt_handle = gatt_objects_[_id]; callback_names_[std::make_pair(gatt_handle, kReadCallback)] = "ReadValueRequestCallback_" + std::to_string(_id); @@ -502,6 +507,11 @@ PlatformResult BluetoothGATTServerService::SetWriteValueRequestCallback( auto _id = static_cast(args.get(kId).get()); LoggerD("Setting write value request callback for a GATT entity with _id: %d", _id); + if (gatt_objects_.find(_id) == gatt_objects_.end()) { + LoggerE("No GATT handle for entity with _id [%d]", _id); + return common::PlatformResult{ErrorCode::ABORT_ERR, "Failed to set write value request callback"}; + } + auto gatt_handle = gatt_objects_[_id]; callback_names_[std::make_pair(gatt_handle, kWriteCallback)] = "WriteValueRequestCallback_" + std::to_string(_id);