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);