From: Pawel Wasowski Date: Wed, 12 Aug 2020 10:48:16 +0000 (+0200) Subject: [Bluetooth] Implement re-registering GATT services on server start X-Git-Tag: submit/tizen/20200909.074050~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=38527f9fafe7f8d673304439bce623f2cb720c6f;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [Bluetooth] Implement re-registering GATT services on server start The services, that are once successfully registered on the local GATT server will be present on it and re-registered on each start() call. This commit implements re-registering services on start. [Verification] Reregistering works - services that were present before stop() are reregistered in the server after start(). Change-Id: I973ab73f652a8faa72fa2c933ae27666e1fe611a Signed-off-by: Pawel Wasowski --- diff --git a/src/bluetooth/bluetooth_api.js b/src/bluetooth/bluetooth_api.js index 5cd60055..d030dca6 100755 --- a/src/bluetooth/bluetooth_api.js +++ b/src/bluetooth/bluetooth_api.js @@ -3221,6 +3221,13 @@ BluetoothAdapter.prototype.getBluetoothProfileHandler = function() { // class BluetoothGATTServer //////////////////////// var _BluetoothGATTServerServices = []; +/* + * This set is used in BluetoothGATTServer::start() to check which services + * from BluetoothGATTServer::services have already been registered in native + * layer and which have to be registered. + */ +var _BluetoothGATTServerServicesRegisteredInNativeLayer = {}; + var BluetoothGATTServer = function() { Object.defineProperties(this, { services: { @@ -3296,6 +3303,46 @@ BluetoothGATTServer.prototype.registerService = function() { } }; +/* + * Objects of this class are used to wait for multiple callbacks results. + * + * Its successCallback and errorCallback members should be passed as + * the success and error callbacks, respectively, to the functions we wait for. + * When the functions we wait for are called callbacksNum times, either + * onAllSucceeded or onFailure is called, depending on whether only + * successCallback was called or not. + * + * For the usage example, take a look at BluetoothGATTServer.prototype.start, + * where it's used to wait for registration of multiple services. + */ +var ResultCallbacksAggregator = function(callbacksNum, onAllSucceeded, onFailure) { + var _callbacksNum = callbacksNum; + var _allSucceeded = true; + var _error; + + this.successCallback = function (){ + _callbacksNum--; + + if (!_callbacksNum) { + if (_allSucceeded) { + onAllSucceeded(); + } else { + onFailure(_error); + } + } + }; + + this.errorCallback = function(error) { + _callbacksNum--; + _allSucceeded = false; + _error = error; + + if (!_callbacksNum) { + onFailure(_error); + } + }; +}; + var BluetoothGATTServer_valid_start_errors = ['InvalidStateError', 'NotSupportedError', 'AbortError']; var BluetoothGATTServer_valid_start_exceptions = ['InvalidStateError', 'TypeMismatchError', 'SecurityError']; @@ -3316,7 +3363,16 @@ BluetoothGATTServer.prototype.start = function() { } ]); - var callback = function(result) { + 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 startServerCallback = function(result) { if (native.isFailure(result)) { native.callIfPossible(args.errorCallback, native.getErrorObjectAndValidate(result, @@ -3326,9 +3382,48 @@ BluetoothGATTServer.prototype.start = function() { } }; - var result = native.call('BluetoothGATTServerStart', {}, callback); - if (native.isFailure(result)) { - throw native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_start_exceptions, AbortError); + if (servicesUnregisteredInNativeLayer.length) { + var registerServiceCallbacksAggregator = new ResultCallbacksAggregator(servicesUnregisteredInNativeLayer.length, + function onAllSucceeded() { + + var result = native.call('BluetoothGATTServerStart', {}, startServerCallback); + + if (native.isFailure(result)) { + throw native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_start_exceptions, AbortError); + } + }, + function onFailure(error) { + native.callIfPossible(args.errorCallback, + native.getErrorObjectAndValidate(error, + BluetoothGATTServer_valid_start_errors, AbortError)); + }); + + var registerServicesCallback = function(result) { + if (native.isFailure(result)) { + registerServiceCallbacksAggregator.errorCallback( + native.getErrorObjectAndValidate(result, + BluetoothGATTServer_valid_start_errors, AbortError)); + } else { + registerServiceCallbacksAggregator.successCallback(); + } + }; + + for (var i = 0; i < servicesUnregisteredInNativeLayer.length; ++i) { + var result = native.call('BluetoothGATTServerRegisterService', servicesUnregisteredInNativeLayer[i], registerServicesCallback); + if (native.isFailure(result)) { + throw native.getErrorObjectAndValidate( + result, + BluetoothGATTServer_valid_registerService_exceptions, + AbortError + ); + } + } + } else { + var result = native.call('BluetoothGATTServerStart', {}, startServerCallback); + + if (native.isFailure(result)) { + throw native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_start_exceptions, AbortError); + } } } @@ -3358,6 +3453,7 @@ BluetoothGATTServer.prototype.stop = function() { native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_stop_errors, AbortError)); } else { + _BluetoothGATTServerServicesRegisteredInNativeLayer = {}; native.callIfPossible(args.successCallback); } };