diff --git a/dom/bluetooth/BluetoothCommon.h b/dom/bluetooth/BluetoothCommon.h index 90be37e586e..acd6cc0e7d8 100644 --- a/dom/bluetooth/BluetoothCommon.h +++ b/dom/bluetooth/BluetoothCommon.h @@ -694,6 +694,27 @@ enum BluetoothGattCharPropBit { typedef uint8_t BluetoothGattCharProp; #define BLUETOOTH_EMPTY_GATT_CHAR_PROP static_cast(0x00) +/* + * Bluetooth GATT Attribute Permissions bit field + */ +enum BluetoothGattAttrPermBit { + GATT_ATTR_PERM_BIT_READ = (1 << 0), + GATT_ATTR_PERM_BIT_READ_ENCRYPTED = (1 << 1), + GATT_ATTR_PERM_BIT_READ_ENCRYPTED_MITM = (1 << 2), + GATT_ATTR_PERM_BIT_WRITE = (1 << 4), + GATT_ATTR_PERM_BIT_WRITE_ENCRYPTED = (1 << 5), + GATT_ATTR_PERM_BIT_WRITE_ENCRYPTED_MITM = (1 << 6), + GATT_ATTR_PERM_BIT_WRITE_SIGNED = (1 << 7), + GATT_ATTR_PERM_BIT_WRITE_SIGNED_MITM = (1 << 8) +}; + +/* + * BluetoothGattAttrPerm is used to store a bit mask value which contains + * each corresponding bit value of each BluetoothGattAttrPermBit. + */ +typedef int32_t BluetoothGattAttrPerm; +#define BLUETOOTH_EMPTY_GATT_ATTR_PERM static_cast(0x00) + struct BluetoothGattAdvData { uint8_t mAdvData[62]; }; @@ -767,6 +788,14 @@ struct BluetoothGattTestParam { uint16_t mU5; }; +struct BluetoothGattResponse { + uint16_t mHandle; + uint16_t mOffset; + uint16_t mLength; + BluetoothGattAuthReq mAuthReq; + uint8_t mValue[BLUETOOTH_GATT_MAX_ATTR_LEN]; +}; + /** * EIR Data Type, Advertising Data Type (AD Type) and OOB Data Type Definitions * Please refer to https://www.bluetooth.org/en-us/specification/\ diff --git a/dom/bluetooth/BluetoothInterface.h b/dom/bluetooth/BluetoothInterface.h index 9b0abbd2316..2e32b939e9c 100644 --- a/dom/bluetooth/BluetoothInterface.h +++ b/dom/bluetooth/BluetoothInterface.h @@ -611,12 +611,120 @@ protected: class BluetoothGattServerNotificationHandler { public: - virtual ~BluetoothGattServerNotificationHandler(); - // TODO: Add server notifications + virtual void + RegisterServerNotification(BluetoothGattStatus aStatus, + int aServerIf, + const BluetoothUuid& aAppUuid) + { } + + virtual void + ConnectionNotification(int aConnId, + int aServerIf, + bool aConnected, + const nsAString& aBdAddr) + { } + + virtual void + ServiceAddedNotification(BluetoothGattStatus aStatus, + int aServerIf, + const BluetoothGattServiceId& aServiceId, + int aServiceHandle) + { } + + virtual void + IncludedServiceAddedNotification(BluetoothGattStatus aStatus, + int aServerIf, + int aServiceHandle, + int aIncludedServiceHandle) + { } + + virtual void + CharacteristicAddedNotification(BluetoothGattStatus aStatus, + int aServerIf, + const BluetoothUuid& aCharId, + int aServiceHandle, + int aCharacteristicHandle) + { } + + virtual void + DescriptorAddedNotification(BluetoothGattStatus aStatus, + int aServerIf, + const BluetoothUuid& aCharId, + int aServiceHandle, + int aDescriptorHandle) + { } + + virtual void + ServiceStartedNotification(BluetoothGattStatus aStatus, + int aServerIf, + int aServiceHandle) + { } + + virtual void + ServiceStoppedNotification(BluetoothGattStatus aStatus, + int aServerIf, + int aServiceHandle) + { } + + virtual void + ServiceDeletedNotification(BluetoothGattStatus aStatus, + int aServerIf, + int aServiceHandle) + { } + + virtual void + RequestReadNotification(int aConnId, + int aTransId, + const nsAString& aBdAddr, + int aAttributeHandle, + int aOffset, + bool aIsLong) + { } + + virtual void + RequestWriteNotification(int aConnId, + int aTransId, + const nsAString& aBdAddr, + int aAttributeHandle, + int aOffset, + const nsTArray& aValue, + bool aNeedResponse, + bool aIsPrepareWrite) + { } + + virtual void + RequestExecuteWriteNotification(int aConnId, + int aTransId, + const nsAString& aBdAddr, + bool aExecute) /* true: execute */ + /* false: cancel */ + { } + + virtual void + ResponseConfirmationNotification(BluetoothGattStatus aStatus, + int aHandle) + { } + + virtual void + IndicationSentNotification(int aConnId, + BluetoothGattStatus aStatus) + { } + + virtual void + CongestionNotification(int aConnId, + bool aCongested) + { } + + virtual void + MtuChangedNotification(int aConnId, + int aMtu) + { } protected: BluetoothGattServerNotificationHandler() { } + + virtual ~BluetoothGattServerNotificationHandler(); }; class BluetoothGattNotificationHandler @@ -688,7 +796,38 @@ protected: virtual ~BluetoothGattClientResultHandler() { } }; -// TODO: Add GattServerResultHandler +class BluetoothGattServerResultHandler +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothGattServerResultHandler) + + virtual void OnError(BluetoothStatus aStatus) + { + BT_WARNING("Received error code %d", (int)aStatus); + } + + virtual void RegisterServer() { } + virtual void UnregisterServer() { } + + virtual void ConnectPeripheral() { } + virtual void DisconnectPeripheral() { } + + virtual void AddService() { } + virtual void AddIncludedService() { } + virtual void AddCharacteristic() { } + virtual void AddDescriptor() { } + + virtual void StartService() { } + virtual void StopService() { } + virtual void DeleteService() { } + + virtual void SendIndication() { } + + virtual void SendResponse() { } + +protected: + virtual ~BluetoothGattServerResultHandler() { } +}; class BluetoothGattClientInterface { @@ -827,7 +966,79 @@ protected: virtual ~BluetoothGattClientInterface(); }; -// TODO: Add GattServerInterface +class BluetoothGattServerInterface +{ +public: + /* Register / Unregister */ + virtual void RegisterServer(const BluetoothUuid& aUuid, + BluetoothGattServerResultHandler* aRes) = 0; + virtual void UnregisterServer(int aServerIf, + BluetoothGattServerResultHandler* aRes) = 0; + + /* Connect / Disconnect */ + virtual void ConnectPeripheral(int aServerIf, + const nsAString& aBdAddr, + bool aIsDirect, /* auto connect */ + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes) = 0; + virtual void DisconnectPeripheral(int aServerIf, + const nsAString& aBdAddr, + int aConnId, + BluetoothGattServerResultHandler* aRes) = 0; + + /* Add a services / a characteristic / a descriptor */ + virtual void AddService(int aServerIf, + const BluetoothGattServiceId& aServiceId, + int aNumHandles, + BluetoothGattServerResultHandler* aRes) = 0; + virtual void AddIncludedService(int aServerIf, + int aServiceHandle, + int aIncludedServiceHandle, + BluetoothGattServerResultHandler* aRes) = 0; + virtual void AddCharacteristic(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattCharProp aProperties, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes) = 0; + virtual void AddDescriptor(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes) = 0; + + /* Start / Stop / Delete a service */ + virtual void StartService(int aServerIf, + int aServiceHandle, + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes) = 0; + virtual void StopService(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes) = 0; + virtual void DeleteService(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes) = 0; + + /* Send an indication or a notification */ + virtual void SendIndication(int aServerIf, + int aAttributeHandle, + int aConnId, + const nsTArray& aValue, + bool aConfirm, /* true: indication */ + /* false: notification */ + BluetoothGattServerResultHandler* aRes) = 0; + + /* Send a response for an incoming indication */ + virtual void SendResponse(int aConnId, + int aTransId, + BluetoothGattStatus aStatus, + const BluetoothGattResponse& aResponse, + BluetoothGattServerResultHandler* aRes) = 0; + +protected: + BluetoothGattServerInterface(); + virtual ~BluetoothGattServerInterface(); +}; class BluetoothGattInterface { diff --git a/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp index 78a41887f6b..806bbc019c3 100644 --- a/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothGattHALInterface.cpp @@ -23,6 +23,15 @@ typedef BluetoothStatus, BluetoothStatus> BluetoothGattClientHALErrorRunnable; +typedef + BluetoothHALInterfaceRunnable0 + BluetoothGattServerHALResultRunnable; + +typedef + BluetoothHALInterfaceRunnable1 + BluetoothGattServerHALErrorRunnable; + typedef BluetoothHALInterfaceRunnable0 BluetoothGattHALResultRunnable; @@ -84,6 +93,29 @@ DispatchBluetoothGattClientHALResult( return rv; } +static nsresult +DispatchBluetoothGattServerHALResult( + BluetoothGattServerResultHandler* aRes, + void (BluetoothGattServerResultHandler::*aMethod)(), + BluetoothStatus aStatus) +{ + MOZ_ASSERT(aRes); + + nsRunnable* runnable; + + if (aStatus == STATUS_SUCCESS) { + runnable = new BluetoothGattServerHALResultRunnable(aRes, aMethod); + } else { + runnable = new BluetoothGattServerHALErrorRunnable(aRes, + &BluetoothGattServerResultHandler::OnError, aStatus); + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + return rv; +} + static nsresult DispatchBluetoothGattHALResult( BluetoothGattResultHandler* aRes, @@ -416,73 +448,244 @@ struct BluetoothGattServerCallback }; // Notifications - // TODO: Add Server Notifications + typedef BluetoothNotificationHALRunnable3< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothUuid, + BluetoothGattStatus, int, const BluetoothUuid&> + RegisterServerNotification; + + typedef BluetoothNotificationHALRunnable4< + GattServerNotificationHandlerWrapper, void, + int, int, bool, nsString, + int, int, bool, const nsAString&> + ConnectionNotification; + + typedef BluetoothNotificationHALRunnable4< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothGattServiceId, int, + BluetoothGattStatus, int, const BluetoothGattServiceId&, int> + ServiceAddedNotification; + + typedef BluetoothNotificationHALRunnable4< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int, int> + IncludedServiceAddedNotification; + + typedef BluetoothNotificationHALRunnable5< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothUuid, int, int, + BluetoothGattStatus, int, const BluetoothUuid&, int, int> + CharacteristicAddedNotification; + + typedef BluetoothNotificationHALRunnable5< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, BluetoothUuid, int, int, + BluetoothGattStatus, int, const BluetoothUuid&, int, int> + DescriptorAddedNotification; + + typedef BluetoothNotificationHALRunnable3< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int> + ServiceStartedNotification; + + typedef BluetoothNotificationHALRunnable3< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int> + ServiceStoppedNotification; + + typedef BluetoothNotificationHALRunnable3< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int, int> + ServiceDeletedNotification; + + typedef BluetoothNotificationHALRunnable6< + GattServerNotificationHandlerWrapper, void, + int, int, nsString, int, int, bool, + int, int, const nsAString&, int, int, bool> + RequestReadNotification; + + typedef BluetoothNotificationHALRunnable8< + GattServerNotificationHandlerWrapper, void, + int, int, nsString, int, int, nsTArray, bool, bool, + int, int, const nsAString&, int, int, const nsTArray&, bool, bool> + RequestWriteNotification; + + typedef BluetoothNotificationHALRunnable4< + GattServerNotificationHandlerWrapper, void, + int, int, nsString, bool, + int, int, const nsAString&, bool> + RequestExecuteWriteNotification; + + typedef BluetoothNotificationHALRunnable2< + GattServerNotificationHandlerWrapper, void, + BluetoothGattStatus, int> + ResponseConfirmationNotification; + +#if ANDROID_VERSION >= 21 + typedef BluetoothNotificationHALRunnable2< + GattServerNotificationHandlerWrapper, void, + int, BluetoothGattStatus> + IndicationSentNotification; + + typedef BluetoothNotificationHALRunnable2< + GattServerNotificationHandlerWrapper, void, + int, bool> + CongestionNotification; +#endif // ANDROID_VERSION >= 21 + +#if ANDROID_VERSION >=22 + typedef BluetoothNotificationHALRunnable2< + GattServerNotificationHandlerWrapper, void, + int, int> + MtuChangedNotification; +#endif // ANDROID_VERSION >=22 // GATT Server callbacks - // TODO: Implement server callbacks - #if ANDROID_VERSION >= 19 static void RegisterServer(int aStatus, int aServerIf, bt_uuid_t* aAppUuid) - { } + { + RegisterServerNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RegisterServerNotification, + aStatus, aServerIf, *aAppUuid); + } static void Connection(int aConnId, int aServerIf, int aIsConnected, bt_bdaddr_t* aBdAddr) - { } + { + ConnectionNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ConnectionNotification, + aConnId, aServerIf, aIsConnected != 0, aBdAddr); + } static void ServiceAdded(int aStatus, int aServerIf, btgatt_srvc_id_t* aServiceId, int aServiceHandle) - { } + { + ServiceAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceAddedNotification, + aStatus, aServerIf, *aServiceId, aServiceHandle); + } static void IncludedServiceAdded(int aStatus, int aServerIf, int aServiceHandle, int aIncludedServiceHandle) - { } + { + IncludedServiceAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::IncludedServiceAddedNotification, + aStatus, aServerIf, aServiceHandle, aIncludedServiceHandle); + } static void CharacteristicAdded(int aStatus, int aServerIf, bt_uuid_t* aUuid, int aServiceHandle, int aCharHandle) - { } + { + CharacteristicAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::CharacteristicAddedNotification, + aStatus, aServerIf, *aUuid, aServiceHandle, aCharHandle); + } static void DescriptorAdded(int aStatus, int aServerIf, bt_uuid_t* aUuid, int aServiceHandle, int aDescriptorHandle) - { } + { + DescriptorAddedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::DescriptorAddedNotification, + aStatus, aServerIf, *aUuid, aServiceHandle, aDescriptorHandle); + } static void ServiceStarted(int aStatus, int aServerIf, int aServiceHandle) - { } + { + ServiceStartedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceStartedNotification, + aStatus, aServerIf, aServiceHandle); + } static void ServiceStopped(int aStatus, int aServerIf, int aServiceHandle) - { } + { + ServiceStoppedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceStoppedNotification, + aStatus, aServerIf, aServiceHandle); + } static void ServiceDeleted(int aStatus, int aServerIf, int aServiceHandle) - { } + { + ServiceDeletedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ServiceDeletedNotification, + aStatus, aServerIf, aServiceHandle); + } static void RequestRead(int aConnId, int aTransId, bt_bdaddr_t* aBdAddr, int aAttrHandle, int aOffset, bool aIsLong) - { } + { + RequestReadNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RequestReadNotification, + aConnId, aTransId, *aBdAddr, aAttrHandle, aOffset, aIsLong); + } static void RequestWrite(int aConnId, int aTransId, bt_bdaddr_t* aBdAddr, int aAttrHandle, int aOffset, int aLength, bool aNeedRsp, bool aIsPrep, uint8_t* aValue) - { } + { + nsTArray value; + value.AppendElements(aValue, aLength); + RequestWriteNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RequestWriteNotification, + aConnId, aTransId, *aBdAddr, aAttrHandle, aOffset, value, aNeedRsp, + aIsPrep); + } static void - RequestExecWrite(int aConnId, int aTransId, bt_bdaddr_t* aBdAddr, - int aExecWrite) - { } + RequestExecuteWrite(int aConnId, int aTransId, bt_bdaddr_t* aBdAddr, + int aExecWrite) + { + RequestExecuteWriteNotification::Dispatch( + &BluetoothGattServerNotificationHandler::RequestExecuteWriteNotification, + aConnId, aTransId, *aBdAddr, aExecWrite != 0); + } static void ResponseConfirmation(int aStatus, int aHandle) - { } + { + ResponseConfirmationNotification::Dispatch( + &BluetoothGattServerNotificationHandler::ResponseConfirmationNotification, + aStatus, aHandle); + } #endif // ANDROID_VERSION >= 19 + +#if ANDROID_VERSION >= 21 + static void + IndicationSent(int aConnId, int aStatus) + { + IndicationSentNotification::Dispatch( + &BluetoothGattServerNotificationHandler::IndicationSentNotification, + aConnId, aStatus); + } + + static void + Congestion(int aConnId, bool aCongested) + { + CongestionNotification::Dispatch( + &BluetoothGattServerNotificationHandler::CongestionNotification, + aConnId, aCongested); + } +#endif // ANDROID_VERSION >= 21 + +#if ANDROID_VERSION >= 22 + static void + MtuChanged(int aConnId, int aMtu) + { + MtuChangedNotification::Dispatch( + &BluetoothGattServerNotificationHandler::MtuChangedNotification, + aConnId, aMtu); + } +#endif // ANDROID_VERSION >= 22 }; // GATT Client Interface @@ -1119,7 +1322,341 @@ BluetoothGattClientHALInterface::TestCommand( } -// TODO: Add GATT Server Interface +// GATT Server Interface + +BluetoothGattServerHALInterface::BluetoothGattServerHALInterface( +#if ANDROID_VERSION >= 19 + const btgatt_server_interface_t* aInterface +#endif + ) +#if ANDROID_VERSION >= 19 + :mInterface(aInterface) +#endif +{ +#if ANDROID_VERSION >= 19 + MOZ_ASSERT(mInterface); +#endif +} + +BluetoothGattServerHALInterface::~BluetoothGattServerHALInterface() +{ } + +void +BluetoothGattServerHALInterface::RegisterServer( + const BluetoothUuid& aUuid, BluetoothGattServerResultHandler* aRes) +{ + int status; +#if ANDROID_VERSION >= 19 + bt_uuid_t uuid; + if (NS_SUCCEEDED(Convert(aUuid, uuid))) { + status = mInterface->register_server(&uuid); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::RegisterServer, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::UnregisterServer( + int aServerIf, BluetoothGattServerResultHandler* aRes) +{ +#if ANDROID_VERSION >= 19 + int status = mInterface->unregister_server(aServerIf); +#else + int status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::UnregisterServer, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::ConnectPeripheral( + int aServerIf, const nsAString& aBdAddr, bool aIsDirect, /* auto connect */ + BluetoothTransport aTransport, BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + btgatt_transport_t transport; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) && + NS_SUCCEEDED(Convert(aTransport, transport))) { + status = mInterface->connect(aServerIf, &bdAddr, aIsDirect, transport); + } else { + status = BT_STATUS_PARM_INVALID; + } +#elif ANDROID_VERSION >= 19 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->connect(aServerIf, &bdAddr, aIsDirect); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::ConnectPeripheral, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::DisconnectPeripheral( + int aServerIf, const nsAString& aBdAddr, int aConnId, + BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->disconnect(aServerIf, &bdAddr, aConnId); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::DisconnectPeripheral, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::AddService( + int aServerIf, const BluetoothGattServiceId& aServiceId, int aNumHandles, + BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + btgatt_srvc_id_t serviceId; + + if (NS_SUCCEEDED(Convert(aServiceId, serviceId))) { + status = mInterface->add_service(aServerIf, &serviceId, aNumHandles); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::AddService, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::AddIncludedService( + int aServerIf, int aServiceHandle, int aIncludedServiceHandle, + BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + status = mInterface->add_included_service(aServerIf, aServiceHandle, + aIncludedServiceHandle); +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::AddIncludedService, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::AddCharacteristic( + int aServerIf, int aServiceHandle, const BluetoothUuid& aUuid, + BluetoothGattCharProp aProperties, BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + bt_uuid_t uuid; + int properties; + int permissions; + + if (NS_SUCCEEDED(Convert(aUuid, uuid)) && + NS_SUCCEEDED(Convert(aProperties, properties)) && + NS_SUCCEEDED(Convert(aPermissions, permissions))) { + status = mInterface->add_characteristic(aServerIf, aServiceHandle, &uuid, + properties, permissions); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::AddCharacteristic, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::AddDescriptor( + int aServerIf, int aServiceHandle, const BluetoothUuid& aUuid, + BluetoothGattAttrPerm aPermissions, BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + bt_uuid_t uuid; + int permissions; + + if (NS_SUCCEEDED(Convert(aUuid, uuid)) && + NS_SUCCEEDED(Convert(aPermissions, permissions))) { + status = mInterface->add_descriptor(aServerIf, aServiceHandle, &uuid, + permissions); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::AddDescriptor, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::StartService( + int aServerIf, int aServiceHandle, BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + int transport; + + if (NS_SUCCEEDED(Convert(aTransport, transport))) { + status = mInterface->start_service(aServerIf, aServiceHandle, transport); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::StartService, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::StopService( + int aServerIf, int aServiceHandle, BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + status = mInterface->stop_service(aServerIf, aServiceHandle); +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::StopService, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::DeleteService( + int aServerIf, int aServiceHandle, BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + status = mInterface->delete_service(aServerIf, aServiceHandle); +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::DeleteService, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::SendIndication( + int aServerIf, int aAttributeHandle, int aConnId, + const nsTArray& aValue, + bool aConfirm, /* true: indication, false: notification */ + BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + char* value = + reinterpret_cast(const_cast(aValue.Elements())); + status = mInterface->send_indication(aServerIf, aAttributeHandle, aConnId, + aValue.Length(), aConfirm, value); +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::SendIndication, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothGattServerHALInterface::SendResponse( + int aConnId, int aTransId, BluetoothGattStatus aStatus, + const BluetoothGattResponse& aResponse, + BluetoothGattServerResultHandler* aRes) +{ + bt_status_t status; +#if ANDROID_VERSION >= 19 + int response_status; + btgatt_response_t response; + if (NS_SUCCEEDED(Convert(aStatus, response_status)) && + NS_SUCCEEDED(Convert(aResponse, response))) { + status = mInterface->send_response(aConnId, aTransId, response_status, + &response); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothGattServerHALResult( + aRes, &BluetoothGattServerResultHandler::SendResponse, + ConvertDefault(status, STATUS_FAIL)); + } +} // GATT Interface @@ -1179,8 +1716,15 @@ BluetoothGattHALInterface::Init( BluetoothGattServerCallback::ServiceDeleted, BluetoothGattServerCallback::RequestRead, BluetoothGattServerCallback::RequestWrite, - BluetoothGattServerCallback::RequestExecWrite, - BluetoothGattServerCallback::ResponseConfirmation + BluetoothGattServerCallback::RequestExecuteWrite, + BluetoothGattServerCallback::ResponseConfirmation, +#if ANDROID_VERSION >= 21 + BluetoothGattServerCallback::IndicationSent, + BluetoothGattServerCallback::Congestion, +#endif // ANDROID_VERSION >= 21 +#if ANDROID_VERSION >= 22 + BluetoothGattServerCallback::MtuChanged +#endif // ANDROID_VERSION >= 22 }; static const btgatt_callbacks_t sCallbacks = { @@ -1245,4 +1789,25 @@ BluetoothGattHALInterface::GetBluetoothGattClientInterface() return sBluetoothGattClientHALInterface; } +BluetoothGattServerInterface* +BluetoothGattHALInterface::GetBluetoothGattServerInterface() +{ + static BluetoothGattServerHALInterface* sBluetoothGattServerHALInterface; + + if (sBluetoothGattServerHALInterface) { + return sBluetoothGattServerHALInterface; + } + +#if ANDROID_VERSION >= 19 + MOZ_ASSERT(mInterface->server); + sBluetoothGattServerHALInterface = + new BluetoothGattServerHALInterface(mInterface->server); +#else + sBluetoothGattServerHALInterface = + new BluetoothGattServerHALInterface(); +#endif + + return sBluetoothGattServerHALInterface; +} + END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothGattHALInterface.h b/dom/bluetooth/bluedroid/BluetoothGattHALInterface.h index 8da08f2ab0f..2ee0a0a8e98 100644 --- a/dom/bluetooth/bluedroid/BluetoothGattHALInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothGattHALInterface.h @@ -160,7 +160,90 @@ private: #endif }; -// TODO: Add server interface +class BluetoothGattServerHALInterface final + : public BluetoothGattServerInterface +{ +public: + friend class BluetoothGattHALInterface; + + /* Register / Unregister */ + void RegisterServer(const BluetoothUuid& aUuid, + BluetoothGattServerResultHandler* aRes); + void UnregisterServer(int aServerIf, + BluetoothGattServerResultHandler* aRes); + + /* Connect / Disconnect */ + void ConnectPeripheral(int aServerIf, + const nsAString& aBdAddr, + bool aIsDirect, /* auto connect */ + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes); + void DisconnectPeripheral(int aServerIf, + const nsAString& aBdAddr, + int aConnId, + BluetoothGattServerResultHandler* aRes); + + /* Add a services / a characteristic / a descriptor */ + void AddService(int aServerIf, + const BluetoothGattServiceId& aServiceId, + int aNumHandles, + BluetoothGattServerResultHandler* aRes); + void AddIncludedService(int aServerIf, + int aServiceHandle, + int aIncludedServiceHandle, + BluetoothGattServerResultHandler* aRes); + void AddCharacteristic(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattCharProp aProperties, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes); + void AddDescriptor(int aServerIf, + int aServiceHandle, + const BluetoothUuid& aUuid, + BluetoothGattAttrPerm aPermissions, + BluetoothGattServerResultHandler* aRes); + + /* Start / Stop / Delete a service */ + void StartService(int aServerIf, + int aServiceHandle, + BluetoothTransport aTransport, + BluetoothGattServerResultHandler* aRes); + void StopService(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes); + void DeleteService(int aServerIf, + int aServiceHandle, + BluetoothGattServerResultHandler* aRes); + + /* Send an indication or a notification */ + void SendIndication(int aServerIf, + int aAttributeHandle, + int aConnId, + const nsTArray& aValue, + bool aConfirm, /* true: indication, false: notification */ + BluetoothGattServerResultHandler* aRes); + + /* Send a response for an incoming indication */ + void SendResponse(int aConnId, + int aTransId, + BluetoothGattStatus aStatus, + const BluetoothGattResponse& aResponse, + BluetoothGattServerResultHandler* aRes); + +protected: + BluetoothGattServerHALInterface( +#if ANDROID_VERSION >= 19 + const btgatt_server_interface_t* aInterface +#endif + ); + ~BluetoothGattServerHALInterface(); + +private: +#if ANDROID_VERSION >= 19 + const btgatt_server_interface_t* mInterface; +#endif +}; class BluetoothGattHALInterface final : public BluetoothGattInterface @@ -173,6 +256,7 @@ public: void Cleanup(BluetoothGattResultHandler* aRes); BluetoothGattClientInterface* GetBluetoothGattClientInterface(); + BluetoothGattServerInterface* GetBluetoothGattServerInterface(); protected: BluetoothGattHALInterface( diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp index cf8083d795a..09ffc38172e 100644 --- a/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp +++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp @@ -387,6 +387,36 @@ Convert(const BluetoothGattTestParam& aIn, btgatt_test_params_t& aOut) return NS_OK; } + +nsresult +Convert(const BluetoothGattResponse& aIn, btgatt_response_t& aOut) +{ + // Only the read response format is used in bluedroid. + nsresult rv = Convert( + ConvertArray(aIn.mValue, sizeof(aIn.mValue)), + aOut.attr_value.value); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + rv = Convert(aIn.mHandle, aOut.attr_value.handle); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + rv = Convert(aIn.mOffset, aOut.attr_value.offset); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + rv = Convert(aIn.mLength, aOut.attr_value.len); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + rv = Convert(aIn.mAuthReq, aOut.attr_value.auth_req); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + return NS_OK; +} #endif // ANDROID_VERSION >= 19 #if ANDROID_VERSION >= 21 diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h index 6c8a39743f7..980bee22f75 100644 --- a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h +++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h @@ -793,6 +793,40 @@ Convert(int aIn, BluetoothGattStatus& aOut) }; if (static_cast(aIn) >= MOZ_ARRAY_LENGTH(sGattStatus)) { aOut = GATT_STATUS_UNKNOWN_ERROR; + return NS_ERROR_ILLEGAL_VALUE; + } else { + aOut = sGattStatus[aIn]; + } + return NS_OK; +} + +inline nsresult +Convert(BluetoothGattStatus aIn, int& aOut) +{ + /* Reference: $B2G/external/bluetooth/bluedroid/stack/include/gatt_api.h */ + static const int sGattStatus[] = { + CONVERT(GATT_STATUS_SUCCESS, 0x0000), + CONVERT(GATT_STATUS_INVALID_HANDLE, 0x0001), + CONVERT(GATT_STATUS_READ_NOT_PERMITTED, 0x0002), + CONVERT(GATT_STATUS_WRITE_NOT_PERMITTED, 0x0003), + CONVERT(GATT_STATUS_INVALID_PDU, 0x0004), + CONVERT(GATT_STATUS_INSUFFICIENT_AUTHENTICATION, 0x0005), + CONVERT(GATT_STATUS_REQUEST_NOT_SUPPORTED, 0x0006), + CONVERT(GATT_STATUS_INVALID_OFFSET, 0x0007), + CONVERT(GATT_STATUS_INSUFFICIENT_AUTHORIZATION, 0x0008), + CONVERT(GATT_STATUS_PREPARE_QUEUE_FULL, 0x0009), + CONVERT(GATT_STATUS_ATTRIBUTE_NOT_FOUND, 0x000a), + CONVERT(GATT_STATUS_ATTRIBUTE_NOT_LONG, 0x000b), + CONVERT(GATT_STATUS_INSUFFICIENT_ENCRYPTION_KEY_SIZE, 0x000c), + CONVERT(GATT_STATUS_INVALID_ATTRIBUTE_LENGTH, 0x000d), + CONVERT(GATT_STATUS_UNLIKELY_ERROR, 0x000e), + CONVERT(GATT_STATUS_INSUFFICIENT_ENCRYPTION, 0x000f), + CONVERT(GATT_STATUS_UNSUPPORTED_GROUP_TYPE, 0x0010), + CONVERT(GATT_STATUS_INSUFFICIENT_RESOURCES, 0x0011) + }; + if (static_cast(aIn) >= MOZ_ARRAY_LENGTH(sGattStatus)) { + aOut = -1; + return NS_ERROR_ILLEGAL_VALUE; } else { aOut = sGattStatus[aIn]; } @@ -802,6 +836,30 @@ Convert(int aIn, BluetoothGattStatus& aOut) nsresult Convert(const uint8_t* aIn, BluetoothGattAdvData& aOut); +inline nsresult +Convert(BluetoothGattAttrPerm aIn, int& aOut) +{ + /* Reference: $B2G/external/bluetooth/bluedroid/stack/include/gatt_api.h */ + static const uint16_t sGattAttrPermBit[] = { + CONVERT(0, GATT_ATTR_PERM_BIT_READ), + CONVERT(1, GATT_ATTR_PERM_BIT_READ_ENCRYPTED), + CONVERT(2, GATT_ATTR_PERM_BIT_READ_ENCRYPTED_MITM), + CONVERT(3, 0), + CONVERT(4, GATT_ATTR_PERM_BIT_WRITE), + CONVERT(5, GATT_ATTR_PERM_BIT_WRITE_ENCRYPTED), + CONVERT(6, GATT_ATTR_PERM_BIT_WRITE_ENCRYPTED_MITM), + CONVERT(7, GATT_ATTR_PERM_BIT_WRITE_SIGNED), + CONVERT(8, GATT_ATTR_PERM_BIT_WRITE_SIGNED_MITM) + }; + aOut = 0; + for (uint8_t i = 0; i < MOZ_ARRAY_LENGTH(sGattAttrPermBit); i++) { + if (aIn & sGattAttrPermBit[i]) { + aOut |= (1 << i); + } + } + return NS_OK; +} + inline nsresult Convert(int aIn, BluetoothGattCharProp& aOut) { @@ -825,6 +883,29 @@ Convert(int aIn, BluetoothGattCharProp& aOut) return NS_OK; } +inline nsresult +Convert(BluetoothGattCharProp aIn, int& aOut) +{ + /* Reference: $B2G/external/bluetooth/bluedroid/stack/include/gatt_api.h */ + static const uint8_t sGattCharPropBit[] = { + CONVERT(0, GATT_CHAR_PROP_BIT_BROADCAST), + CONVERT(1, GATT_CHAR_PROP_BIT_READ), + CONVERT(2, GATT_CHAR_PROP_BIT_WRITE_NO_RESPONSE), + CONVERT(3, GATT_CHAR_PROP_BIT_WRITE), + CONVERT(4, GATT_CHAR_PROP_BIT_NOTIFY), + CONVERT(5, GATT_CHAR_PROP_BIT_INDICATE), + CONVERT(6, GATT_CHAR_PROP_BIT_SIGNED_WRITE), + CONVERT(7, GATT_CHAR_PROP_BIT_EXTENDED_PROPERTIES) + }; + aOut = 0; + for (uint8_t i = 0; i < MOZ_ARRAY_LENGTH(sGattCharPropBit); i++) { + if (aIn & sGattCharPropBit[i]) { + aOut |= (1 << i); + } + } + return NS_OK; +} + inline nsresult Convert(BluetoothGattAuthReq aIn, int& aOut) { @@ -894,11 +975,6 @@ Convert(const btgatt_notify_params_t& aIn, BluetoothGattNotifyParam& aOut); nsresult Convert(const BluetoothGattTestParam& aIn, btgatt_test_params_t& aOut); -#endif // ANDROID_VERSION >= 19 - -#if ANDROID_VERSION >= 21 -nsresult -Convert(const BluetoothTransport& aIn, btgatt_transport_t& aOut); inline nsresult Convert(BluetoothTransport aIn, int& aOut) @@ -909,12 +985,21 @@ Convert(BluetoothTransport aIn, int& aOut) CONVERT(TRANSPORT_LE, 2) }; if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sTransport))) { + aOut = -1; return NS_ERROR_ILLEGAL_VALUE; } aOut = sTransport[aIn]; return NS_OK; } +nsresult +Convert(const BluetoothGattResponse& aIn, btgatt_response_t& aOut); +#endif // ANDROID_VERSION >= 19 + +#if ANDROID_VERSION >= 21 +nsresult +Convert(const BluetoothTransport& aIn, btgatt_transport_t& aOut); + nsresult Convert(const bt_activity_energy_info& aIn, BluetoothActivityEnergyInfo& aOut); @@ -1620,6 +1705,373 @@ private: Tin5 mArg5; }; +template +class BluetoothNotificationHALRunnable6 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable6 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5, + aIn6))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6) + { + nsRefPtr runnable = Create(aMethod, + aIn1, aIn2, aIn3, aIn4, aIn5, aIn6); + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable6::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable6( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6) + { + nsresult rv = Convert(aIn1, mArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn2, mArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn3, mArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn4, mArg4); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn5, mArg5); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn6, mArg6); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; + Tin6 mArg6; +}; + +template +class BluetoothNotificationHALRunnable7 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable7 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5, + aIn6, aIn7))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7) + { + nsRefPtr runnable = Create(aMethod, + aIn1, aIn2, aIn3, aIn4, aIn5, aIn6, + aIn7); + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable7::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6, mArg7); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable7( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7) + { + nsresult rv = Convert(aIn1, mArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn2, mArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn3, mArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn4, mArg4); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn5, mArg5); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn6, mArg6); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn7, mArg7); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; + Tin6 mArg6; + Tin7 mArg7; +}; + +template +class BluetoothNotificationHALRunnable8 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable8 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7, const T8& aIn8) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5, + aIn6, aIn7, aIn8))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, + Arg8), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7, const T8& aIn8) + { + nsRefPtr runnable = Create(aMethod, + aIn1, aIn2, aIn3, aIn4, aIn5, aIn6, + aIn7, aIn8); + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable8::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() override + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5, mArg6, mArg7, mArg8); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable8( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5, const T6& aIn6, + const T7& aIn7, const T8& aIn8) + { + nsresult rv = Convert(aIn1, mArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn2, mArg2); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn3, mArg3); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn4, mArg4); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn5, mArg5); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn6, mArg6); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn7, mArg7); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn8, mArg8); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; + Tin6 mArg6; + Tin7 mArg7; + Tin8 mArg8; +}; + END_BLUETOOTH_NAMESPACE #endif