From: Pawel Wasowski
Date: Tue, 18 Aug 2020 03:08:55 +0000 (+0200)
Subject: [Bluetooth] Implement BluetoothGATTServerService::unregister()
X-Git-Tag: submit/tizen/20200918.124009~11
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=87cb625f1cd2e3675f668b3807291ce5da270ced;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git
[Bluetooth] Implement BluetoothGATTServerService::unregister()
This commit implements Implement BluetoothGATTServerService::unregister()
in JS and native layers.
[Verification] Basic tests in Chrome Dev Tools have shown that it works.
More thorough tests may be needed.
Change-Id: I0d0cd99ea2e11337ac19970d07ec92730c1cb2a0
Signed-off-by: Pawel Wasowski
---
diff --git a/src/bluetooth/bluetooth_api.js b/src/bluetooth/bluetooth_api.js
index f6f4061d..5fe99390 100755
--- a/src/bluetooth/bluetooth_api.js
+++ b/src/bluetooth/bluetooth_api.js
@@ -174,8 +174,7 @@ tizen.BluetoothLEServiceData = function(d) {
set: function(v) {
try {
data_ = BluetoothManager_toDOMString(v);
- }
- catch (err) {
+ } catch (err) {
data_ = Converter.toString(v);
}
}
@@ -1676,9 +1675,9 @@ var BluetoothGATTService = function(data, address) {
if (native.isSuccess(result)) {
var resultObject = native.getResultObject(result);
resultObject.forEach(function(c) {
- if (!T.isNullOrUndefined(c)) {
- characteristics.push(new BluetoothGATTCharacteristic(c, address_));
- }
+ if (!T.isNullOrUndefined(c)) {
+ characteristics.push(new BluetoothGATTCharacteristic(c, address_));
+ }
});
}
return characteristics;
@@ -1809,6 +1808,122 @@ Object.defineProperty(BluetoothGATTServerService.prototype, 'constructor', {
writable: true
});
+function _getIncludedServicesAndItsComponentsIdsRecursively(service) {
+ var ids = [];
+
+ for (var serviceIndex = 0; serviceIndex < service.services.length; ++serviceIndex) {
+ ids.push(service.services[serviceIndex]._id);
+ ids = ids.concat(
+ _getIncludedServicesAndItsComponentsIdsRecursively(
+ service.services[serviceIndex]
+ )
+ );
+ }
+
+ for (
+ var characteristicIndex = 0;
+ characteristicIndex < service.characteristics.length;
+ ++characteristicIndex
+ ) {
+ ids.push(service.characteristics[characteristicIndex]._id);
+
+ for (
+ var descriptorIndex = 0;
+ descriptorIndex <
+ service.characteristics[characteristicIndex].descriptors.length;
+ ++descriptorIndex
+ ) {
+ ids.push(
+ service.characteristics[characteristicIndex].descriptors[descriptorIndex]
+ ._id
+ );
+ }
+ }
+
+ return ids;
+}
+
+var BluetoothGATTServer_valid_unregisterService_errors = [
+ 'InvalidStateError',
+ 'AbortError'
+];
+var BluetoothGATTServer_valid_unregisterService_exceptions = [
+ 'TypeMismatchError',
+ 'SecurityError'
+];
+
+BluetoothGATTServerService.prototype.unregister = function() {
+ var args = AV.validateArgs(arguments, [
+ {
+ name: 'successCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ }
+ ]);
+
+ var serviceIndex = _BluetoothGATTServerServices.findIndex(
+ function(service) {
+ return service._id === this._id;
+ }.bind(this)
+ );
+
+ if (serviceIndex === -1) {
+ throw new WebAPIException(
+ 'AbortError',
+ 'The service is not registered in the local GATT server'
+ );
+ }
+
+ function removeFromJSArrayAndCallSuccessCb() {
+ _BluetoothGATTServerServices.splice(serviceIndex, 1);
+ native.callIfPossible(args.successCallback);
+ }
+
+ if (!_BluetoothGATTServerServicesRegisteredInNativeLayer[this._id]) {
+ removeFromJSArrayAndCallSuccessCb();
+ return;
+ }
+
+ var callback = function(result) {
+ if (native.isFailure(result)) {
+ native.callIfPossible(
+ args.errorCallback,
+ native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_unregisterService_errors,
+ AbortError
+ )
+ );
+ } else {
+ delete _BluetoothGATTServerServicesRegisteredInNativeLayer[this._id];
+ removeFromJSArrayAndCallSuccessCb();
+ }
+ }.bind(this);
+
+ var callArgs = {
+ _id: this._id,
+ idsToRemoveFromNativeLayer: _getIncludedServicesAndItsComponentsIdsRecursively(
+ this
+ )
+ };
+ var result = native.call('BluetoothGATTServerUnregisterService', callArgs, callback);
+
+ if (native.isFailure(result)) {
+ throw native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_unregisterService_errors,
+ AbortError
+ );
+ }
+};
+
var numberArrayToByteArray = function(array) {
var d = [];
@@ -1821,13 +1936,13 @@ var numberArrayToByteArray = function(array) {
//class BluetoothGATTCharacteristic ///////////////////////////
var BluetoothGATTCharacteristic = function(data, address) {
if (!T.isObject(data)) {
- return null;
+ return null;
}
var address_ = address;
var handle_ = data.handle;
var descriptors_ = data.descriptors.map(function(descriptor_data) {
return new BluetoothGATTDescriptor(descriptor_data, address_);
- });
+ });
var isBroadcast_ = data.isBroadcast;
var hasExtendedProperties_ = data.hasExtendedProperties;
var isNotify_ = data.isNotify;
@@ -1949,7 +2064,11 @@ var BluetoothGATTCharacteristic = function(data, address) {
var callArgs = { handle: handle_, address: address_ };
- var result = native.call('BluetoothGATTClientServiceReadValue', callArgs, callback);
+ var result = native.call(
+ 'BluetoothGATTClientServiceReadValue',
+ callArgs,
+ callback
+ );
if (native.isFailure(result)) {
throw native.getErrorObject(result);
@@ -1958,20 +2077,23 @@ var BluetoothGATTCharacteristic = function(data, address) {
this.writeValue = function(value, successCallback, errorCallback) {
privUtils_.log('Entered BluetoothGATTCharacteristic.writeValue()');
- var args = AV.validateArgs([successCallback, errorCallback], [
- {
- name: 'successCallback',
- type: AV.Types.FUNCTION,
- optional: true,
- nullable: true
- },
- {
- name: 'errorCallback',
- type: AV.Types.FUNCTION,
- optional: true,
- nullable: true
- }
- ]);
+ var args = AV.validateArgs(
+ [successCallback, errorCallback],
+ [
+ {
+ name: 'successCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ }
+ ]
+ );
var callback = function(result) {
if (native.isFailure(result)) {
@@ -1987,7 +2109,11 @@ var BluetoothGATTCharacteristic = function(data, address) {
address: address_
};
- var result = native.call('BluetoothGATTClientServiceWriteValue', callArgs, callback);
+ var result = native.call(
+ 'BluetoothGATTClientServiceWriteValue',
+ callArgs,
+ callback
+ );
if (native.isFailure(result)) {
throw native.getErrorObject(result);
@@ -2233,10 +2359,14 @@ var BluetoothGATTServerCharacteristic = function(data) {
);
};
- this.removeValueChangeListener = function() { /* Intended no operation */ };
+ this.removeValueChangeListener = function() {
+ /* Intended no operation */
+ };
};
-BluetoothGATTServerCharacteristic.prototype = Object.create(BluetoothGATTCharacteristic.prototype);
+BluetoothGATTServerCharacteristic.prototype = Object.create(
+ BluetoothGATTCharacteristic.prototype
+);
Object.defineProperty(BluetoothGATTServerCharacteristic.prototype, 'constructor', {
value: BluetoothGATTServerCharacteristic,
@@ -2399,7 +2529,11 @@ var BluetoothGATTDescriptor = function(data, address) {
var callArgs = { handle: handle_, address: address_ };
- var result = native.call('BluetoothGATTClientServiceReadValue', callArgs, callback);
+ var result = native.call(
+ 'BluetoothGATTClientServiceReadValue',
+ callArgs,
+ callback
+ );
if (native.isFailure(result)) {
throw native.getErrorObject(result);
@@ -2408,20 +2542,23 @@ var BluetoothGATTDescriptor = function(data, address) {
this.writeValue = function(value, successCallback, errorCallback) {
privUtils_.log('Entered BluetoothGATTDescriptor.writeValue()');
- var args = AV.validateArgs([successCallback, errorCallback], [
- {
- name: 'successCallback',
- type: AV.Types.FUNCTION,
- optional: true,
- nullable: true
- },
- {
- name: 'errorCallback',
- type: AV.Types.FUNCTION,
- optional: true,
- nullable: true
- }
- ]);
+ var args = AV.validateArgs(
+ [successCallback, errorCallback],
+ [
+ {
+ name: 'successCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ },
+ {
+ name: 'errorCallback',
+ type: AV.Types.FUNCTION,
+ optional: true,
+ nullable: true
+ }
+ ]
+ );
var callback = function(result) {
if (native.isFailure(result)) {
@@ -2437,7 +2574,11 @@ var BluetoothGATTDescriptor = function(data, address) {
address: address_
};
- var result = native.call('BluetoothGATTClientServiceWriteValue', callArgs, callback);
+ var result = native.call(
+ 'BluetoothGATTClientServiceWriteValue',
+ callArgs,
+ callback
+ );
if (native.isFailure(result)) {
throw native.getErrorObject(result);
@@ -2583,7 +2724,9 @@ var BluetoothGATTServerDescriptor = function(data, address) {
};
};
-BluetoothGATTServerDescriptor.prototype = Object.create(BluetoothGATTDescriptor.prototype);
+BluetoothGATTServerDescriptor.prototype = Object.create(
+ BluetoothGATTDescriptor.prototype
+);
Object.defineProperty(BluetoothGATTServerDescriptor.prototype, 'constructor', {
value: BluetoothGATTServerDescriptor,
@@ -3320,31 +3463,39 @@ var ResultCallbacksAggregator = function(callbacksNum, onAllSucceeded, onFailure
var _allSucceeded = true;
var _error;
- this.successCallback = function (){
- _callbacksNum--;
+ this.successCallback = function() {
+ _callbacksNum--;
- if (!_callbacksNum) {
- if (_allSucceeded) {
- onAllSucceeded();
- } else {
- onFailure(_error);
+ if (!_callbacksNum) {
+ if (_allSucceeded) {
+ onAllSucceeded();
+ } else {
+ onFailure(_error);
+ }
}
- }
};
this.errorCallback = function(error) {
- _callbacksNum--;
- _allSucceeded = false;
- _error = error;
+ _callbacksNum--;
+ _allSucceeded = false;
+ _error = error;
- if (!_callbacksNum) {
- onFailure(_error);
- }
+ if (!_callbacksNum) {
+ onFailure(_error);
+ }
};
};
-var BluetoothGATTServer_valid_start_errors = ['InvalidStateError', 'NotSupportedError', 'AbortError'];
-var BluetoothGATTServer_valid_start_exceptions = ['InvalidStateError', 'TypeMismatchError', 'SecurityError'];
+var BluetoothGATTServer_valid_start_errors = [
+ 'InvalidStateError',
+ 'NotSupportedError',
+ 'AbortError'
+];
+var BluetoothGATTServer_valid_start_exceptions = [
+ 'InvalidStateError',
+ 'TypeMismatchError',
+ 'SecurityError'
+];
BluetoothGATTServer.prototype.start = function() {
privUtils_.log('Entered BluetoothGATTServer.start()');
@@ -3374,61 +3525,100 @@ BluetoothGATTServer.prototype.start = function() {
var startServerCallback = function(result) {
if (native.isFailure(result)) {
- native.callIfPossible(args.errorCallback,
- native.getErrorObjectAndValidate(result,
- BluetoothGATTServer_valid_start_errors, AbortError));
+ native.callIfPossible(
+ args.errorCallback,
+ native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_start_errors,
+ AbortError
+ )
+ );
} else {
native.callIfPossible(args.successCallback);
}
};
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
+ 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);
+ throw native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_start_exceptions,
+ AbortError
+ );
}
}
-}
+};
-var BluetoothGATTServer_valid_stop_errors = ['InvalidStateError', 'NotSupportedError', 'AbortError'];
-var BluetoothGATTServer_valid_stop_exceptions = ['InvalidStateError', 'TypeMismatchError', 'SecurityError'];
+var BluetoothGATTServer_valid_stop_errors = [
+ 'InvalidStateError',
+ 'NotSupportedError',
+ 'AbortError'
+];
+var BluetoothGATTServer_valid_stop_exceptions = [
+ 'InvalidStateError',
+ 'TypeMismatchError',
+ 'SecurityError'
+];
BluetoothGATTServer.prototype.stop = function() {
privUtils_.log('Entered BluetoothGATTServer.stop()');
@@ -3449,9 +3639,14 @@ BluetoothGATTServer.prototype.stop = function() {
var callback = function(result) {
if (native.isFailure(result)) {
- native.callIfPossible(args.errorCallback,
- native.getErrorObjectAndValidate(result,
- BluetoothGATTServer_valid_stop_errors, AbortError));
+ native.callIfPossible(
+ args.errorCallback,
+ native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_stop_errors,
+ AbortError
+ )
+ );
} else {
_BluetoothGATTServerServicesRegisteredInNativeLayer = {};
native.callIfPossible(args.successCallback);
@@ -3460,9 +3655,13 @@ BluetoothGATTServer.prototype.stop = function() {
var result = native.call('BluetoothGATTServerStop', {}, callback);
if (native.isFailure(result)) {
- throw native.getErrorObjectAndValidate(result, BluetoothGATTServer_valid_stop_exceptions, AbortError);
+ throw native.getErrorObjectAndValidate(
+ result,
+ BluetoothGATTServer_valid_stop_exceptions,
+ AbortError
+ );
}
-}
+};
var BluetoothGATTServer_valid_getConnectionMtu_errors = ['InvalidStateError', 'NotSupportedError', 'UnknownError'];
var BluetoothGATTServer_valid_getConnectionMtu_exceptions = ['TypeMismatchError', 'SecurityError'];
@@ -3566,36 +3765,46 @@ var BluetoothManager_checkAndNormalizeHexString = function(hexString) {
if (hexString.startsWith('0x')) {
hexString = hexString.substring(2);
}
- if (!(/^[0-9a-f]+$/.test(hexString))) {
- throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'Given string is not hexadecimal value');
+ if (!/^[0-9a-f]+$/.test(hexString)) {
+ throw new WebAPIException(
+ WebAPIException.TYPE_MISMATCH_ERR,
+ 'Given string is not hexadecimal value'
+ );
}
if ('0' === hexString) {
- return '00';
+ return '00';
}
- if (1 === hexString.length%2) {
+ if (1 === hexString.length % 2) {
// to save consistency with BluetoothLEManufacturerData, last character is omitted
- hexString = hexString.replace(/.$/,'');
+ hexString = hexString.replace(/.$/, '');
}
return hexString;
-}
+};
var BluetoothManager_HexStringToUint8Array = function(hexString) {
hexString = BluetoothManager_checkAndNormalizeHexString(hexString);
if (0 === hexString.length) {
return new Uint8Array([]);
}
- var data = hexString.match(/[0-9a-f]{2}/g).map(function(byte) {return parseInt(byte, 16)});
+ var data = hexString.match(/[0-9a-f]{2}/g).map(function(byte) {
+ return parseInt(byte, 16);
+ });
return new Uint8Array(data);
-}
+};
var BluetoothManager_byteArrayToHexString = function(bytes) {
if (0 == bytes.length) {
return '';
}
- return '0x' + Array.prototype.map.call(bytes, function(byte) {
- return ('0' + (byte & 0xFF).toString(16)).slice(-2);
- }).join('');
-}
+ return (
+ '0x' +
+ Array.prototype.map
+ .call(bytes, function(byte) {
+ return ('0' + (byte & 0xff).toString(16)).slice(-2);
+ })
+ .join('')
+ );
+};
var BluetoothManager_toByteArray = function(data) {
if (data && String === data.constructor) {
@@ -3603,9 +3812,11 @@ var BluetoothManager_toByteArray = function(data) {
} else {
try {
data = numberArrayToByteArray(data);
- }
- catch(err) {
- throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'argument is not a valid Bytes type');
+ } catch (err) {
+ throw new WebAPIException(
+ WebAPIException.TYPE_MISMATCH_ERR,
+ 'argument is not a valid Bytes type'
+ );
}
}
return data;
@@ -3638,10 +3849,12 @@ var BluetoothManager_toUint8Array = function(data) {
return BluetoothManager_HexStringToUint8Array(data);
} else {
try {
- data = new Uint8Array(numberArrayToByteArray(data));
- }
- catch(err) {
- throw new WebAPIException(WebAPIException.TYPE_MISMATCH_ERR, 'argument is not a valid Bytes type');
+ data = new Uint8Array(numberArrayToByteArray(data));
+ } catch (err) {
+ throw new WebAPIException(
+ WebAPIException.TYPE_MISMATCH_ERR,
+ 'argument is not a valid Bytes type'
+ );
}
}
return data;
diff --git a/src/bluetooth/bluetooth_gatt_server.cc b/src/bluetooth/bluetooth_gatt_server.cc
index 0d131a08..d33c2755 100644
--- a/src/bluetooth/bluetooth_gatt_server.cc
+++ b/src/bluetooth/bluetooth_gatt_server.cc
@@ -178,6 +178,19 @@ void BluetoothGATTServer::RegisterService(const picojson::value& args, picojson:
ReportSuccess(out);
}
+void BluetoothGATTServer::UnregisterService(const picojson::value& args, picojson::object& out) {
+ ScopeLogger();
+
+ auto result = service_.UnregisterService(args, handle_);
+
+ if (result.IsError()) {
+ ReportError(result, &out);
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
bool BluetoothGATTServer::IsRunning() {
return running_;
}
diff --git a/src/bluetooth/bluetooth_gatt_server.h b/src/bluetooth/bluetooth_gatt_server.h
index 82185f4f..525d921b 100644
--- a/src/bluetooth/bluetooth_gatt_server.h
+++ b/src/bluetooth/bluetooth_gatt_server.h
@@ -39,6 +39,7 @@ class BluetoothGATTServer {
void Stop(picojson::object& out);
void GetConnectionMtu(const picojson::value& args, picojson::object& out);
void RegisterService(const picojson::value& args, picojson::object& out);
+ void UnregisterService(const picojson::value& args, picojson::object& out);
bool IsRunning();
static bool DestroyService(int total, int index, bt_gatt_h handle, void* user_data);
diff --git a/src/bluetooth/bluetooth_gatt_server_service.cc b/src/bluetooth/bluetooth_gatt_server_service.cc
index dcf0e6d4..85688215 100644
--- a/src/bluetooth/bluetooth_gatt_server_service.cc
+++ b/src/bluetooth/bluetooth_gatt_server_service.cc
@@ -56,6 +56,7 @@ const std::string kEncryptedSignedReadPermission = "encryptedSignedReadPermissio
const std::string kEncryptedSignedWritePermission = "encryptedSignedWritePermission";
const std::string kId = "_id";
+const std::string kIdsToRemoveFromNativeLayer = "idsToRemoveFromNativeLayer";
int GetPermissionsInt(const picojson::value& permissions) {
ScopeLogger("permissions: %s", permissions.serialize().c_str());
@@ -119,7 +120,8 @@ int GetPropertiesInt(const picojson::value& properties) {
} // namespace
-bool BluetoothGATTServerService::DestroyService(int total, int index, bt_gatt_h handle, void* user_data) {
+bool BluetoothGATTServerService::DestroyService(int total, int index, bt_gatt_h handle,
+ void* user_data) {
ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
/*
@@ -138,7 +140,7 @@ bool BluetoothGATTServerService::DestroyService(int total, int index, bt_gatt_h
}
bool BluetoothGATTServerService::DestroyCharacteristic(int total, int index, bt_gatt_h handle,
- void* user_data) {
+ void* user_data) {
ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
auto ret = bt_gatt_characteristic_destroy(handle);
@@ -151,7 +153,7 @@ bool BluetoothGATTServerService::DestroyCharacteristic(int total, int index, bt_
}
bool BluetoothGATTServerService::DestroyDescriptor(int total, int index, bt_gatt_h handle,
- void* user_data) {
+ void* user_data) {
ScopeLogger("total: %d, index: %d, handle: %p", total, index, handle);
auto ret = bt_gatt_descriptor_destroy(handle);
@@ -381,8 +383,8 @@ common::PlatformResult BluetoothGATTServerService::RegisterService(
return common::PlatformResult();
}
-
-common::PlatformResult BluetoothGATTServerService::UnregisterService(const picojson::value& args, bt_gatt_server_h server) {
+common::PlatformResult BluetoothGATTServerService::UnregisterService(const picojson::value& args,
+ bt_gatt_server_h server) {
ScopeLogger();
auto _id = static_cast(args.get(kId).get());
@@ -390,6 +392,13 @@ common::PlatformResult BluetoothGATTServerService::UnregisterService(const picoj
auto service_handle = gatt_objects_[_id];
+ /*
+ * Undocumented behavior of native Bluetooth API:
+ * bt_gatt_server_unregister_service() not only unregisters the service,
+ * but also calls bt_gatt_destroy_service() on its handle, destroying
+ * the corresponding service object and all its components (included services,
+ * characteristics, descriptors).
+ */
auto ret = bt_gatt_server_unregister_service(server, service_handle);
if (BT_ERROR_NONE != ret) {
LoggerE("bt_gatt_server_unregister_service() failed: %d (%s)", ret, get_error_message(ret));
@@ -398,8 +407,15 @@ common::PlatformResult BluetoothGATTServerService::UnregisterService(const picoj
LoggerD("bt_gatt_server_unregister_service(): SUCCESS");
gatt_objects_.erase(_id);
- return common::PlatformResult{};
+ auto ids_to_remove = args.get(kIdsToRemoveFromNativeLayer).get();
+ for (const auto& to_remove : ids_to_remove) {
+ int id_to_remove = static_cast(to_remove.get());
+ LoggerD("Erasing gatt object with _id: %d", id_to_remove);
+ gatt_objects_.erase(id_to_remove);
+ }
+
+ return common::PlatformResult{};
}
} // namespace bluetooth
diff --git a/src/bluetooth/bluetooth_instance.cc b/src/bluetooth/bluetooth_instance.cc
index a7575ea7..70a70b72 100644
--- a/src/bluetooth/bluetooth_instance.cc
+++ b/src/bluetooth/bluetooth_instance.cc
@@ -105,6 +105,7 @@ BluetoothInstance::BluetoothInstance()
REGISTER_METHOD(BluetoothGATTServerStop);
REGISTER_METHOD(BluetoothGATTServerGetConnectionMtu);
REGISTER_METHOD(BluetoothGATTServerRegisterService);
+ REGISTER_METHOD(BluetoothGATTServerUnregisterService);
#undef REGISTER_METHOD
}
@@ -410,37 +411,37 @@ void BluetoothInstance::BluetoothLEDeviceGetServiceAllUuids(const picojson::valu
}
void BluetoothInstance::BluetoothGATTClientServiceGetServices(const picojson::value& args,
- picojson::object& out) {
+ picojson::object& out) {
ScopeLogger();
bluetooth_gatt_client_service_.GetServices(args, out);
}
void BluetoothInstance::BluetoothGATTClientServiceGetCharacteristics(const picojson::value& args,
- picojson::object& out) {
+ picojson::object& out) {
ScopeLogger();
bluetooth_gatt_client_service_.GetCharacteristics(args, out);
}
void BluetoothInstance::BluetoothGATTClientServiceReadValue(const picojson::value& args,
- picojson::object& out) {
+ picojson::object& out) {
ScopeLogger();
bluetooth_gatt_client_service_.ReadValue(args, out);
}
void BluetoothInstance::BluetoothGATTClientServiceWriteValue(const picojson::value& args,
- picojson::object& out) {
+ picojson::object& out) {
ScopeLogger();
bluetooth_gatt_client_service_.WriteValue(args, out);
}
-void BluetoothInstance::BluetoothGATTClientServiceAddValueChangeListener(const picojson::value& args,
- picojson::object& out) {
+void BluetoothInstance::BluetoothGATTClientServiceAddValueChangeListener(
+ const picojson::value& args, picojson::object& out) {
ScopeLogger();
bluetooth_gatt_client_service_.AddValueChangeListener(args, out);
}
-void BluetoothInstance::BluetoothGATTClientServiceRemoveValueChangeListener(const picojson::value& args,
- picojson::object& out) {
+void BluetoothInstance::BluetoothGATTClientServiceRemoveValueChangeListener(
+ const picojson::value& args, picojson::object& out) {
ScopeLogger();
bluetooth_gatt_client_service_.RemoveValueChangeListener(args, out);
}
@@ -520,5 +521,23 @@ void BluetoothInstance::BluetoothGATTServerRegisterService(const picojson::value
ReportSuccess(out);
}
+void BluetoothInstance::BluetoothGATTServerUnregisterService(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ CHECK_PRIVILEGE_ACCESS(kPrivilegeBluetooth, &out);
+
+ worker.add_job([this, args] {
+ ScopeLogger("Async call: BluetoothGATTServerUnregisterService");
+ picojson::value response = picojson::value(picojson::object());
+ picojson::object& async_out = response.get();
+ double callback_id = args.get("callbackId").get();
+ async_out["callbackId"] = picojson::value(callback_id);
+ this->bluetooth_gatt_server_.UnregisterService(args, async_out);
+ this->PostMessage(response.serialize().c_str());
+ });
+
+ ReportSuccess(out);
+}
+
} // namespace bluetooth
} // namespace extension
diff --git a/src/bluetooth/bluetooth_instance.h b/src/bluetooth/bluetooth_instance.h
index ed122272..e3e31c20 100644
--- a/src/bluetooth/bluetooth_instance.h
+++ b/src/bluetooth/bluetooth_instance.h
@@ -21,8 +21,8 @@
#include "bluetooth/bluetooth_adapter.h"
#include "bluetooth/bluetooth_device.h"
-#include "bluetooth/bluetooth_gatt_server.h"
#include "bluetooth/bluetooth_gatt_client_service.h"
+#include "bluetooth/bluetooth_gatt_server.h"
#include "bluetooth/bluetooth_gatt_server_service.h"
#include "bluetooth/bluetooth_health_application.h"
#include "bluetooth/bluetooth_health_channel.h"
@@ -102,17 +102,19 @@ class BluetoothInstance : public common::ParsedInstance {
void BluetoothLEDeviceGetServiceAllUuids(const picojson::value& args, picojson::object& out);
void BluetoothGATTClientServiceGetServices(const picojson::value& args, picojson::object& out);
- void BluetoothGATTClientServiceGetCharacteristics(const picojson::value& args, picojson::object& out);
+ void BluetoothGATTClientServiceGetCharacteristics(const picojson::value& args,
+ picojson::object& out);
void BluetoothGATTClientServiceReadValue(const picojson::value& args, picojson::object& out);
void BluetoothGATTClientServiceWriteValue(const picojson::value& args, picojson::object& out);
void BluetoothGATTClientServiceAddValueChangeListener(const picojson::value& args,
- picojson::object& out);
+ picojson::object& out);
void BluetoothGATTClientServiceRemoveValueChangeListener(const picojson::value& args,
- picojson::object& out);
+ picojson::object& out);
void BluetoothGATTServerStart(const picojson::value& args, picojson::object& out);
void BluetoothGATTServerStop(const picojson::value& args, picojson::object& out);
void BluetoothGATTServerGetConnectionMtu(const picojson::value& args, picojson::object& out);
void BluetoothGATTServerRegisterService(const picojson::value& args, picojson::object& out);
+ void BluetoothGATTServerUnregisterService(const picojson::value& args, picojson::object& out);
BluetoothAdapter bluetooth_adapter_;
BluetoothDevice bluetooth_device_;