From 090e1841698d90de063190acffe1eda850d1256a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 11 Sep 2014 09:38:13 +0200 Subject: [PATCH] Bug 1061489: Distribute Bluetooth HAL implementation among multiple files, r=shuang The files BluetoothHALInterface.{cpp,h} are getting too large. This patch moves helper functions and profile implementations into separate files. --- .../bluedroid/BluetoothA2dpHALInterface.cpp | 184 + .../bluedroid/BluetoothA2dpHALInterface.h | 44 + .../bluedroid/BluetoothAvrcpHALInterface.cpp | 593 +++ .../bluedroid/BluetoothAvrcpHALInterface.h | 84 + .../bluedroid/BluetoothHALHelpers.cpp | 298 ++ dom/bluetooth/bluedroid/BluetoothHALHelpers.h | 1439 +++++++ .../bluedroid/BluetoothHALInterface.cpp | 3684 +---------------- .../bluedroid/BluetoothHALInterface.h | 214 - .../BluetoothHandsfreeHALInterface.cpp | 616 +++ .../BluetoothHandsfreeHALInterface.h | 95 + .../bluedroid/BluetoothSocketHALInterface.cpp | 480 +++ .../bluedroid/BluetoothSocketHALInterface.h | 49 + dom/bluetooth/moz.build | 5 + 13 files changed, 3978 insertions(+), 3807 deletions(-) create mode 100644 dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.cpp create mode 100644 dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.h create mode 100644 dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.cpp create mode 100644 dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.h create mode 100644 dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp create mode 100644 dom/bluetooth/bluedroid/BluetoothHALHelpers.h create mode 100644 dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp create mode 100644 dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h create mode 100644 dom/bluetooth/bluedroid/BluetoothSocketHALInterface.cpp create mode 100644 dom/bluetooth/bluedroid/BluetoothSocketHALInterface.h diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.cpp new file mode 100644 index 000000000000..5bd82e7c893e --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.cpp @@ -0,0 +1,184 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "BluetoothA2dpHALInterface.h" +#include "BluetoothHALHelpers.h" + +BEGIN_BLUETOOTH_NAMESPACE + +typedef + BluetoothHALInterfaceRunnable0 + BluetoothA2dpHALResultRunnable; + +typedef + BluetoothHALInterfaceRunnable1 + BluetoothA2dpHALErrorRunnable; + +static nsresult +DispatchBluetoothA2dpHALResult( + BluetoothA2dpResultHandler* aRes, + void (BluetoothA2dpResultHandler::*aMethod)(), + BluetoothStatus aStatus) +{ + MOZ_ASSERT(aRes); + + nsRunnable* runnable; + + if (aStatus == STATUS_SUCCESS) { + runnable = new BluetoothA2dpHALResultRunnable(aRes, aMethod); + } else { + runnable = new BluetoothA2dpHALErrorRunnable(aRes, + &BluetoothA2dpResultHandler::OnError, aStatus); + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + return rv; +} + +// Notification handling +// + +static BluetoothA2dpNotificationHandler* sA2dpNotificationHandler; + +struct BluetoothA2dpHALCallback +{ + class A2dpNotificationHandlerWrapper + { + public: + typedef BluetoothA2dpNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sA2dpNotificationHandler; + } + }; + + // Notifications + + typedef BluetoothNotificationHALRunnable2< + A2dpNotificationHandlerWrapper, void, + BluetoothA2dpConnectionState, nsString, + BluetoothA2dpConnectionState, const nsAString&> + ConnectionStateNotification; + + typedef BluetoothNotificationHALRunnable2< + A2dpNotificationHandlerWrapper, void, + BluetoothA2dpAudioState, nsString, + BluetoothA2dpAudioState, const nsAString&> + AudioStateNotification; + + // Bluedroid A2DP callbacks + + static void + ConnectionState(btav_connection_state_t aState, bt_bdaddr_t* aBdAddr) + { + ConnectionStateNotification::Dispatch( + &BluetoothA2dpNotificationHandler::ConnectionStateNotification, + aState, aBdAddr); + } + + static void + AudioState(btav_audio_state_t aState, bt_bdaddr_t* aBdAddr) + { + AudioStateNotification::Dispatch( + &BluetoothA2dpNotificationHandler::AudioStateNotification, + aState, aBdAddr); + } +}; + +// Interface +// + +BluetoothA2dpHALInterface::BluetoothA2dpHALInterface( + const btav_interface_t* aInterface) +: mInterface(aInterface) +{ + MOZ_ASSERT(mInterface); +} + +BluetoothA2dpHALInterface::~BluetoothA2dpHALInterface() +{ } + +void +BluetoothA2dpHALInterface::Init( + BluetoothA2dpNotificationHandler* aNotificationHandler, + BluetoothA2dpResultHandler* aRes) +{ + static btav_callbacks_t sCallbacks = { + sizeof(sCallbacks), + BluetoothA2dpHALCallback::ConnectionState, + BluetoothA2dpHALCallback::AudioState + }; + + sA2dpNotificationHandler = aNotificationHandler; + + bt_status_t status = mInterface->init(&sCallbacks); + + if (aRes) { + DispatchBluetoothA2dpHALResult(aRes, + &BluetoothA2dpResultHandler::Init, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothA2dpHALInterface::Cleanup(BluetoothA2dpResultHandler* aRes) +{ + mInterface->cleanup(); + + if (aRes) { + DispatchBluetoothA2dpHALResult(aRes, + &BluetoothA2dpResultHandler::Cleanup, + STATUS_SUCCESS); + } +} + +void +BluetoothA2dpHALInterface::Connect(const nsAString& aBdAddr, + BluetoothA2dpResultHandler* aRes) +{ + bt_status_t status; + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->connect(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothA2dpHALResult( + aRes, &BluetoothA2dpResultHandler::Connect, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothA2dpHALInterface::Disconnect(const nsAString& aBdAddr, + BluetoothA2dpResultHandler* aRes) +{ + bt_status_t status; + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->disconnect(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothA2dpHALResult( + aRes, &BluetoothA2dpResultHandler::Disconnect, + ConvertDefault(status, STATUS_FAIL)); + } +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.h b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.h new file mode 100644 index 000000000000..84b1108bf3fa --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.h @@ -0,0 +1,44 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetootha2dphalinterface_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetootha2dphalinterface_h__ + +#include +#include +#include "BluetoothCommon.h" +#include "BluetoothInterface.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothHALInterface; + +class BluetoothA2dpHALInterface MOZ_FINAL + : public BluetoothA2dpInterface +{ +public: + friend class BluetoothHALInterface; + + void Init(BluetoothA2dpNotificationHandler* aNotificationHandler, + BluetoothA2dpResultHandler* aRes); + void Cleanup(BluetoothA2dpResultHandler* aRes); + + void Connect(const nsAString& aBdAddr, + BluetoothA2dpResultHandler* aRes); + void Disconnect(const nsAString& aBdAddr, + BluetoothA2dpResultHandler* aRes); + +protected: + BluetoothA2dpHALInterface(const btav_interface_t* aInterface); + ~BluetoothA2dpHALInterface(); + +private: + const btav_interface_t* mInterface; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff --git a/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.cpp new file mode 100644 index 000000000000..3b9f1e8bae9d --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.cpp @@ -0,0 +1,593 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "BluetoothAvrcpHALInterface.h" +#include "BluetoothHALHelpers.h" + +BEGIN_BLUETOOTH_NAMESPACE + +typedef + BluetoothHALInterfaceRunnable0 + BluetoothAvrcpHALResultRunnable; + +typedef + BluetoothHALInterfaceRunnable1 + BluetoothAvrcpHALErrorRunnable; + +static nsresult +DispatchBluetoothAvrcpHALResult( + BluetoothAvrcpResultHandler* aRes, + void (BluetoothAvrcpResultHandler::*aMethod)(), + BluetoothStatus aStatus) +{ + MOZ_ASSERT(aRes); + + nsRunnable* runnable; + + if (aStatus == STATUS_SUCCESS) { + runnable = new BluetoothAvrcpHALResultRunnable(aRes, aMethod); + } else { + runnable = new BluetoothAvrcpHALErrorRunnable(aRes, + &BluetoothAvrcpResultHandler::OnError, aStatus); + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + return rv; +} + +// Notification handling +// + +static BluetoothAvrcpNotificationHandler* sAvrcpNotificationHandler; + +struct BluetoothAvrcpCallback +{ + class AvrcpNotificationHandlerWrapper + { + public: + typedef BluetoothAvrcpNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sAvrcpNotificationHandler; + } + }; + + // Notifications + + typedef BluetoothNotificationHALRunnable0 + GetPlayStatusNotification; + + typedef BluetoothNotificationHALRunnable0 + ListPlayerAppAttrNotification; + + typedef BluetoothNotificationHALRunnable1 + ListPlayerAppValuesNotification; + + typedef BluetoothNotificationHALRunnable2, + uint8_t, const BluetoothAvrcpPlayerAttribute*> + GetPlayerAppValueNotification; + + typedef BluetoothNotificationHALRunnable2, + uint8_t, const BluetoothAvrcpPlayerAttribute*> + GetPlayerAppAttrsTextNotification; + + typedef BluetoothNotificationHALRunnable3, + uint8_t, uint8_t, const uint8_t*> + GetPlayerAppValuesTextNotification; + + typedef BluetoothNotificationHALRunnable1 + SetPlayerAppValueNotification; + + typedef BluetoothNotificationHALRunnable2, + uint8_t, const BluetoothAvrcpMediaAttribute*> + GetElementAttrNotification; + + typedef BluetoothNotificationHALRunnable2 + RegisterNotificationNotification; + + typedef BluetoothNotificationHALRunnable2 + RemoteFeatureNotification; + + typedef BluetoothNotificationHALRunnable2 + VolumeChangeNotification; + + typedef BluetoothNotificationHALRunnable2 + PassthroughCmdNotification; + + // Bluedroid AVRCP callbacks + +#if ANDROID_VERSION >= 18 + static void + GetPlayStatus() + { + GetPlayStatusNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayStatusNotification); + } + + static void + ListPlayerAppAttr() + { + ListPlayerAppAttrNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification); + } + + static void + ListPlayerAppValues(btrc_player_attr_t aAttrId) + { + ListPlayerAppValuesNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification, + aAttrId); + } + + static void + GetPlayerAppValue(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs) + { + GetPlayerAppValueNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification, + aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); + } + + static void + GetPlayerAppAttrsText(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs) + { + GetPlayerAppAttrsTextNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification, + aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); + } + + static void + GetPlayerAppValuesText(uint8_t aAttrId, uint8_t aNumVals, uint8_t* aVals) + { + GetPlayerAppValuesTextNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification, + aAttrId, aNumVals, ConvertArray(aVals, aNumVals)); + } + + static void + SetPlayerAppValue(btrc_player_settings_t* aVals) + { + SetPlayerAppValueNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification, + *aVals); + } + + static void + GetElementAttr(uint8_t aNumAttrs, btrc_media_attr_t* aAttrs) + { + GetElementAttrNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::GetElementAttrNotification, + aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); + } + + static void + RegisterNotification(btrc_event_id_t aEvent, uint32_t aParam) + { + RegisterNotificationNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::RegisterNotificationNotification, + aEvent, aParam); + } +#endif // ANDROID_VERSION >= 18 + +#if ANDROID_VERSION >= 19 + static void + RemoteFeature(bt_bdaddr_t* aBdAddr, btrc_remote_features_t aFeatures) + { + RemoteFeatureNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::RemoteFeatureNotification, + aBdAddr, aFeatures); + } + + static void + VolumeChange(uint8_t aVolume, uint8_t aCType) + { + VolumeChangeNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::VolumeChangeNotification, + aVolume, aCType); + } + + static void + PassthroughCmd(int aId, int aKeyState) + { + PassthroughCmdNotification::Dispatch( + &BluetoothAvrcpNotificationHandler::PassthroughCmdNotification, + aId, aKeyState); + } +#endif // ANDROID_VERSION >= 19 +}; + +// Interface +// + +BluetoothAvrcpHALInterface::BluetoothAvrcpHALInterface( +#if ANDROID_VERSION >= 18 + const btrc_interface_t* aInterface +#endif + ) +#if ANDROID_VERSION >= 18 +: mInterface(aInterface) +#endif +{ +#if ANDROID_VERSION >= 18 + MOZ_ASSERT(mInterface); +#endif +} + +BluetoothAvrcpHALInterface::~BluetoothAvrcpHALInterface() +{ } + +void +BluetoothAvrcpHALInterface::Init( + BluetoothAvrcpNotificationHandler* aNotificationHandler, + BluetoothAvrcpResultHandler* aRes) +{ +#if ANDROID_VERSION >= 18 + static btrc_callbacks_t sCallbacks = { + sizeof(sCallbacks), +#if ANDROID_VERSION >= 19 + BluetoothAvrcpCallback::RemoteFeature, +#endif + BluetoothAvrcpCallback::GetPlayStatus, + BluetoothAvrcpCallback::ListPlayerAppAttr, + BluetoothAvrcpCallback::ListPlayerAppValues, + BluetoothAvrcpCallback::GetPlayerAppValue, + BluetoothAvrcpCallback::GetPlayerAppAttrsText, + BluetoothAvrcpCallback::GetPlayerAppValuesText, + BluetoothAvrcpCallback::SetPlayerAppValue, + BluetoothAvrcpCallback::GetElementAttr, + BluetoothAvrcpCallback::RegisterNotification +#if ANDROID_VERSION >= 19 + , + BluetoothAvrcpCallback::VolumeChange, + BluetoothAvrcpCallback::PassthroughCmd +#endif + }; +#endif // ANDROID_VERSION >= 18 + + sAvrcpNotificationHandler = aNotificationHandler; + +#if ANDROID_VERSION >= 18 + bt_status_t status = mInterface->init(&sCallbacks); +#else + bt_status_t status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult(aRes, &BluetoothAvrcpResultHandler::Init, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::Cleanup(BluetoothAvrcpResultHandler* aRes) +{ +#if ANDROID_VERSION >= 18 + mInterface->cleanup(); +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult(aRes, + &BluetoothAvrcpResultHandler::Cleanup, STATUS_SUCCESS); + } +} + +void +BluetoothAvrcpHALInterface::GetPlayStatusRsp( + ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos, + BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + btrc_play_status_t playStatus = BTRC_PLAYSTATE_STOPPED; + + if (!(NS_FAILED(Convert(aPlayStatus, playStatus)))) { + status = mInterface->get_play_status_rsp(playStatus, aSongLen, aSongPos); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::ListPlayerAppAttrRsp( + int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs, + BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + ConvertArray pAttrsArray(aPAttrs, aNumAttr); + nsAutoArrayPtr pAttrs; + + if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) { + status = mInterface->list_player_app_attr_rsp(aNumAttr, pAttrs); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::ListPlayerAppValueRsp( + int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes) +{ +#if ANDROID_VERSION >= 18 + bt_status_t status = mInterface->list_player_app_value_rsp(aNumVal, aPVals); +#else + bt_status_t status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::GetPlayerAppValueRsp( + uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues, + BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + btrc_player_settings_t pVals; + + /* FIXME: you need to implement the missing conversion functions */ + NS_NOTREACHED("Conversion function missing"); + + if (false /* TODO: we don't support any player app values currently */) { + status = mInterface->get_player_app_value_rsp(&pVals); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::GetPlayerAppAttrTextRsp( + int aNumAttr, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + btrc_player_setting_text_t* aPAttrs; + + /* FIXME: you need to implement the missing conversion functions */ + NS_NOTREACHED("Conversion function missing"); + + if (false /* TODO: we don't support any attributes currently */) { + status = mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::GetPlayerAppValueTextRsp( + int aNumVal, const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + btrc_player_setting_text_t* pVals; + + /* FIXME: you need to implement the missing conversion functions */ + NS_NOTREACHED("Conversion function missing"); + + if (false /* TODO: we don't support any values currently */) { + status = mInterface->get_player_app_value_text_rsp(aNumVal, pVals); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::GetElementAttrRsp( + uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttrs, + BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + ConvertArray pAttrsArray(aAttrs, aNumAttr); + nsAutoArrayPtr pAttrs; + + if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) { + status = mInterface->get_element_attr_rsp(aNumAttr, pAttrs); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::SetPlayerAppValueRsp( + BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + btrc_status_t rspStatus = BTRC_STS_BAD_CMD; // silences compiler warning + + if (NS_SUCCEEDED(Convert(aRspStatus, rspStatus))) { + status = mInterface->set_player_app_value_rsp(rspStatus); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::RegisterNotificationRsp( + BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, + BluetoothAvrcpResultHandler* aRes) +{ + bt_status_t status; + +#if ANDROID_VERSION >= 18 + nsresult rv; + btrc_event_id_t event = { }; + btrc_notification_type_t type = BTRC_NOTIFICATION_TYPE_INTERIM; + btrc_register_notification_t param; + + switch (aEvent) { + case AVRCP_EVENT_PLAY_STATUS_CHANGED: + rv = Convert(aParam.mPlayStatus, param.play_status); + break; + case AVRCP_EVENT_TRACK_CHANGE: + MOZ_ASSERT(sizeof(aParam.mTrack) == sizeof(param.track)); + memcpy(param.track, aParam.mTrack, sizeof(param.track)); + rv = NS_OK; + break; + case AVRCP_EVENT_TRACK_REACHED_END: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + case AVRCP_EVENT_TRACK_REACHED_START: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + case AVRCP_EVENT_PLAY_POS_CHANGED: + param.song_pos = aParam.mSongPos; + rv = NS_OK; + break; + case AVRCP_EVENT_APP_SETTINGS_CHANGED: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + default: + NS_NOTREACHED("Unknown conversion"); + rv = NS_ERROR_ILLEGAL_VALUE; + break; + } + + if (NS_SUCCEEDED(rv) && + NS_SUCCEEDED(Convert(aEvent, event)) && + NS_SUCCEEDED(Convert(aType, type))) { + status = mInterface->register_notification_rsp(event, type, ¶m); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothAvrcpHALInterface::SetVolume(uint8_t aVolume, + BluetoothAvrcpResultHandler* aRes) +{ +#if ANDROID_VERSION >= 19 + bt_status_t status = mInterface->set_volume(aVolume); +#else + bt_status_t status = BT_STATUS_UNSUPPORTED; +#endif + + if (aRes) { + DispatchBluetoothAvrcpHALResult( + aRes, &BluetoothAvrcpResultHandler::SetVolume, + ConvertDefault(status, STATUS_FAIL)); + } +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.h b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.h new file mode 100644 index 000000000000..8dcd54fc6bc5 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.h @@ -0,0 +1,84 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothavrcphalinterface_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothavrcphalinterface_h__ + +#include +#if ANDROID_VERSION >= 18 +#include +#endif +#include "BluetoothCommon.h" +#include "BluetoothInterface.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothHALInterface; + +class BluetoothAvrcpHALInterface MOZ_FINAL + : public BluetoothAvrcpInterface +{ +public: + friend class BluetoothHALInterface; + + void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler, + BluetoothAvrcpResultHandler* aRes); + void Cleanup(BluetoothAvrcpResultHandler* aRes); + + void GetPlayStatusRsp(ControlPlayStatus aPlayStatus, + uint32_t aSongLen, uint32_t aSongPos, + BluetoothAvrcpResultHandler* aRes); + + void ListPlayerAppAttrRsp(int aNumAttr, + const BluetoothAvrcpPlayerAttribute* aPAttrs, + BluetoothAvrcpResultHandler* aRes); + void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals, + BluetoothAvrcpResultHandler* aRes); + + /* TODO: redesign this interface once we actually use it */ + void GetPlayerAppValueRsp(uint8_t aNumAttrs, + const uint8_t* aIds, const uint8_t* aValues, + BluetoothAvrcpResultHandler* aRes); + /* TODO: redesign this interface once we actually use it */ + void GetPlayerAppAttrTextRsp(int aNumAttr, + const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes); + /* TODO: redesign this interface once we actually use it */ + void GetPlayerAppValueTextRsp(int aNumVal, + const uint8_t* aIds, const char** aTexts, + BluetoothAvrcpResultHandler* aRes); + + void GetElementAttrRsp(uint8_t aNumAttr, + const BluetoothAvrcpElementAttribute* aAttr, + BluetoothAvrcpResultHandler* aRes); + + void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus, + BluetoothAvrcpResultHandler* aRes); + + void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent, + BluetoothAvrcpNotification aType, + const BluetoothAvrcpNotificationParam& aParam, + BluetoothAvrcpResultHandler* aRes); + + void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes); + +protected: + BluetoothAvrcpHALInterface( +#if ANDROID_VERSION >= 18 + const btrc_interface_t* aInterface +#endif + ); + ~BluetoothAvrcpHALInterface(); + +private: +#if ANDROID_VERSION >= 18 + const btrc_interface_t* mInterface; +#endif +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp new file mode 100644 index 000000000000..f0163b26084d --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp @@ -0,0 +1,298 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "BluetoothHALHelpers.h" + +#define MAX_UUID_SIZE 16 + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Conversion +// + +nsresult +Convert(const nsAString& aIn, bt_property_type_t& aOut) +{ + if (aIn.EqualsLiteral("Name")) { + aOut = BT_PROPERTY_BDNAME; + } else if (aIn.EqualsLiteral("Discoverable")) { + aOut = BT_PROPERTY_ADAPTER_SCAN_MODE; + } else if (aIn.EqualsLiteral("DiscoverableTimeout")) { + aOut = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT; + } else { + BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aIn).get()); + return NS_ERROR_ILLEGAL_VALUE; + } + return NS_OK; +} + +nsresult +Convert(ConvertNamedValue& aIn, bt_property_t& aOut) +{ + nsresult rv = Convert(aIn.mNamedValue.name(), aOut.type); + if (NS_FAILED(rv)) { + return rv; + } + + if (aIn.mNamedValue.value().type() == BluetoothValue::Tuint32_t) { + // Set discoverable timeout + aOut.val = + reinterpret_cast(aIn.mNamedValue.value().get_uint32_t()); + } else if (aIn.mNamedValue.value().type() == BluetoothValue::TnsString) { + // Set name + aIn.mStringValue = + NS_ConvertUTF16toUTF8(aIn.mNamedValue.value().get_nsString()); + aOut.val = + const_cast(static_cast(aIn.mStringValue.get())); + aOut.len = strlen(static_cast(aOut.val)); + } else if (aIn.mNamedValue.value().type() == BluetoothValue::Tbool) { + // Set scan mode + rv = Convert(aIn.mNamedValue.value().get_bool(), aIn.mScanMode); + if (NS_FAILED(rv)) { + return rv; + } + aOut.val = &aIn.mScanMode; + aOut.len = sizeof(aIn.mScanMode); + } else { + BT_LOGR("Invalid property value type"); + return NS_ERROR_ILLEGAL_VALUE; + } + + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, bt_bdaddr_t& aOut) +{ + NS_ConvertUTF16toUTF8 bdAddressUTF8(aIn); + const char* str = bdAddressUTF8.get(); + + for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aOut.address); ++i, ++str) { + aOut.address[i] = + static_cast(strtoul(str, const_cast(&str), 16)); + } + + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, bt_ssp_variant_t& aOut) +{ + if (aIn.EqualsLiteral("PasskeyConfirmation")) { + aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION; + } else if (aIn.EqualsLiteral("PasskeyEntry")) { + aOut = BT_SSP_VARIANT_PASSKEY_ENTRY; + } else if (aIn.EqualsLiteral("Consent")) { + aOut = BT_SSP_VARIANT_CONSENT; + } else if (aIn.EqualsLiteral("PasskeyNotification")) { + aOut = BT_SSP_VARIANT_PASSKEY_NOTIFICATION; + } else { + BT_LOGR("Invalid SSP variant name: %s", NS_ConvertUTF16toUTF8(aIn).get()); + aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning + return NS_ERROR_ILLEGAL_VALUE; + } + return NS_OK; +} + +nsresult +Convert(const uint8_t aIn[16], bt_uuid_t& aOut) +{ + if (sizeof(aOut.uu) != 16) { + return NS_ERROR_ILLEGAL_VALUE; + } + + memcpy(aOut.uu, aIn, sizeof(aOut.uu)); + + return NS_OK; +} + +nsresult +Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut) +{ + if (sizeof(aIn.uu) != sizeof(aOut.mUuid)) { + return NS_ERROR_ILLEGAL_VALUE; + } + + memcpy(aOut.mUuid, aIn.uu, sizeof(aOut.mUuid)); + + return NS_OK; +} + +nsresult +Convert(const nsAString& aIn, bt_pin_code_t& aOut) +{ + if (aIn.Length() > MOZ_ARRAY_LENGTH(aOut.pin)) { + return NS_ERROR_ILLEGAL_VALUE; + } + + NS_ConvertUTF16toUTF8 pinCodeUTF8(aIn); + const char* str = pinCodeUTF8.get(); + + nsAString::size_type i; + + // Fill pin into aOut + for (i = 0; i < aIn.Length(); ++i, ++str) { + aOut.pin[i] = static_cast(*str); + } + + // Clear remaining bytes in aOut + size_t ntrailing = + (MOZ_ARRAY_LENGTH(aOut.pin) - aIn.Length()) * sizeof(aOut.pin[0]); + memset(aOut.pin + aIn.Length(), 0, ntrailing); + + return NS_OK; +} + +nsresult +Convert(const bt_bdaddr_t& aIn, nsAString& aOut) +{ + char str[BLUETOOTH_ADDRESS_LENGTH + 1]; + + int res = snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", + static_cast(aIn.address[0]), + static_cast(aIn.address[1]), + static_cast(aIn.address[2]), + static_cast(aIn.address[3]), + static_cast(aIn.address[4]), + static_cast(aIn.address[5])); + if (res < 0) { + return NS_ERROR_ILLEGAL_VALUE; + } else if ((size_t)res >= sizeof(str)) { + return NS_ERROR_OUT_OF_MEMORY; /* string buffer too small */ + } + + aOut = NS_ConvertUTF8toUTF16(str); + + return NS_OK; +} + +nsresult +Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut) +{ + nsresult rv = Convert(aIn.uuid, aOut.mUuid); + if (NS_FAILED(rv)) { + return rv; + } + + aOut.mChannel = aIn.channel; + + MOZ_ASSERT(sizeof(aIn.name) == sizeof(aOut.mName)); + memcpy(aOut.mName, aIn.name, sizeof(aOut.mName)); + + return NS_OK; +} + +#if ANDROID_VERSION >= 18 +nsresult +Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut) +{ + const NS_ConvertUTF16toUTF8 value(aIn.mValue); + size_t len = std::min(strlen(value.get()), sizeof(aOut.text) - 1); + + memcpy(aOut.text, value.get(), len); + aOut.text[len] = '\0'; + aOut.attr_id = aIn.mId; + + return NS_OK; +} + +nsresult +Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut) +{ + aOut.mNumAttr = aIn.num_attr; + memcpy(aOut.mIds, aIn.attr_ids, aIn.num_attr); + memcpy(aOut.mValues, aIn.attr_values, aIn.num_attr); + + return NS_OK; +} +#endif // ANDROID_VERSION >= 18 + +nsresult +Convert(const bt_property_t& aIn, BluetoothProperty& aOut) +{ + /* type conversion */ + + nsresult rv = Convert(aIn.type, aOut.mType); + if (NS_FAILED(rv)) { + return rv; + } + + /* value conversion */ + + switch (aOut.mType) { + case PROPERTY_BDNAME: + /* fall through */ + case PROPERTY_REMOTE_FRIENDLY_NAME: + { + // We construct an nsCString here because bdname + // returned from Bluedroid is not 0-terminated. + aOut.mString = NS_ConvertUTF8toUTF16( + nsCString(static_cast(aIn.val), aIn.len)); + } + break; + case PROPERTY_BDADDR: + rv = Convert(*static_cast(aIn.val), aOut.mString); + break; + case PROPERTY_UUIDS: + { + size_t numUuids = aIn.len / MAX_UUID_SIZE; + ConvertArray array( + static_cast(aIn.val), numUuids); + aOut.mUuidArray.SetLength(numUuids); + rv = Convert(array, aOut.mUuidArray); + } + break; + case PROPERTY_CLASS_OF_DEVICE: + /* fall through */ + case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: + aOut.mUint32 = *static_cast(aIn.val); + break; + case PROPERTY_TYPE_OF_DEVICE: + rv = Convert(*static_cast(aIn.val), + aOut.mDeviceType); + break; + case PROPERTY_SERVICE_RECORD: + rv = Convert(*static_cast(aIn.val), + aOut.mServiceRecord); + break; + case PROPERTY_ADAPTER_SCAN_MODE: + rv = Convert(*static_cast(aIn.val), + aOut.mScanMode); + break; + case PROPERTY_ADAPTER_BONDED_DEVICES: + { + size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES; + ConvertArray array( + static_cast(aIn.val), numAddresses); + aOut.mStringArray.SetLength(numAddresses); + rv = Convert(array, aOut.mStringArray); + } + break; + case PROPERTY_REMOTE_RSSI: + aOut.mInt32 = *static_cast(aIn.val); + break; +#if ANDROID_VERSION >= 18 + case PROPERTY_REMOTE_VERSION_INFO: + rv = Convert(*static_cast(aIn.val), + aOut.mRemoteInfo); + break; +#endif + case PROPERTY_REMOTE_DEVICE_TIMESTAMP: + /* nothing to do */ + break; + default: + /* mismatch with type conversion */ + NS_NOTREACHED("Unhandled property type"); + break; + } + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h new file mode 100644 index 000000000000..a3db9504fa5b --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h @@ -0,0 +1,1439 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothhalhelpers_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothhalhelpers_h__ + +#include +#include +#include +#include +#if ANDROID_VERSION >= 18 +#include +#endif +#include "BluetoothCommon.h" +#include "mozilla/ArrayUtils.h" +#include "mozilla/dom/bluetooth/BluetoothTypes.h" +#include "nsThreadUtils.h" + +#if MOZ_IS_GCC && MOZ_GCC_VERSION_AT_LEAST(4, 7, 0) +/* use designated array initializers if supported */ +#define CONVERT(in_, out_) \ + [in_] = out_ +#else +/* otherwise init array element by position */ +#define CONVERT(in_, out_) \ + out_ +#endif + +BEGIN_BLUETOOTH_NAMESPACE + +// +// Conversion +// + +inline nsresult +Convert(bt_status_t aIn, BluetoothStatus& aOut) +{ + static const BluetoothStatus sStatus[] = { + CONVERT(BT_STATUS_SUCCESS, STATUS_SUCCESS), + CONVERT(BT_STATUS_FAIL, STATUS_FAIL), + CONVERT(BT_STATUS_NOT_READY, STATUS_NOT_READY), + CONVERT(BT_STATUS_NOMEM, STATUS_NOMEM), + CONVERT(BT_STATUS_BUSY, STATUS_BUSY), + CONVERT(BT_STATUS_DONE, STATUS_DONE), + CONVERT(BT_STATUS_UNSUPPORTED, STATUS_UNSUPPORTED), + CONVERT(BT_STATUS_PARM_INVALID, STATUS_PARM_INVALID), + CONVERT(BT_STATUS_UNHANDLED, STATUS_UNHANDLED), + CONVERT(BT_STATUS_AUTH_FAILURE, STATUS_AUTH_FAILURE), + CONVERT(BT_STATUS_RMT_DEV_DOWN, STATUS_RMT_DEV_DOWN) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sStatus[aIn]; + return NS_OK; +} + +inline nsresult +Convert(int aIn, BluetoothStatus& aOut) +{ + return Convert(static_cast(aIn), aOut); +} + +nsresult +Convert(const nsAString& aIn, bt_property_type_t& aOut); + +inline nsresult +Convert(bool aIn, bt_scan_mode_t& aOut) +{ + static const bt_scan_mode_t sScanMode[] = { + CONVERT(false, BT_SCAN_MODE_CONNECTABLE), + CONVERT(true, BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sScanMode[aIn]; + return NS_OK; +} + + +inline nsresult +Convert(bt_scan_mode_t aIn, BluetoothScanMode& aOut) +{ + static const BluetoothScanMode sScanMode[] = { + CONVERT(BT_SCAN_MODE_NONE, SCAN_MODE_NONE), + CONVERT(BT_SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE), + CONVERT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE, + SCAN_MODE_CONNECTABLE_DISCOVERABLE) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sScanMode[aIn]; + return NS_OK; +} + +struct ConvertNamedValue +{ + ConvertNamedValue(const BluetoothNamedValue& aNamedValue) + : mNamedValue(aNamedValue) + { } + + const BluetoothNamedValue& mNamedValue; + + // temporary fields + nsCString mStringValue; + bt_scan_mode_t mScanMode; +}; + +nsresult +Convert(ConvertNamedValue& aIn, bt_property_t& aOut); + +nsresult +Convert(const nsAString& aIn, bt_bdaddr_t& aOut); + +nsresult +Convert(const nsAString& aIn, bt_ssp_variant_t& aOut); + +inline nsresult +Convert(const bt_ssp_variant_t& aIn, nsAString& aOut) +{ + static const char * const sSspVariant[] = { + CONVERT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION, "PasskeyConfirmation"), + CONVERT(BT_SSP_VARIANT_PASSKEY_ENTRY, "PasskeyEntry"), + CONVERT(BT_SSP_VARIANT_CONSENT, "Consent"), + CONVERT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION, "PasskeyNotification") + }; + if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = NS_ConvertUTF8toUTF16(sSspVariant[aIn]); + return NS_OK; +} + +inline nsresult +Convert(const bool& aIn, uint8_t& aOut) +{ + // casting converts true/false to either 1 or 0 + aOut = static_cast(aIn); + return NS_OK; +} + +nsresult +Convert(const uint8_t aIn[16], bt_uuid_t& aOut); + +nsresult +Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut); + +nsresult +Convert(const nsAString& aIn, bt_pin_code_t& aOut); + +nsresult +Convert(const bt_bdaddr_t& aIn, nsAString& aOut); + +inline nsresult +Convert(const bt_bdaddr_t* aIn, nsAString& aOut) +{ + if (!aIn) { + aOut.AssignLiteral(BLUETOOTH_ADDRESS_NONE); + return NS_OK; + } + return Convert(*aIn, aOut); +} + +inline nsresult +Convert(bt_state_t aIn, bool& aOut) +{ + static const bool sState[] = { + CONVERT(BT_STATE_OFF, false), + CONVERT(BT_STATE_ON, true) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bt_property_type_t aIn, BluetoothPropertyType& aOut) +{ + static const BluetoothPropertyType sPropertyType[] = { + CONVERT(0, static_cast(0)), // invalid, required by gcc + CONVERT(BT_PROPERTY_BDNAME, PROPERTY_BDNAME), + CONVERT(BT_PROPERTY_BDADDR, PROPERTY_BDADDR), + CONVERT(BT_PROPERTY_UUIDS, PROPERTY_UUIDS), + CONVERT(BT_PROPERTY_CLASS_OF_DEVICE, PROPERTY_CLASS_OF_DEVICE), + CONVERT(BT_PROPERTY_TYPE_OF_DEVICE, PROPERTY_TYPE_OF_DEVICE), + CONVERT(BT_PROPERTY_SERVICE_RECORD, PROPERTY_SERVICE_RECORD), + CONVERT(BT_PROPERTY_ADAPTER_SCAN_MODE, PROPERTY_ADAPTER_SCAN_MODE), + CONVERT(BT_PROPERTY_ADAPTER_BONDED_DEVICES, + PROPERTY_ADAPTER_BONDED_DEVICES), + CONVERT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, + PROPERTY_ADAPTER_DISCOVERY_TIMEOUT), + CONVERT(BT_PROPERTY_REMOTE_FRIENDLY_NAME, PROPERTY_REMOTE_FRIENDLY_NAME), + CONVERT(BT_PROPERTY_REMOTE_RSSI, PROPERTY_REMOTE_RSSI), + CONVERT(BT_PROPERTY_REMOTE_VERSION_INFO,PROPERTY_REMOTE_VERSION_INFO) + }; + if (aIn == BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP) { + /* This case is handled separately to not populate + * |sPropertyType| with empty entries. */ + aOut = PROPERTY_REMOTE_DEVICE_TIMESTAMP; + return NS_OK; + } + if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPropertyType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPropertyType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bt_discovery_state_t aIn, bool& aOut) +{ + static const bool sDiscoveryState[] = { + CONVERT(BT_DISCOVERY_STOPPED, false), + CONVERT(BT_DISCOVERY_STARTED, true) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sDiscoveryState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sDiscoveryState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(const char* aIn, nsACString& aOut) +{ + aOut.Assign(aIn); + + return NS_OK; +} + +inline nsresult +Convert(const char* aIn, nsAString& aOut) +{ + aOut = NS_ConvertUTF8toUTF16(aIn); + + return NS_OK; +} + +inline nsresult +Convert(const bt_bdname_t& aIn, nsAString& aOut) +{ + return Convert(reinterpret_cast(aIn.name), aOut); +} + +inline nsresult +Convert(const bt_bdname_t* aIn, nsAString& aOut) +{ + if (!aIn) { + aOut.Truncate(); + return NS_OK; + } + return Convert(*aIn, aOut); +} + +inline nsresult +Convert(bt_bond_state_t aIn, BluetoothBondState& aOut) +{ + static const BluetoothBondState sBondState[] = { + CONVERT(BT_BOND_STATE_NONE, BOND_STATE_NONE), + CONVERT(BT_BOND_STATE_BONDING, BOND_STATE_BONDING), + CONVERT(BT_BOND_STATE_BONDED, BOND_STATE_BONDED) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sBondState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sBondState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bt_acl_state_t aIn, bool& aOut) +{ + static const bool sAclState[] = { + CONVERT(BT_ACL_STATE_CONNECTED, true), + CONVERT(BT_ACL_STATE_DISCONNECTED, false) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sAclState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAclState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bt_device_type_t aIn, BluetoothDeviceType& aOut) +{ + static const BluetoothDeviceType sDeviceType[] = { + CONVERT(0, static_cast(0)), // invalid, required by gcc + CONVERT(BT_DEVICE_DEVTYPE_BREDR, DEVICE_TYPE_BREDR), + CONVERT(BT_DEVICE_DEVTYPE_BLE, DEVICE_TYPE_BLE), + CONVERT(BT_DEVICE_DEVTYPE_DUAL, DEVICE_TYPE_DUAL) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sDeviceType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sDeviceType[aIn]; + return NS_OK; +} + +nsresult +Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut); + +inline nsresult +Convert(BluetoothSocketType aIn, btsock_type_t& aOut) +{ + // FIXME: Array member [0] is currently invalid, but required + // by gcc. Start values in |BluetoothSocketType| at index + // 0 to fix this problem. + static const btsock_type_t sSocketType[] = { + CONVERT(0, static_cast(0)), // invalid, [0] required by gcc + CONVERT(BluetoothSocketType::RFCOMM, BTSOCK_RFCOMM), + CONVERT(BluetoothSocketType::SCO, BTSOCK_SCO), + CONVERT(BluetoothSocketType::L2CAP, BTSOCK_L2CAP), + // EL2CAP is not supported by Bluedroid + }; + if (aIn == BluetoothSocketType::EL2CAP || + aIn >= MOZ_ARRAY_LENGTH(sSocketType) || !sSocketType[aIn]) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sSocketType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeAtResponse aIn, bthf_at_response_t& aOut) +{ + static const bthf_at_response_t sAtResponse[] = { + CONVERT(HFP_AT_RESPONSE_ERROR, BTHF_AT_RESPONSE_ERROR), + CONVERT(HFP_AT_RESPONSE_OK, BTHF_AT_RESPONSE_OK) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sAtResponse)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAtResponse[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeCallAddressType aIn, bthf_call_addrtype_t& aOut) +{ + static const bthf_call_addrtype_t sCallAddressType[] = { + CONVERT(HFP_CALL_ADDRESS_TYPE_UNKNOWN, BTHF_CALL_ADDRTYPE_UNKNOWN), + CONVERT(HFP_CALL_ADDRESS_TYPE_INTERNATIONAL, + BTHF_CALL_ADDRTYPE_INTERNATIONAL) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sCallAddressType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallAddressType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeCallDirection aIn, bthf_call_direction_t& aOut) +{ + static const bthf_call_direction_t sCallDirection[] = { + CONVERT(HFP_CALL_DIRECTION_OUTGOING, BTHF_CALL_DIRECTION_OUTGOING), + CONVERT(HFP_CALL_DIRECTION_INCOMING, BTHF_CALL_DIRECTION_INCOMING) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sCallDirection)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallDirection[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeCallMode aIn, bthf_call_mode_t& aOut) +{ + static const bthf_call_mode_t sCallMode[] = { + CONVERT(HFP_CALL_MODE_VOICE, BTHF_CALL_TYPE_VOICE), + CONVERT(HFP_CALL_MODE_DATA, BTHF_CALL_TYPE_DATA), + CONVERT(HFP_CALL_MODE_FAX, BTHF_CALL_TYPE_FAX) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sCallMode)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallMode[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeCallMptyType aIn, bthf_call_mpty_type_t& aOut) +{ + static const bthf_call_mpty_type_t sCallMptyType[] = { + CONVERT(HFP_CALL_MPTY_TYPE_SINGLE, BTHF_CALL_MPTY_TYPE_SINGLE), + CONVERT(HFP_CALL_MPTY_TYPE_MULTI, BTHF_CALL_MPTY_TYPE_MULTI) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sCallMptyType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallMptyType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeCallState aIn, bthf_call_state_t& aOut) +{ + static const bthf_call_state_t sCallState[] = { + CONVERT(HFP_CALL_STATE_ACTIVE, BTHF_CALL_STATE_ACTIVE), + CONVERT(HFP_CALL_STATE_HELD, BTHF_CALL_STATE_HELD), + CONVERT(HFP_CALL_STATE_DIALING, BTHF_CALL_STATE_DIALING), + CONVERT(HFP_CALL_STATE_ALERTING, BTHF_CALL_STATE_ALERTING), + CONVERT(HFP_CALL_STATE_INCOMING, BTHF_CALL_STATE_INCOMING), + CONVERT(HFP_CALL_STATE_WAITING, BTHF_CALL_STATE_WAITING), + CONVERT(HFP_CALL_STATE_IDLE, BTHF_CALL_STATE_IDLE) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sCallState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeNetworkState aIn, bthf_network_state_t& aOut) +{ + static const bthf_network_state_t sNetworkState[] = { + CONVERT(HFP_NETWORK_STATE_NOT_AVAILABLE, BTHF_NETWORK_STATE_NOT_AVAILABLE), + CONVERT(HFP_NETWORK_STATE_AVAILABLE, BTHF_NETWORK_STATE_AVAILABLE) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sNetworkState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNetworkState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeServiceType aIn, bthf_service_type_t& aOut) +{ + static const bthf_service_type_t sServiceType[] = { + CONVERT(HFP_SERVICE_TYPE_HOME, BTHF_SERVICE_TYPE_HOME), + CONVERT(HFP_SERVICE_TYPE_ROAMING, BTHF_SERVICE_TYPE_ROAMING) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sServiceType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sServiceType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeVolumeType aIn, bthf_volume_type_t& aOut) +{ + static const bthf_volume_type_t sVolumeType[] = { + CONVERT(HFP_VOLUME_TYPE_SPEAKER, BTHF_VOLUME_TYPE_SPK), + CONVERT(HFP_VOLUME_TYPE_MICROPHONE, BTHF_VOLUME_TYPE_MIC) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sVolumeType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bthf_audio_state_t aIn, BluetoothHandsfreeAudioState& aOut) +{ + static const BluetoothHandsfreeAudioState sAudioState[] = { + CONVERT(BTHF_AUDIO_STATE_DISCONNECTED, HFP_AUDIO_STATE_DISCONNECTED), + CONVERT(BTHF_AUDIO_STATE_CONNECTING, HFP_AUDIO_STATE_CONNECTING), + CONVERT(BTHF_AUDIO_STATE_CONNECTED, HFP_AUDIO_STATE_CONNECTED), + CONVERT(BTHF_AUDIO_STATE_DISCONNECTING, HFP_AUDIO_STATE_DISCONNECTING) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAudioState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bthf_chld_type_t aIn, BluetoothHandsfreeCallHoldType& aOut) +{ + static const BluetoothHandsfreeCallHoldType sCallHoldType[] = { + CONVERT(BTHF_CHLD_TYPE_RELEASEHELD, HFP_CALL_HOLD_RELEASEHELD), + CONVERT(BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD, + HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD), + CONVERT(BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD, + HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD), + CONVERT(BTHF_CHLD_TYPE_ADDHELDTOCONF, HFP_CALL_HOLD_ADDHELDTOCONF) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sCallHoldType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sCallHoldType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bthf_connection_state_t aIn, BluetoothHandsfreeConnectionState& aOut) +{ + static const BluetoothHandsfreeConnectionState sConnectionState[] = { + CONVERT(BTHF_CONNECTION_STATE_DISCONNECTED, + HFP_CONNECTION_STATE_DISCONNECTED), + CONVERT(BTHF_CONNECTION_STATE_CONNECTING, HFP_CONNECTION_STATE_CONNECTING), + CONVERT(BTHF_CONNECTION_STATE_CONNECTED, HFP_CONNECTION_STATE_CONNECTED), + CONVERT(BTHF_CONNECTION_STATE_SLC_CONNECTED, + HFP_CONNECTION_STATE_SLC_CONNECTED), + CONVERT(BTHF_CONNECTION_STATE_DISCONNECTING, + HFP_CONNECTION_STATE_DISCONNECTING) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sConnectionState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bthf_nrec_t aIn, BluetoothHandsfreeNRECState& aOut) +{ + static const BluetoothHandsfreeNRECState sNRECState[] = { + CONVERT(BTHF_NREC_STOP, HFP_NREC_STOPPED), + CONVERT(BTHF_NREC_START, HFP_NREC_STARTED) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sNRECState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNRECState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bthf_vr_state_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut) +{ + static const BluetoothHandsfreeVoiceRecognitionState + sVoiceRecognitionState[] = { + CONVERT(BTHF_VR_STATE_STOPPED, HFP_VOICE_RECOGNITION_STOPPED), + CONVERT(BTHF_VR_STATE_STARTED, HFP_VOICE_RECOGNITION_STARTED) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sVoiceRecognitionState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sVoiceRecognitionState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(bthf_volume_type_t aIn, BluetoothHandsfreeVolumeType& aOut) +{ + static const BluetoothHandsfreeVolumeType sVolumeType[] = { + CONVERT(BTHF_VOLUME_TYPE_SPK, HFP_VOLUME_TYPE_SPEAKER), + CONVERT(BTHF_VOLUME_TYPE_MIC, HFP_VOLUME_TYPE_MICROPHONE) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sVolumeType[aIn]; + return NS_OK; +} + +inline nsresult +Convert(btav_connection_state_t aIn, BluetoothA2dpConnectionState& aOut) +{ + static const BluetoothA2dpConnectionState sConnectionState[] = { + CONVERT(BTAV_CONNECTION_STATE_DISCONNECTED, + A2DP_CONNECTION_STATE_DISCONNECTED), + CONVERT(BTAV_CONNECTION_STATE_CONNECTING, + A2DP_CONNECTION_STATE_CONNECTING), + CONVERT(BTAV_CONNECTION_STATE_CONNECTED, + A2DP_CONNECTION_STATE_CONNECTED), + CONVERT(BTAV_CONNECTION_STATE_DISCONNECTING, + A2DP_CONNECTION_STATE_DISCONNECTING), + }; + if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sConnectionState[aIn]; + return NS_OK; +} + +inline nsresult +Convert(btav_audio_state_t aIn, BluetoothA2dpAudioState& aOut) +{ + static const BluetoothA2dpAudioState sAudioState[] = { + CONVERT(BTAV_AUDIO_STATE_REMOTE_SUSPEND, A2DP_AUDIO_STATE_REMOTE_SUSPEND), + CONVERT(BTAV_AUDIO_STATE_STOPPED, A2DP_AUDIO_STATE_STOPPED), + CONVERT(BTAV_AUDIO_STATE_STARTED, A2DP_AUDIO_STATE_STARTED), + }; + if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sAudioState[aIn]; + return NS_OK; +} + +#if ANDROID_VERSION >= 18 +inline nsresult +Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut) +{ + aOut.mVerMajor = aIn.version; + aOut.mVerMinor = aIn.sub_ver; + aOut.mManufacturer = aIn.manufacturer; + + return NS_OK; +} + +inline nsresult +Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut) +{ + static const btrc_play_status_t sPlayStatus[] = { + CONVERT(PLAYSTATUS_STOPPED, BTRC_PLAYSTATE_STOPPED), + CONVERT(PLAYSTATUS_PLAYING, BTRC_PLAYSTATE_PLAYING), + CONVERT(PLAYSTATUS_PAUSED, BTRC_PLAYSTATE_PAUSED), + CONVERT(PLAYSTATUS_FWD_SEEK, BTRC_PLAYSTATE_FWD_SEEK), + CONVERT(PLAYSTATUS_REV_SEEK, BTRC_PLAYSTATE_REV_SEEK) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sPlayStatus)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPlayStatus[aIn]; + return NS_OK; +} + +inline nsresult +Convert(enum BluetoothAvrcpPlayerAttribute aIn, btrc_player_attr_t& aOut) +{ + static const btrc_player_attr_t sPlayerAttr[] = { + CONVERT(AVRCP_PLAYER_ATTRIBUTE_EQUALIZER, BTRC_PLAYER_ATTR_EQUALIZER), + CONVERT(AVRCP_PLAYER_ATTRIBUTE_REPEAT, BTRC_PLAYER_ATTR_REPEAT), + CONVERT(AVRCP_PLAYER_ATTRIBUTE_SHUFFLE, BTRC_PLAYER_ATTR_SHUFFLE), + CONVERT(AVRCP_PLAYER_ATTRIBUTE_SCAN, BTRC_PLAYER_ATTR_SCAN) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPlayerAttr[aIn]; + return NS_OK; +} + +inline nsresult +Convert(btrc_player_attr_t aIn, enum BluetoothAvrcpPlayerAttribute& aOut) +{ + static const BluetoothAvrcpPlayerAttribute sPlayerAttr[] = { + CONVERT(0, static_cast(0)), // invalid, [0] required by gcc + CONVERT(BTRC_PLAYER_ATTR_EQUALIZER, AVRCP_PLAYER_ATTRIBUTE_EQUALIZER), + CONVERT(BTRC_PLAYER_ATTR_REPEAT, AVRCP_PLAYER_ATTRIBUTE_REPEAT), + CONVERT(BTRC_PLAYER_ATTR_SHUFFLE, AVRCP_PLAYER_ATTRIBUTE_SHUFFLE), + CONVERT(BTRC_PLAYER_ATTR_SCAN, AVRCP_PLAYER_ATTRIBUTE_SCAN) + }; + if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sPlayerAttr[aIn]; + return NS_OK; +} + +inline nsresult +Convert(enum BluetoothAvrcpStatus aIn, btrc_status_t& aOut) +{ + static const btrc_status_t sStatus[] = { + CONVERT(AVRCP_STATUS_BAD_COMMAND, BTRC_STS_BAD_CMD), + CONVERT(AVRCP_STATUS_BAD_PARAMETER, BTRC_STS_BAD_PARAM), + CONVERT(AVRCP_STATUS_NOT_FOUND, BTRC_STS_NOT_FOUND), + CONVERT(AVRCP_STATUS_INTERNAL_ERROR, BTRC_STS_INTERNAL_ERR), + CONVERT(AVRCP_STATUS_SUCCESS, BTRC_STS_NO_ERROR) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sStatus[aIn]; + return NS_OK; +} + +inline nsresult +Convert(enum BluetoothAvrcpEvent aIn, btrc_event_id_t& aOut) +{ + static const btrc_event_id_t sEventId[] = { + CONVERT(AVRCP_EVENT_PLAY_STATUS_CHANGED, BTRC_EVT_PLAY_STATUS_CHANGED), + CONVERT(AVRCP_EVENT_TRACK_CHANGE, BTRC_EVT_TRACK_CHANGE), + CONVERT(AVRCP_EVENT_TRACK_REACHED_END, BTRC_EVT_TRACK_REACHED_END), + CONVERT(AVRCP_EVENT_TRACK_REACHED_START, BTRC_EVT_TRACK_REACHED_START), + CONVERT(AVRCP_EVENT_PLAY_POS_CHANGED, BTRC_EVT_PLAY_POS_CHANGED), + CONVERT(AVRCP_EVENT_APP_SETTINGS_CHANGED, BTRC_EVT_APP_SETTINGS_CHANGED) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sEventId)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sEventId[aIn]; + return NS_OK; +} + +inline nsresult +Convert(btrc_event_id_t aIn, enum BluetoothAvrcpEvent& aOut) +{ + static const BluetoothAvrcpEvent sEventId[] = { + CONVERT(0, static_cast(0)), // invalid, [0] required by gcc + CONVERT(BTRC_EVT_PLAY_STATUS_CHANGED, AVRCP_EVENT_PLAY_STATUS_CHANGED), + CONVERT(BTRC_EVT_TRACK_CHANGE, AVRCP_EVENT_TRACK_CHANGE), + CONVERT(BTRC_EVT_TRACK_REACHED_END, AVRCP_EVENT_TRACK_REACHED_END), + CONVERT(BTRC_EVT_TRACK_REACHED_START, AVRCP_EVENT_TRACK_REACHED_START), + CONVERT(BTRC_EVT_PLAY_POS_CHANGED, AVRCP_EVENT_PLAY_POS_CHANGED), + CONVERT(6, static_cast(0)), // invalid, [6] required by gcc + CONVERT(7, static_cast(0)), // invalid, [7] required by gcc + CONVERT(BTRC_EVT_APP_SETTINGS_CHANGED, AVRCP_EVENT_APP_SETTINGS_CHANGED) + }; + if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sEventId[aIn]; + return NS_OK; +} + +inline nsresult +Convert(btrc_media_attr_t aIn, enum BluetoothAvrcpMediaAttribute& aOut) +{ + static const BluetoothAvrcpMediaAttribute sEventId[] = { + CONVERT(0, static_cast(0)), // invalid, [0] required by gcc + CONVERT(BTRC_MEDIA_ATTR_TITLE, AVRCP_MEDIA_ATTRIBUTE_TITLE), + CONVERT(BTRC_MEDIA_ATTR_ARTIST, AVRCP_MEDIA_ATTRIBUTE_ARTIST), + CONVERT(BTRC_MEDIA_ATTR_ALBUM, AVRCP_MEDIA_ATTRIBUTE_ALBUM), + CONVERT(BTRC_MEDIA_ATTR_TRACK_NUM, AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM), + CONVERT(BTRC_MEDIA_ATTR_NUM_TRACKS, AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS), + CONVERT(BTRC_MEDIA_ATTR_GENRE, AVRCP_MEDIA_ATTRIBUTE_GENRE), + CONVERT(BTRC_MEDIA_ATTR_PLAYING_TIME, AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME) + }; + if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sEventId[aIn]; + return NS_OK; +} + +inline nsresult +Convert(enum BluetoothAvrcpNotification aIn, btrc_notification_type_t& aOut) +{ + static const btrc_notification_type_t sNotificationType[] = { + CONVERT(AVRCP_NTF_INTERIM, BTRC_NOTIFICATION_TYPE_INTERIM), + CONVERT(AVRCP_NTF_CHANGED, BTRC_NOTIFICATION_TYPE_CHANGED) + }; + if (aIn >= MOZ_ARRAY_LENGTH(sNotificationType)) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sNotificationType[aIn]; + return NS_OK; +} + +nsresult +Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut); + +nsresult +Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut); +#endif // ANDROID_VERSION >= 18 + +#if ANDROID_VERSION >= 19 +inline nsresult +Convert(btrc_remote_features_t aIn, unsigned long& aOut) +{ + /* The input type's name is misleading. The converted value is + * actually a bitmask. + */ + aOut = static_cast(aIn); + return NS_OK; +} +#endif // ANDROID_VERSION >= 19 + +/* |ConvertArray| is a helper for converting arrays. Pass an + * instance of this structure as the first argument to |Convert| + * to convert an array. The output type has to support the array + * subscript operator. + */ +template +struct ConvertArray +{ + ConvertArray(const T* aData, unsigned long aLength) + : mData(aData) + , mLength(aLength) + { } + + const T* mData; + unsigned long mLength; +}; + +/* This implementation of |Convert| converts the elements of an + * array one-by-one. The result data structures must have enough + * memory allocated. + */ +template +inline nsresult +Convert(const ConvertArray& aIn, Tout& aOut) +{ + for (unsigned long i = 0; i < aIn.mLength; ++i) { + nsresult rv = Convert(aIn.mData[i], aOut[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +/* This implementation of |Convert| is a helper that automatically + * allocates enough memory to hold the conversion results. The + * actual conversion is performed by the array-conversion helper + * above. + */ +template +inline nsresult +Convert(const ConvertArray& aIn, nsAutoArrayPtr& aOut) +{ + aOut = new Tout[aIn.mLength]; + Tout* out = aOut.get(); + + return Convert(aIn, out); +} + +/* |ConvertDefault| is a helper function to return the result of a + * conversion or a default value if the conversion fails. + */ +template +inline Tout +ConvertDefault(const Tin& aIn, const Tout& aDefault) +{ + Tout out = aDefault; // assignment silences compiler warning + if (NS_FAILED(Convert(aIn, out))) { + return aDefault; + } + return out; +} + +/* This implementation of |Convert| is a helper for copying the + * input value into the output value. It handles all cases that + * need no conversion. + */ +template +inline nsresult +Convert(const T& aIn, T& aOut) +{ + aOut = aIn; + + return NS_OK; +} + +nsresult +Convert(const bt_property_t& aIn, BluetoothProperty& aOut); + +// +// Result handling +// + +template +class BluetoothHALInterfaceRunnable0 : public nsRunnable +{ +public: + BluetoothHALInterfaceRunnable0(Obj* aObj, Res (Obj::*aMethod)()) + : mObj(aObj) + , mMethod(aMethod) + { + MOZ_ASSERT(mObj); + MOZ_ASSERT(mMethod); + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + ((*mObj).*mMethod)(); + return NS_OK; + } + +private: + nsRefPtr mObj; + void (Obj::*mMethod)(); +}; + +template +class BluetoothHALInterfaceRunnable1 : public nsRunnable +{ +public: + BluetoothHALInterfaceRunnable1(Obj* aObj, Res (Obj::*aMethod)(Arg1), + const Arg1& aArg1) + : mObj(aObj) + , mMethod(aMethod) + , mArg1(aArg1) + { + MOZ_ASSERT(mObj); + MOZ_ASSERT(mMethod); + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + ((*mObj).*mMethod)(mArg1); + return NS_OK; + } + +private: + nsRefPtr mObj; + Res (Obj::*mMethod)(Arg1); + Tin1 mArg1; +}; + +template +class BluetoothHALInterfaceRunnable3 : public nsRunnable +{ +public: + BluetoothHALInterfaceRunnable3(Obj* aObj, + Res (Obj::*aMethod)(Arg1, Arg2, Arg3), + const Arg1& aArg1, const Arg2& aArg2, + const Arg3& aArg3) + : mObj(aObj) + , mMethod(aMethod) + , mArg1(aArg1) + , mArg2(aArg2) + , mArg3(aArg3) + { + MOZ_ASSERT(mObj); + MOZ_ASSERT(mMethod); + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + ((*mObj).*mMethod)(mArg1, mArg2, mArg3); + return NS_OK; + } + +private: + nsRefPtr mObj; + Res (Obj::*mMethod)(Arg1, Arg2, Arg3); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; +}; + +// +// Notification handling +// + +template +class BluetoothNotificationHALRunnable0 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable0 SelfType; + + static already_AddRefed Create(Res (ObjectType::*aMethod)()) + { + nsRefPtr runnable(new SelfType(aMethod)); + + return runnable.forget(); + } + + static void + Dispatch(Res (ObjectType::*aMethod)()) + { + nsRefPtr runnable = Create(aMethod); + + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable0::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable0(Res (ObjectType::*aMethod)()) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + Res (ObjectType::*mMethod)(); +}; + +template +class BluetoothNotificationHALRunnable1 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable1 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1), const T1& aIn1) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1), const T1& aIn1) + { + nsRefPtr runnable = Create(aMethod, aIn1); + + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable1::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable1(Res (ObjectType::*aMethod)(Arg1)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1) + { + nsresult rv = Convert(aIn1, mArg1); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1); + Tin1 mArg1; +}; + +template +class BluetoothNotificationHALRunnable2 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable2 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2), const T1& aIn1, const T2& aIn2) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2), + const T1& aIn1, const T2& aIn2) + { + nsRefPtr runnable = Create(aMethod, aIn1, aIn2); + + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable2::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable2( + Res (ObjectType::*aMethod)(Arg1, Arg2)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1, const T2& aIn2) + { + nsresult rv = Convert(aIn1, mArg1); + if (NS_FAILED(rv)) { + return rv; + } + rv = Convert(aIn2, mArg2); + if (NS_FAILED(rv)) { + return rv; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2); + Tin1 mArg1; + Tin2 mArg2; +}; + +template +class BluetoothNotificationHALRunnable3 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable3 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), + const T1& aIn1, const T2& aIn2, const T3& aIn3) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), + const T1& aIn1, const T2& aIn2, const T3& aIn3) + { + nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3); + + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable3::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable3( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3) + { + 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; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; +}; + +template +class BluetoothNotificationHALRunnable4 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable4 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), + const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), + const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4) + { + nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3, aIn4); + + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable4::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_OVERRIDE + { + MOZ_ASSERT(NS_IsMainThread()); + + ObjectType* obj = ObjectWrapper::GetInstance(); + + if (!obj) { + BT_WARNING("Notification handler not initialized"); + } else { + ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable4( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1, const T2& aIn2, + const T3& aIn3, const T4& aIn4) + { + 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; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; +}; + +template +class BluetoothNotificationHALRunnable5 : public nsRunnable +{ +public: + typedef typename ObjectWrapper::ObjectType ObjectType; + typedef BluetoothNotificationHALRunnable5 SelfType; + + template + static already_AddRefed Create( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5) + { + nsRefPtr runnable(new SelfType(aMethod)); + + if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5))) { + return nullptr; + } + return runnable.forget(); + } + + template + static void + Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), + const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5) + { + nsRefPtr runnable = Create(aMethod, + aIn1, aIn2, aIn3, aIn4, aIn5); + if (!runnable) { + BT_WARNING("BluetoothNotificationHALRunnable5::Create failed"); + return; + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + } + + NS_METHOD + Run() MOZ_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); + } + return NS_OK; + } + +private: + BluetoothNotificationHALRunnable5( + Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5)) + : mMethod(aMethod) + { + MOZ_ASSERT(mMethod); + } + + template + nsresult + ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3, + const T4& aIn4, const T5& aIn5) + { + 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; + } + return NS_OK; + } + + Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5); + Tin1 mArg1; + Tin2 mArg2; + Tin3 mArg3; + Tin4 mArg4; + Tin5 mArg5; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff --git a/dom/bluetooth/bluedroid/BluetoothHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothHALInterface.cpp index 43a6fab5dbd8..e7527181e2e7 100644 --- a/dom/bluetooth/bluedroid/BluetoothHALInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothHALInterface.cpp @@ -5,25 +5,11 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BluetoothHALInterface.h" -#include -#include -#include -#include "base/message_loop.h" -#include "nsAutoPtr.h" -#include "nsThreadUtils.h" -#include "nsXULAppAPI.h" - -#if MOZ_IS_GCC && MOZ_GCC_VERSION_AT_LEAST(4, 7, 0) -/* use designated array initializers if supported */ -#define CONVERT(in_, out_) \ - [in_] = out_ -#else -/* otherwise init array element by position */ -#define CONVERT(in_, out_) \ - out_ -#endif - -#define MAX_UUID_SIZE 16 +#include "BluetoothHALHelpers.h" +#include "BluetoothA2dpHALInterface.h" +#include "BluetoothAvrcpHALInterface.h" +#include "BluetoothHandsfreeHALInterface.h" +#include "BluetoothSocketHALInterface.h" BEGIN_BLUETOOTH_NAMESPACE @@ -31,1656 +17,6 @@ template struct interface_traits { }; -// -// Conversion -// - -static nsresult -Convert(bt_status_t aIn, BluetoothStatus& aOut) -{ - static const BluetoothStatus sStatus[] = { - CONVERT(BT_STATUS_SUCCESS, STATUS_SUCCESS), - CONVERT(BT_STATUS_FAIL, STATUS_FAIL), - CONVERT(BT_STATUS_NOT_READY, STATUS_NOT_READY), - CONVERT(BT_STATUS_NOMEM, STATUS_NOMEM), - CONVERT(BT_STATUS_BUSY, STATUS_BUSY), - CONVERT(BT_STATUS_DONE, STATUS_DONE), - CONVERT(BT_STATUS_UNSUPPORTED, STATUS_UNSUPPORTED), - CONVERT(BT_STATUS_PARM_INVALID, STATUS_PARM_INVALID), - CONVERT(BT_STATUS_UNHANDLED, STATUS_UNHANDLED), - CONVERT(BT_STATUS_AUTH_FAILURE, STATUS_AUTH_FAILURE), - CONVERT(BT_STATUS_RMT_DEV_DOWN, STATUS_RMT_DEV_DOWN) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sStatus[aIn]; - return NS_OK; -} - -static nsresult -Convert(int aIn, BluetoothStatus& aOut) -{ - return Convert(static_cast(aIn), aOut); -} - -static nsresult -Convert(const nsAString& aIn, bt_property_type_t& aOut) -{ - if (aIn.EqualsLiteral("Name")) { - aOut = BT_PROPERTY_BDNAME; - } else if (aIn.EqualsLiteral("Discoverable")) { - aOut = BT_PROPERTY_ADAPTER_SCAN_MODE; - } else if (aIn.EqualsLiteral("DiscoverableTimeout")) { - aOut = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT; - } else { - BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aIn).get()); - return NS_ERROR_ILLEGAL_VALUE; - } - return NS_OK; -} - -static nsresult -Convert(bool aIn, bt_scan_mode_t& aOut) -{ - static const bt_scan_mode_t sScanMode[] = { - CONVERT(false, BT_SCAN_MODE_CONNECTABLE), - CONVERT(true, BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sScanMode[aIn]; - return NS_OK; -} - - -static nsresult -Convert(bt_scan_mode_t aIn, BluetoothScanMode& aOut) -{ - static const BluetoothScanMode sScanMode[] = { - CONVERT(BT_SCAN_MODE_NONE, SCAN_MODE_NONE), - CONVERT(BT_SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE), - CONVERT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE, - SCAN_MODE_CONNECTABLE_DISCOVERABLE) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sScanMode[aIn]; - return NS_OK; -} - -struct ConvertNamedValue -{ - ConvertNamedValue(const BluetoothNamedValue& aNamedValue) - : mNamedValue(aNamedValue) - { } - - const BluetoothNamedValue& mNamedValue; - - // temporary fields - nsCString mStringValue; - bt_scan_mode_t mScanMode; -}; - -static nsresult -Convert(ConvertNamedValue& aIn, bt_property_t& aOut) -{ - nsresult rv = Convert(aIn.mNamedValue.name(), aOut.type); - if (NS_FAILED(rv)) { - return rv; - } - - if (aIn.mNamedValue.value().type() == BluetoothValue::Tuint32_t) { - // Set discoverable timeout - aOut.val = - reinterpret_cast(aIn.mNamedValue.value().get_uint32_t()); - } else if (aIn.mNamedValue.value().type() == BluetoothValue::TnsString) { - // Set name - aIn.mStringValue = - NS_ConvertUTF16toUTF8(aIn.mNamedValue.value().get_nsString()); - aOut.val = - const_cast(static_cast(aIn.mStringValue.get())); - aOut.len = strlen(static_cast(aOut.val)); - } else if (aIn.mNamedValue.value().type() == BluetoothValue::Tbool) { - // Set scan mode - rv = Convert(aIn.mNamedValue.value().get_bool(), aIn.mScanMode); - if (NS_FAILED(rv)) { - return rv; - } - aOut.val = &aIn.mScanMode; - aOut.len = sizeof(aIn.mScanMode); - } else { - BT_LOGR("Invalid property value type"); - return NS_ERROR_ILLEGAL_VALUE; - } - - return NS_OK; -} - -static nsresult -Convert(const nsAString& aIn, bt_bdaddr_t& aOut) -{ - NS_ConvertUTF16toUTF8 bdAddressUTF8(aIn); - const char* str = bdAddressUTF8.get(); - - for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aOut.address); ++i, ++str) { - aOut.address[i] = - static_cast(strtoul(str, const_cast(&str), 16)); - } - - return NS_OK; -} - -static nsresult -Convert(const nsAString& aIn, bt_ssp_variant_t& aOut) -{ - if (aIn.EqualsLiteral("PasskeyConfirmation")) { - aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION; - } else if (aIn.EqualsLiteral("PasskeyEntry")) { - aOut = BT_SSP_VARIANT_PASSKEY_ENTRY; - } else if (aIn.EqualsLiteral("Consent")) { - aOut = BT_SSP_VARIANT_CONSENT; - } else if (aIn.EqualsLiteral("PasskeyNotification")) { - aOut = BT_SSP_VARIANT_PASSKEY_NOTIFICATION; - } else { - BT_LOGR("Invalid SSP variant name: %s", NS_ConvertUTF16toUTF8(aIn).get()); - aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning - return NS_ERROR_ILLEGAL_VALUE; - } - return NS_OK; -} - -static nsresult -Convert(const bt_ssp_variant_t& aIn, nsAString& aOut) -{ - static const char * const sSspVariant[] = { - CONVERT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION, "PasskeyConfirmation"), - CONVERT(BT_SSP_VARIANT_PASSKEY_ENTRY, "PasskeyEntry"), - CONVERT(BT_SSP_VARIANT_CONSENT, "Consent"), - CONVERT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION, "PasskeyNotification") - }; - if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = NS_ConvertUTF8toUTF16(sSspVariant[aIn]); - return NS_OK; -} - -static nsresult -Convert(const bool& aIn, uint8_t& aOut) -{ - // casting converts true/false to either 1 or 0 - aOut = static_cast(aIn); - return NS_OK; -} - -static nsresult -Convert(const uint8_t aIn[16], bt_uuid_t& aOut) -{ - if (sizeof(aOut.uu) != 16) { - return NS_ERROR_ILLEGAL_VALUE; - } - - memcpy(aOut.uu, aIn, sizeof(aOut.uu)); - - return NS_OK; -} - -static nsresult -Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut) -{ - if (sizeof(aIn.uu) != sizeof(aOut.mUuid)) { - return NS_ERROR_ILLEGAL_VALUE; - } - - memcpy(aOut.mUuid, aIn.uu, sizeof(aOut.mUuid)); - - return NS_OK; -} - -static nsresult -Convert(const nsAString& aIn, bt_pin_code_t& aOut) -{ - if (aIn.Length() > MOZ_ARRAY_LENGTH(aOut.pin)) { - return NS_ERROR_ILLEGAL_VALUE; - } - - NS_ConvertUTF16toUTF8 pinCodeUTF8(aIn); - const char* str = pinCodeUTF8.get(); - - nsAString::size_type i; - - // Fill pin into aOut - for (i = 0; i < aIn.Length(); ++i, ++str) { - aOut.pin[i] = static_cast(*str); - } - - // Clear remaining bytes in aOut - size_t ntrailing = - (MOZ_ARRAY_LENGTH(aOut.pin) - aIn.Length()) * sizeof(aOut.pin[0]); - memset(aOut.pin + aIn.Length(), 0, ntrailing); - - return NS_OK; -} - -static nsresult -Convert(const bt_bdaddr_t& aIn, nsAString& aOut) -{ - char str[BLUETOOTH_ADDRESS_LENGTH + 1]; - - int res = snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", - static_cast(aIn.address[0]), - static_cast(aIn.address[1]), - static_cast(aIn.address[2]), - static_cast(aIn.address[3]), - static_cast(aIn.address[4]), - static_cast(aIn.address[5])); - if (res < 0) { - return NS_ERROR_ILLEGAL_VALUE; - } else if ((size_t)res >= sizeof(str)) { - return NS_ERROR_OUT_OF_MEMORY; /* string buffer too small */ - } - - aOut = NS_ConvertUTF8toUTF16(str); - - return NS_OK; -} - -static nsresult -Convert(const bt_bdaddr_t* aIn, nsAString& aOut) -{ - if (!aIn) { - aOut.AssignLiteral(BLUETOOTH_ADDRESS_NONE); - return NS_OK; - } - return Convert(*aIn, aOut); -} - -static nsresult -Convert(bt_state_t aIn, bool& aOut) -{ - static const bool sState[] = { - CONVERT(BT_STATE_OFF, false), - CONVERT(BT_STATE_ON, true) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sState[aIn]; - return NS_OK; -} - -static nsresult -Convert(bt_property_type_t aIn, BluetoothPropertyType& aOut) -{ - static const BluetoothPropertyType sPropertyType[] = { - CONVERT(0, static_cast(0)), // invalid, required by gcc - CONVERT(BT_PROPERTY_BDNAME, PROPERTY_BDNAME), - CONVERT(BT_PROPERTY_BDADDR, PROPERTY_BDADDR), - CONVERT(BT_PROPERTY_UUIDS, PROPERTY_UUIDS), - CONVERT(BT_PROPERTY_CLASS_OF_DEVICE, PROPERTY_CLASS_OF_DEVICE), - CONVERT(BT_PROPERTY_TYPE_OF_DEVICE, PROPERTY_TYPE_OF_DEVICE), - CONVERT(BT_PROPERTY_SERVICE_RECORD, PROPERTY_SERVICE_RECORD), - CONVERT(BT_PROPERTY_ADAPTER_SCAN_MODE, PROPERTY_ADAPTER_SCAN_MODE), - CONVERT(BT_PROPERTY_ADAPTER_BONDED_DEVICES, - PROPERTY_ADAPTER_BONDED_DEVICES), - CONVERT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, - PROPERTY_ADAPTER_DISCOVERY_TIMEOUT), - CONVERT(BT_PROPERTY_REMOTE_FRIENDLY_NAME, PROPERTY_REMOTE_FRIENDLY_NAME), - CONVERT(BT_PROPERTY_REMOTE_RSSI, PROPERTY_REMOTE_RSSI), - CONVERT(BT_PROPERTY_REMOTE_VERSION_INFO,PROPERTY_REMOTE_VERSION_INFO) - }; - if (aIn == BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP) { - /* This case is handled separately to not populate - * |sPropertyType| with empty entries. */ - aOut = PROPERTY_REMOTE_DEVICE_TIMESTAMP; - return NS_OK; - } - if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPropertyType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sPropertyType[aIn]; - return NS_OK; -} - -static nsresult -Convert(bt_discovery_state_t aIn, bool& aOut) -{ - static const bool sDiscoveryState[] = { - CONVERT(BT_DISCOVERY_STOPPED, false), - CONVERT(BT_DISCOVERY_STARTED, true) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sDiscoveryState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sDiscoveryState[aIn]; - return NS_OK; -} - -static nsresult -Convert(const char* aIn, nsACString& aOut) -{ - aOut.Assign(aIn); - - return NS_OK; -} - -static nsresult -Convert(const char* aIn, nsAString& aOut) -{ - aOut = NS_ConvertUTF8toUTF16(aIn); - - return NS_OK; -} - -static nsresult -Convert(const bt_bdname_t& aIn, nsAString& aOut) -{ - return Convert(reinterpret_cast(aIn.name), aOut); -} - -static nsresult -Convert(const bt_bdname_t* aIn, nsAString& aOut) -{ - if (!aIn) { - aOut.Truncate(); - return NS_OK; - } - return Convert(*aIn, aOut); -} - -static nsresult -Convert(bt_bond_state_t aIn, BluetoothBondState& aOut) -{ - static const BluetoothBondState sBondState[] = { - CONVERT(BT_BOND_STATE_NONE, BOND_STATE_NONE), - CONVERT(BT_BOND_STATE_BONDING, BOND_STATE_BONDING), - CONVERT(BT_BOND_STATE_BONDED, BOND_STATE_BONDED) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sBondState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sBondState[aIn]; - return NS_OK; -} - -static nsresult -Convert(bt_acl_state_t aIn, bool& aOut) -{ - static const bool sAclState[] = { - CONVERT(BT_ACL_STATE_CONNECTED, true), - CONVERT(BT_ACL_STATE_DISCONNECTED, false) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sAclState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sAclState[aIn]; - return NS_OK; -} - -static nsresult -Convert(bt_device_type_t aIn, BluetoothDeviceType& aOut) -{ - static const BluetoothDeviceType sDeviceType[] = { - CONVERT(0, static_cast(0)), // invalid, required by gcc - CONVERT(BT_DEVICE_DEVTYPE_BREDR, DEVICE_TYPE_BREDR), - CONVERT(BT_DEVICE_DEVTYPE_BLE, DEVICE_TYPE_BLE), - CONVERT(BT_DEVICE_DEVTYPE_DUAL, DEVICE_TYPE_DUAL) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sDeviceType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sDeviceType[aIn]; - return NS_OK; -} - -static nsresult -Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut) -{ - nsresult rv = Convert(aIn.uuid, aOut.mUuid); - if (NS_FAILED(rv)) { - return rv; - } - - aOut.mChannel = aIn.channel; - - MOZ_ASSERT(sizeof(aIn.name) == sizeof(aOut.mName)); - memcpy(aOut.mName, aIn.name, sizeof(aOut.mName)); - - return NS_OK; -} - -static nsresult -Convert(BluetoothSocketType aIn, btsock_type_t& aOut) -{ - // FIXME: Array member [0] is currently invalid, but required - // by gcc. Start values in |BluetoothSocketType| at index - // 0 to fix this problem. - static const btsock_type_t sSocketType[] = { - CONVERT(0, static_cast(0)), // invalid, [0] required by gcc - CONVERT(BluetoothSocketType::RFCOMM, BTSOCK_RFCOMM), - CONVERT(BluetoothSocketType::SCO, BTSOCK_SCO), - CONVERT(BluetoothSocketType::L2CAP, BTSOCK_L2CAP), - // EL2CAP is not supported by Bluedroid - }; - if (aIn == BluetoothSocketType::EL2CAP || - aIn >= MOZ_ARRAY_LENGTH(sSocketType) || !sSocketType[aIn]) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sSocketType[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeAtResponse aIn, bthf_at_response_t& aOut) -{ - static const bthf_at_response_t sAtResponse[] = { - CONVERT(HFP_AT_RESPONSE_ERROR, BTHF_AT_RESPONSE_ERROR), - CONVERT(HFP_AT_RESPONSE_OK, BTHF_AT_RESPONSE_OK) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sAtResponse)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sAtResponse[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeCallAddressType aIn, bthf_call_addrtype_t& aOut) -{ - static const bthf_call_addrtype_t sCallAddressType[] = { - CONVERT(HFP_CALL_ADDRESS_TYPE_UNKNOWN, BTHF_CALL_ADDRTYPE_UNKNOWN), - CONVERT(HFP_CALL_ADDRESS_TYPE_INTERNATIONAL, - BTHF_CALL_ADDRTYPE_INTERNATIONAL) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sCallAddressType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sCallAddressType[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeCallDirection aIn, bthf_call_direction_t& aOut) -{ - static const bthf_call_direction_t sCallDirection[] = { - CONVERT(HFP_CALL_DIRECTION_OUTGOING, BTHF_CALL_DIRECTION_OUTGOING), - CONVERT(HFP_CALL_DIRECTION_INCOMING, BTHF_CALL_DIRECTION_INCOMING) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sCallDirection)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sCallDirection[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeCallMode aIn, bthf_call_mode_t& aOut) -{ - static const bthf_call_mode_t sCallMode[] = { - CONVERT(HFP_CALL_MODE_VOICE, BTHF_CALL_TYPE_VOICE), - CONVERT(HFP_CALL_MODE_DATA, BTHF_CALL_TYPE_DATA), - CONVERT(HFP_CALL_MODE_FAX, BTHF_CALL_TYPE_FAX) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sCallMode)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sCallMode[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeCallMptyType aIn, bthf_call_mpty_type_t& aOut) -{ - static const bthf_call_mpty_type_t sCallMptyType[] = { - CONVERT(HFP_CALL_MPTY_TYPE_SINGLE, BTHF_CALL_MPTY_TYPE_SINGLE), - CONVERT(HFP_CALL_MPTY_TYPE_MULTI, BTHF_CALL_MPTY_TYPE_MULTI) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sCallMptyType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sCallMptyType[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeCallState aIn, bthf_call_state_t& aOut) -{ - static const bthf_call_state_t sCallState[] = { - CONVERT(HFP_CALL_STATE_ACTIVE, BTHF_CALL_STATE_ACTIVE), - CONVERT(HFP_CALL_STATE_HELD, BTHF_CALL_STATE_HELD), - CONVERT(HFP_CALL_STATE_DIALING, BTHF_CALL_STATE_DIALING), - CONVERT(HFP_CALL_STATE_ALERTING, BTHF_CALL_STATE_ALERTING), - CONVERT(HFP_CALL_STATE_INCOMING, BTHF_CALL_STATE_INCOMING), - CONVERT(HFP_CALL_STATE_WAITING, BTHF_CALL_STATE_WAITING), - CONVERT(HFP_CALL_STATE_IDLE, BTHF_CALL_STATE_IDLE) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sCallState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sCallState[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeNetworkState aIn, bthf_network_state_t& aOut) -{ - static const bthf_network_state_t sNetworkState[] = { - CONVERT(HFP_NETWORK_STATE_NOT_AVAILABLE, BTHF_NETWORK_STATE_NOT_AVAILABLE), - CONVERT(HFP_NETWORK_STATE_AVAILABLE, BTHF_NETWORK_STATE_AVAILABLE) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sNetworkState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sNetworkState[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeServiceType aIn, bthf_service_type_t& aOut) -{ - static const bthf_service_type_t sServiceType[] = { - CONVERT(HFP_SERVICE_TYPE_HOME, BTHF_SERVICE_TYPE_HOME), - CONVERT(HFP_SERVICE_TYPE_ROAMING, BTHF_SERVICE_TYPE_ROAMING) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sServiceType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sServiceType[aIn]; - return NS_OK; -} - -static nsresult -Convert(BluetoothHandsfreeVolumeType aIn, bthf_volume_type_t& aOut) -{ - static const bthf_volume_type_t sVolumeType[] = { - CONVERT(HFP_VOLUME_TYPE_SPEAKER, BTHF_VOLUME_TYPE_SPK), - CONVERT(HFP_VOLUME_TYPE_MICROPHONE, BTHF_VOLUME_TYPE_MIC) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sVolumeType[aIn]; - return NS_OK; -} - -static nsresult -Convert(bthf_audio_state_t aIn, BluetoothHandsfreeAudioState& aOut) -{ - static const BluetoothHandsfreeAudioState sAudioState[] = { - CONVERT(BTHF_AUDIO_STATE_DISCONNECTED, HFP_AUDIO_STATE_DISCONNECTED), - CONVERT(BTHF_AUDIO_STATE_CONNECTING, HFP_AUDIO_STATE_CONNECTING), - CONVERT(BTHF_AUDIO_STATE_CONNECTED, HFP_AUDIO_STATE_CONNECTED), - CONVERT(BTHF_AUDIO_STATE_DISCONNECTING, HFP_AUDIO_STATE_DISCONNECTING) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sAudioState[aIn]; - return NS_OK; -} - -static nsresult -Convert(bthf_chld_type_t aIn, BluetoothHandsfreeCallHoldType& aOut) -{ - static const BluetoothHandsfreeCallHoldType sCallHoldType[] = { - CONVERT(BTHF_CHLD_TYPE_RELEASEHELD, HFP_CALL_HOLD_RELEASEHELD), - CONVERT(BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD, - HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD), - CONVERT(BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD, - HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD), - CONVERT(BTHF_CHLD_TYPE_ADDHELDTOCONF, HFP_CALL_HOLD_ADDHELDTOCONF) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sCallHoldType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sCallHoldType[aIn]; - return NS_OK; -} - -static nsresult -Convert(bthf_connection_state_t aIn, BluetoothHandsfreeConnectionState& aOut) -{ - static const BluetoothHandsfreeConnectionState sConnectionState[] = { - CONVERT(BTHF_CONNECTION_STATE_DISCONNECTED, - HFP_CONNECTION_STATE_DISCONNECTED), - CONVERT(BTHF_CONNECTION_STATE_CONNECTING, HFP_CONNECTION_STATE_CONNECTING), - CONVERT(BTHF_CONNECTION_STATE_CONNECTED, HFP_CONNECTION_STATE_CONNECTED), - CONVERT(BTHF_CONNECTION_STATE_SLC_CONNECTED, - HFP_CONNECTION_STATE_SLC_CONNECTED), - CONVERT(BTHF_CONNECTION_STATE_DISCONNECTING, - HFP_CONNECTION_STATE_DISCONNECTING) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sConnectionState[aIn]; - return NS_OK; -} - -static nsresult -Convert(bthf_nrec_t aIn, BluetoothHandsfreeNRECState& aOut) -{ - static const BluetoothHandsfreeNRECState sNRECState[] = { - CONVERT(BTHF_NREC_STOP, HFP_NREC_STOPPED), - CONVERT(BTHF_NREC_START, HFP_NREC_STARTED) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sNRECState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sNRECState[aIn]; - return NS_OK; -} - -static nsresult -Convert(bthf_vr_state_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut) -{ - static const BluetoothHandsfreeVoiceRecognitionState - sVoiceRecognitionState[] = { - CONVERT(BTHF_VR_STATE_STOPPED, HFP_VOICE_RECOGNITION_STOPPED), - CONVERT(BTHF_VR_STATE_STARTED, HFP_VOICE_RECOGNITION_STARTED) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sVoiceRecognitionState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sVoiceRecognitionState[aIn]; - return NS_OK; -} - -static nsresult -Convert(bthf_volume_type_t aIn, BluetoothHandsfreeVolumeType& aOut) -{ - static const BluetoothHandsfreeVolumeType sVolumeType[] = { - CONVERT(BTHF_VOLUME_TYPE_SPK, HFP_VOLUME_TYPE_SPEAKER), - CONVERT(BTHF_VOLUME_TYPE_MIC, HFP_VOLUME_TYPE_MICROPHONE) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sVolumeType[aIn]; - return NS_OK; -} - -static nsresult -Convert(btav_connection_state_t aIn, BluetoothA2dpConnectionState& aOut) -{ - static const BluetoothA2dpConnectionState sConnectionState[] = { - CONVERT(BTAV_CONNECTION_STATE_DISCONNECTED, - A2DP_CONNECTION_STATE_DISCONNECTED), - CONVERT(BTAV_CONNECTION_STATE_CONNECTING, - A2DP_CONNECTION_STATE_CONNECTING), - CONVERT(BTAV_CONNECTION_STATE_CONNECTED, - A2DP_CONNECTION_STATE_CONNECTED), - CONVERT(BTAV_CONNECTION_STATE_DISCONNECTING, - A2DP_CONNECTION_STATE_DISCONNECTING), - }; - if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sConnectionState[aIn]; - return NS_OK; -} - -static nsresult -Convert(btav_audio_state_t aIn, BluetoothA2dpAudioState& aOut) -{ - static const BluetoothA2dpAudioState sAudioState[] = { - CONVERT(BTAV_AUDIO_STATE_REMOTE_SUSPEND, A2DP_AUDIO_STATE_REMOTE_SUSPEND), - CONVERT(BTAV_AUDIO_STATE_STOPPED, A2DP_AUDIO_STATE_STOPPED), - CONVERT(BTAV_AUDIO_STATE_STARTED, A2DP_AUDIO_STATE_STARTED), - }; - if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sAudioState[aIn]; - return NS_OK; -} - -#if ANDROID_VERSION >= 18 -static nsresult -Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut) -{ - aOut.mVerMajor = aIn.version; - aOut.mVerMinor = aIn.sub_ver; - aOut.mManufacturer = aIn.manufacturer; - - return NS_OK; -} - -static nsresult -Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut) -{ - static const btrc_play_status_t sPlayStatus[] = { - CONVERT(PLAYSTATUS_STOPPED, BTRC_PLAYSTATE_STOPPED), - CONVERT(PLAYSTATUS_PLAYING, BTRC_PLAYSTATE_PLAYING), - CONVERT(PLAYSTATUS_PAUSED, BTRC_PLAYSTATE_PAUSED), - CONVERT(PLAYSTATUS_FWD_SEEK, BTRC_PLAYSTATE_FWD_SEEK), - CONVERT(PLAYSTATUS_REV_SEEK, BTRC_PLAYSTATE_REV_SEEK) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sPlayStatus)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sPlayStatus[aIn]; - return NS_OK; -} - -static nsresult -Convert(enum BluetoothAvrcpPlayerAttribute aIn, btrc_player_attr_t& aOut) -{ - static const btrc_player_attr_t sPlayerAttr[] = { - CONVERT(AVRCP_PLAYER_ATTRIBUTE_EQUALIZER, BTRC_PLAYER_ATTR_EQUALIZER), - CONVERT(AVRCP_PLAYER_ATTRIBUTE_REPEAT, BTRC_PLAYER_ATTR_REPEAT), - CONVERT(AVRCP_PLAYER_ATTRIBUTE_SHUFFLE, BTRC_PLAYER_ATTR_SHUFFLE), - CONVERT(AVRCP_PLAYER_ATTRIBUTE_SCAN, BTRC_PLAYER_ATTR_SCAN) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sPlayerAttr[aIn]; - return NS_OK; -} - -static nsresult -Convert(btrc_player_attr_t aIn, enum BluetoothAvrcpPlayerAttribute& aOut) -{ - static const BluetoothAvrcpPlayerAttribute sPlayerAttr[] = { - CONVERT(0, static_cast(0)), // invalid, [0] required by gcc - CONVERT(BTRC_PLAYER_ATTR_EQUALIZER, AVRCP_PLAYER_ATTRIBUTE_EQUALIZER), - CONVERT(BTRC_PLAYER_ATTR_REPEAT, AVRCP_PLAYER_ATTRIBUTE_REPEAT), - CONVERT(BTRC_PLAYER_ATTR_SHUFFLE, AVRCP_PLAYER_ATTRIBUTE_SHUFFLE), - CONVERT(BTRC_PLAYER_ATTR_SCAN, AVRCP_PLAYER_ATTRIBUTE_SCAN) - }; - if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sPlayerAttr[aIn]; - return NS_OK; -} - -static nsresult -Convert(enum BluetoothAvrcpStatus aIn, btrc_status_t& aOut) -{ - static const btrc_status_t sStatus[] = { - CONVERT(AVRCP_STATUS_BAD_COMMAND, BTRC_STS_BAD_CMD), - CONVERT(AVRCP_STATUS_BAD_PARAMETER, BTRC_STS_BAD_PARAM), - CONVERT(AVRCP_STATUS_NOT_FOUND, BTRC_STS_NOT_FOUND), - CONVERT(AVRCP_STATUS_INTERNAL_ERROR, BTRC_STS_INTERNAL_ERR), - CONVERT(AVRCP_STATUS_SUCCESS, BTRC_STS_NO_ERROR) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sStatus[aIn]; - return NS_OK; -} - -static nsresult -Convert(enum BluetoothAvrcpEvent aIn, btrc_event_id_t& aOut) -{ - static const btrc_event_id_t sEventId[] = { - CONVERT(AVRCP_EVENT_PLAY_STATUS_CHANGED, BTRC_EVT_PLAY_STATUS_CHANGED), - CONVERT(AVRCP_EVENT_TRACK_CHANGE, BTRC_EVT_TRACK_CHANGE), - CONVERT(AVRCP_EVENT_TRACK_REACHED_END, BTRC_EVT_TRACK_REACHED_END), - CONVERT(AVRCP_EVENT_TRACK_REACHED_START, BTRC_EVT_TRACK_REACHED_START), - CONVERT(AVRCP_EVENT_PLAY_POS_CHANGED, BTRC_EVT_PLAY_POS_CHANGED), - CONVERT(AVRCP_EVENT_APP_SETTINGS_CHANGED, BTRC_EVT_APP_SETTINGS_CHANGED) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sEventId)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sEventId[aIn]; - return NS_OK; -} - -static nsresult -Convert(btrc_event_id_t aIn, enum BluetoothAvrcpEvent& aOut) -{ - static const BluetoothAvrcpEvent sEventId[] = { - CONVERT(0, static_cast(0)), // invalid, [0] required by gcc - CONVERT(BTRC_EVT_PLAY_STATUS_CHANGED, AVRCP_EVENT_PLAY_STATUS_CHANGED), - CONVERT(BTRC_EVT_TRACK_CHANGE, AVRCP_EVENT_TRACK_CHANGE), - CONVERT(BTRC_EVT_TRACK_REACHED_END, AVRCP_EVENT_TRACK_REACHED_END), - CONVERT(BTRC_EVT_TRACK_REACHED_START, AVRCP_EVENT_TRACK_REACHED_START), - CONVERT(BTRC_EVT_PLAY_POS_CHANGED, AVRCP_EVENT_PLAY_POS_CHANGED), - CONVERT(6, static_cast(0)), // invalid, [6] required by gcc - CONVERT(7, static_cast(0)), // invalid, [7] required by gcc - CONVERT(BTRC_EVT_APP_SETTINGS_CHANGED, AVRCP_EVENT_APP_SETTINGS_CHANGED) - }; - if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sEventId[aIn]; - return NS_OK; -} - -static nsresult -Convert(btrc_media_attr_t aIn, enum BluetoothAvrcpMediaAttribute& aOut) -{ - static const BluetoothAvrcpMediaAttribute sEventId[] = { - CONVERT(0, static_cast(0)), // invalid, [0] required by gcc - CONVERT(BTRC_MEDIA_ATTR_TITLE, AVRCP_MEDIA_ATTRIBUTE_TITLE), - CONVERT(BTRC_MEDIA_ATTR_ARTIST, AVRCP_MEDIA_ATTRIBUTE_ARTIST), - CONVERT(BTRC_MEDIA_ATTR_ALBUM, AVRCP_MEDIA_ATTRIBUTE_ALBUM), - CONVERT(BTRC_MEDIA_ATTR_TRACK_NUM, AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM), - CONVERT(BTRC_MEDIA_ATTR_NUM_TRACKS, AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS), - CONVERT(BTRC_MEDIA_ATTR_GENRE, AVRCP_MEDIA_ATTRIBUTE_GENRE), - CONVERT(BTRC_MEDIA_ATTR_PLAYING_TIME, AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME) - }; - if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sEventId[aIn]; - return NS_OK; -} - -static nsresult -Convert(enum BluetoothAvrcpNotification aIn, btrc_notification_type_t& aOut) -{ - static const btrc_notification_type_t sNotificationType[] = { - CONVERT(AVRCP_NTF_INTERIM, BTRC_NOTIFICATION_TYPE_INTERIM), - CONVERT(AVRCP_NTF_CHANGED, BTRC_NOTIFICATION_TYPE_CHANGED) - }; - if (aIn >= MOZ_ARRAY_LENGTH(sNotificationType)) { - return NS_ERROR_ILLEGAL_VALUE; - } - aOut = sNotificationType[aIn]; - return NS_OK; -} - -static nsresult -Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut) -{ - const NS_ConvertUTF16toUTF8 value(aIn.mValue); - size_t len = std::min(strlen(value.get()), sizeof(aOut.text) - 1); - - memcpy(aOut.text, value.get(), len); - aOut.text[len] = '\0'; - aOut.attr_id = aIn.mId; - - return NS_OK; -} - -static nsresult -Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut) -{ - aOut.mNumAttr = aIn.num_attr; - memcpy(aOut.mIds, aIn.attr_ids, aIn.num_attr); - memcpy(aOut.mValues, aIn.attr_values, aIn.num_attr); - - return NS_OK; -} -#endif // ANDROID_VERSION >= 18 - -#if ANDROID_VERSION >= 19 -static nsresult -Convert(btrc_remote_features_t aIn, unsigned long& aOut) -{ - /* The input type's name is misleading. The converted value is - * actually a bitmask. - */ - aOut = static_cast(aIn); - return NS_OK; -} -#endif // ANDROID_VERSION >= 19 - -/* |ConvertArray| is a helper for converting arrays. Pass an - * instance of this structure as the first argument to |Convert| - * to convert an array. The output type has to support the array - * subscript operator. - */ -template -struct ConvertArray -{ - ConvertArray(const T* aData, unsigned long aLength) - : mData(aData) - , mLength(aLength) - { } - - const T* mData; - unsigned long mLength; -}; - -/* This implementation of |Convert| converts the elements of an - * array one-by-one. The result data structures must have enough - * memory allocated. - */ -template -static nsresult -Convert(const ConvertArray& aIn, Tout& aOut) -{ - for (unsigned long i = 0; i < aIn.mLength; ++i) { - nsresult rv = Convert(aIn.mData[i], aOut[i]); - if (NS_FAILED(rv)) { - return rv; - } - } - return NS_OK; -} - -/* This implementation of |Convert| is a helper that automatically - * allocates enough memory to hold the conversion results. The - * actual conversion is performed by the array-conversion helper - * above. - */ -template -static nsresult -Convert(const ConvertArray& aIn, nsAutoArrayPtr& aOut) -{ - aOut = new Tout[aIn.mLength]; - Tout* out = aOut.get(); - - return Convert(aIn, out); -} - -/* |ConvertDefault| is a helper function to return the result of a - * conversion or a default value if the conversion fails. - */ -template -static Tout -ConvertDefault(const Tin& aIn, const Tout& aDefault) -{ - Tout out = aDefault; // assignment silences compiler warning - if (NS_FAILED(Convert(aIn, out))) { - return aDefault; - } - return out; -} - -/* This implementation of |Convert| is a helper for copying the - * input value into the output value. It handles all cases that - * need no conversion. - */ -template -static nsresult -Convert(const T& aIn, T& aOut) -{ - aOut = aIn; - - return NS_OK; -} - -static nsresult -Convert(const bt_property_t& aIn, BluetoothProperty& aOut) -{ - /* type conversion */ - - nsresult rv = Convert(aIn.type, aOut.mType); - if (NS_FAILED(rv)) { - return rv; - } - - /* value conversion */ - - switch (aOut.mType) { - case PROPERTY_BDNAME: - /* fall through */ - case PROPERTY_REMOTE_FRIENDLY_NAME: - { - // We construct an nsCString here because bdname - // returned from Bluedroid is not 0-terminated. - aOut.mString = NS_ConvertUTF8toUTF16( - nsCString(static_cast(aIn.val), aIn.len)); - } - break; - case PROPERTY_BDADDR: - rv = Convert(*static_cast(aIn.val), aOut.mString); - break; - case PROPERTY_UUIDS: - { - size_t numUuids = aIn.len / MAX_UUID_SIZE; - ConvertArray array( - static_cast(aIn.val), numUuids); - aOut.mUuidArray.SetLength(numUuids); - rv = Convert(array, aOut.mUuidArray); - } - break; - case PROPERTY_CLASS_OF_DEVICE: - /* fall through */ - case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT: - aOut.mUint32 = *static_cast(aIn.val); - break; - case PROPERTY_TYPE_OF_DEVICE: - rv = Convert(*static_cast(aIn.val), - aOut.mDeviceType); - break; - case PROPERTY_SERVICE_RECORD: - rv = Convert(*static_cast(aIn.val), - aOut.mServiceRecord); - break; - case PROPERTY_ADAPTER_SCAN_MODE: - rv = Convert(*static_cast(aIn.val), - aOut.mScanMode); - break; - case PROPERTY_ADAPTER_BONDED_DEVICES: - { - size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES; - ConvertArray array( - static_cast(aIn.val), numAddresses); - aOut.mStringArray.SetLength(numAddresses); - rv = Convert(array, aOut.mStringArray); - } - break; - case PROPERTY_REMOTE_RSSI: - aOut.mInt32 = *static_cast(aIn.val); - break; -#if ANDROID_VERSION >= 18 - case PROPERTY_REMOTE_VERSION_INFO: - rv = Convert(*static_cast(aIn.val), - aOut.mRemoteInfo); - break; -#endif - case PROPERTY_REMOTE_DEVICE_TIMESTAMP: - /* nothing to do */ - break; - default: - /* mismatch with type conversion */ - NS_NOTREACHED("Unhandled property type"); - break; - } - if (NS_FAILED(rv)) { - return rv; - } - return NS_OK; -} - -// -// Result handling -// - -template -class BluetoothHALInterfaceRunnable0 : public nsRunnable -{ -public: - BluetoothHALInterfaceRunnable0(Obj* aObj, Res (Obj::*aMethod)()) - : mObj(aObj) - , mMethod(aMethod) - { - MOZ_ASSERT(mObj); - MOZ_ASSERT(mMethod); - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - ((*mObj).*mMethod)(); - return NS_OK; - } - -private: - nsRefPtr mObj; - void (Obj::*mMethod)(); -}; - -template -class BluetoothHALInterfaceRunnable1 : public nsRunnable -{ -public: - BluetoothHALInterfaceRunnable1(Obj* aObj, Res (Obj::*aMethod)(Arg1), - const Arg1& aArg1) - : mObj(aObj) - , mMethod(aMethod) - , mArg1(aArg1) - { - MOZ_ASSERT(mObj); - MOZ_ASSERT(mMethod); - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - ((*mObj).*mMethod)(mArg1); - return NS_OK; - } - -private: - nsRefPtr mObj; - Res (Obj::*mMethod)(Arg1); - Tin1 mArg1; -}; - -template -class BluetoothHALInterfaceRunnable3 : public nsRunnable -{ -public: - BluetoothHALInterfaceRunnable3(Obj* aObj, - Res (Obj::*aMethod)(Arg1, Arg2, Arg3), - const Arg1& aArg1, const Arg2& aArg2, - const Arg3& aArg3) - : mObj(aObj) - , mMethod(aMethod) - , mArg1(aArg1) - , mArg2(aArg2) - , mArg3(aArg3) - { - MOZ_ASSERT(mObj); - MOZ_ASSERT(mMethod); - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - ((*mObj).*mMethod)(mArg1, mArg2, mArg3); - return NS_OK; - } - -private: - nsRefPtr mObj; - Res (Obj::*mMethod)(Arg1, Arg2, Arg3); - Tin1 mArg1; - Tin2 mArg2; - Tin3 mArg3; -}; - -// -// Notification handling -// - -template -class BluetoothNotificationHALRunnable0 : public nsRunnable -{ -public: - typedef typename ObjectWrapper::ObjectType ObjectType; - typedef BluetoothNotificationHALRunnable0 SelfType; - - static already_AddRefed Create(Res (ObjectType::*aMethod)()) - { - nsRefPtr runnable(new SelfType(aMethod)); - - return runnable.forget(); - } - - static void - Dispatch(Res (ObjectType::*aMethod)()) - { - nsRefPtr runnable = Create(aMethod); - - if (!runnable) { - BT_WARNING("BluetoothNotificationHALRunnable0::Create failed"); - return; - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - MOZ_ASSERT(NS_IsMainThread()); - - ObjectType* obj = ObjectWrapper::GetInstance(); - - if (!obj) { - BT_WARNING("Notification handler not initialized"); - } else { - ((*obj).*mMethod)(); - } - return NS_OK; - } - -private: - BluetoothNotificationHALRunnable0(Res (ObjectType::*aMethod)()) - : mMethod(aMethod) - { - MOZ_ASSERT(mMethod); - } - - Res (ObjectType::*mMethod)(); -}; - -template -class BluetoothNotificationHALRunnable1 : public nsRunnable -{ -public: - typedef typename ObjectWrapper::ObjectType ObjectType; - typedef BluetoothNotificationHALRunnable1 SelfType; - - template - static already_AddRefed Create( - Res (ObjectType::*aMethod)(Arg1), const T1& aIn1) - { - nsRefPtr runnable(new SelfType(aMethod)); - - if (NS_FAILED(runnable->ConvertAndSet(aIn1))) { - return nullptr; - } - return runnable.forget(); - } - - template - static void - Dispatch(Res (ObjectType::*aMethod)(Arg1), const T1& aIn1) - { - nsRefPtr runnable = Create(aMethod, aIn1); - - if (!runnable) { - BT_WARNING("BluetoothNotificationHALRunnable1::Create failed"); - return; - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - MOZ_ASSERT(NS_IsMainThread()); - - ObjectType* obj = ObjectWrapper::GetInstance(); - - if (!obj) { - BT_WARNING("Notification handler not initialized"); - } else { - ((*obj).*mMethod)(mArg1); - } - return NS_OK; - } - -private: - BluetoothNotificationHALRunnable1(Res (ObjectType::*aMethod)(Arg1)) - : mMethod(aMethod) - { - MOZ_ASSERT(mMethod); - } - - template - nsresult - ConvertAndSet(const T1& aIn1) - { - nsresult rv = Convert(aIn1, mArg1); - if (NS_FAILED(rv)) { - return rv; - } - return NS_OK; - } - - Res (ObjectType::*mMethod)(Arg1); - Tin1 mArg1; -}; - -template -class BluetoothNotificationHALRunnable2 : public nsRunnable -{ -public: - typedef typename ObjectWrapper::ObjectType ObjectType; - typedef BluetoothNotificationHALRunnable2 SelfType; - - template - static already_AddRefed Create( - Res (ObjectType::*aMethod)(Arg1, Arg2), const T1& aIn1, const T2& aIn2) - { - nsRefPtr runnable(new SelfType(aMethod)); - - if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2))) { - return nullptr; - } - return runnable.forget(); - } - - template - static void - Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2), - const T1& aIn1, const T2& aIn2) - { - nsRefPtr runnable = Create(aMethod, aIn1, aIn2); - - if (!runnable) { - BT_WARNING("BluetoothNotificationHALRunnable2::Create failed"); - return; - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - MOZ_ASSERT(NS_IsMainThread()); - - ObjectType* obj = ObjectWrapper::GetInstance(); - - if (!obj) { - BT_WARNING("Notification handler not initialized"); - } else { - ((*obj).*mMethod)(mArg1, mArg2); - } - return NS_OK; - } - -private: - BluetoothNotificationHALRunnable2( - Res (ObjectType::*aMethod)(Arg1, Arg2)) - : mMethod(aMethod) - { - MOZ_ASSERT(mMethod); - } - - template - nsresult - ConvertAndSet(const T1& aIn1, const T2& aIn2) - { - nsresult rv = Convert(aIn1, mArg1); - if (NS_FAILED(rv)) { - return rv; - } - rv = Convert(aIn2, mArg2); - if (NS_FAILED(rv)) { - return rv; - } - return NS_OK; - } - - Res (ObjectType::*mMethod)(Arg1, Arg2); - Tin1 mArg1; - Tin2 mArg2; -}; - -template -class BluetoothNotificationHALRunnable3 : public nsRunnable -{ -public: - typedef typename ObjectWrapper::ObjectType ObjectType; - typedef BluetoothNotificationHALRunnable3 SelfType; - - template - static already_AddRefed Create( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), - const T1& aIn1, const T2& aIn2, const T3& aIn3) - { - nsRefPtr runnable(new SelfType(aMethod)); - - if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3))) { - return nullptr; - } - return runnable.forget(); - } - - template - static void - Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), - const T1& aIn1, const T2& aIn2, const T3& aIn3) - { - nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3); - - if (!runnable) { - BT_WARNING("BluetoothNotificationHALRunnable3::Create failed"); - return; - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - MOZ_ASSERT(NS_IsMainThread()); - - ObjectType* obj = ObjectWrapper::GetInstance(); - - if (!obj) { - BT_WARNING("Notification handler not initialized"); - } else { - ((*obj).*mMethod)(mArg1, mArg2, mArg3); - } - return NS_OK; - } - -private: - BluetoothNotificationHALRunnable3( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3)) - : mMethod(aMethod) - { - MOZ_ASSERT(mMethod); - } - - template - nsresult - ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3) - { - 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; - } - return NS_OK; - } - - Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3); - Tin1 mArg1; - Tin2 mArg2; - Tin3 mArg3; -}; - -template -class BluetoothNotificationHALRunnable4 : public nsRunnable -{ -public: - typedef typename ObjectWrapper::ObjectType ObjectType; - typedef BluetoothNotificationHALRunnable4 SelfType; - - template - static already_AddRefed Create( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), - const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4) - { - nsRefPtr runnable(new SelfType(aMethod)); - - if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4))) { - return nullptr; - } - return runnable.forget(); - } - - template - static void - Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4), - const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4) - { - nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3, aIn4); - - if (!runnable) { - BT_WARNING("BluetoothNotificationHALRunnable4::Create failed"); - return; - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - } - - NS_METHOD - Run() MOZ_OVERRIDE - { - MOZ_ASSERT(NS_IsMainThread()); - - ObjectType* obj = ObjectWrapper::GetInstance(); - - if (!obj) { - BT_WARNING("Notification handler not initialized"); - } else { - ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4); - } - return NS_OK; - } - -private: - BluetoothNotificationHALRunnable4( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4)) - : mMethod(aMethod) - { - MOZ_ASSERT(mMethod); - } - - template - nsresult - ConvertAndSet(const T1& aIn1, const T2& aIn2, - const T3& aIn3, const T4& aIn4) - { - 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; - } - return NS_OK; - } - - Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4); - Tin1 mArg1; - Tin2 mArg2; - Tin3 mArg3; - Tin4 mArg4; -}; - -template -class BluetoothNotificationHALRunnable5 : public nsRunnable -{ -public: - typedef typename ObjectWrapper::ObjectType ObjectType; - typedef BluetoothNotificationHALRunnable5 SelfType; - - template - static already_AddRefed Create( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), - const T1& aIn1, const T2& aIn2, const T3& aIn3, - const T4& aIn4, const T5& aIn5) - { - nsRefPtr runnable(new SelfType(aMethod)); - - if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5))) { - return nullptr; - } - return runnable.forget(); - } - - template - static void - Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5), - const T1& aIn1, const T2& aIn2, const T3& aIn3, - const T4& aIn4, const T5& aIn5) - { - nsRefPtr runnable = Create(aMethod, - aIn1, aIn2, aIn3, aIn4, aIn5); - if (!runnable) { - BT_WARNING("BluetoothNotificationHALRunnable5::Create failed"); - return; - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - } - - NS_METHOD - Run() MOZ_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); - } - return NS_OK; - } - -private: - BluetoothNotificationHALRunnable5( - Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5)) - : mMethod(aMethod) - { - MOZ_ASSERT(mMethod); - } - - template - nsresult - ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3, - const T4& aIn4, const T5& aIn5) - { - 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; - } - return NS_OK; - } - - Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5); - Tin1 mArg1; - Tin2 mArg2; - Tin3 mArg3; - Tin4 mArg4; - Tin5 mArg5; -}; - -// -// Socket Interface -// - template<> struct interface_traits { @@ -1692,474 +28,6 @@ struct interface_traits } }; -typedef - BluetoothHALInterfaceRunnable1 - BluetoothSocketHALIntResultRunnable; - -typedef - BluetoothHALInterfaceRunnable3 - BluetoothSocketHALIntStringIntResultRunnable; - -typedef - BluetoothHALInterfaceRunnable1 - BluetoothSocketHALErrorRunnable; - -static nsresult -DispatchBluetoothSocketHALResult( - BluetoothSocketResultHandler* aRes, - void (BluetoothSocketResultHandler::*aMethod)(int), int aArg, - BluetoothStatus aStatus) -{ - MOZ_ASSERT(aRes); - - nsRunnable* runnable; - - if (aStatus == STATUS_SUCCESS) { - runnable = new BluetoothSocketHALIntResultRunnable(aRes, aMethod, aArg); - } else { - runnable = new BluetoothSocketHALErrorRunnable(aRes, - &BluetoothSocketResultHandler::OnError, aStatus); - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - return rv; -} - -static nsresult -DispatchBluetoothSocketHALResult( - BluetoothSocketResultHandler* aRes, - void (BluetoothSocketResultHandler::*aMethod)(int, const nsAString&, int), - int aArg1, const nsAString& aArg2, int aArg3, BluetoothStatus aStatus) -{ - MOZ_ASSERT(aRes); - - nsRunnable* runnable; - - if (aStatus == STATUS_SUCCESS) { - runnable = new BluetoothSocketHALIntStringIntResultRunnable( - aRes, aMethod, aArg1, aArg2, aArg3); - } else { - runnable = new BluetoothSocketHALErrorRunnable(aRes, - &BluetoothSocketResultHandler::OnError, aStatus); - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - return rv; -} - -void -BluetoothSocketHALInterface::Listen(BluetoothSocketType aType, - const nsAString& aServiceName, - const uint8_t aServiceUuid[16], - int aChannel, bool aEncrypt, - bool aAuth, - BluetoothSocketResultHandler* aRes) -{ - int fd; - bt_status_t status; - btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning - - if (NS_SUCCEEDED(Convert(aType, type))) { - status = mInterface->listen(type, - NS_ConvertUTF16toUTF8(aServiceName).get(), - aServiceUuid, aChannel, &fd, - (BTSOCK_FLAG_ENCRYPT * aEncrypt) | - (BTSOCK_FLAG_AUTH * aAuth)); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothSocketHALResult( - aRes, &BluetoothSocketResultHandler::Listen, fd, - ConvertDefault(status, STATUS_FAIL)); - } -} - -#define CMSGHDR_CONTAINS_FD(_cmsghdr) \ - ( ((_cmsghdr)->cmsg_level == SOL_SOCKET) && \ - ((_cmsghdr)->cmsg_type == SCM_RIGHTS) ) - -/* |SocketMessageWatcher| receives Bluedroid's socket setup - * messages on the I/O thread. You need to inherit from this - * class to make use of it. - * - * Bluedroid sends two socket info messages (20 bytes) at - * the beginning of a connection to both peers. - * - * - 1st message: [channel:4] - * - 2nd message: [size:2][bd address:6][channel:4][connection status:4] - * - * On the server side, the second message will contain a - * socket file descriptor for the connection. The client - * uses the original file descriptor. - */ -class SocketMessageWatcher : public MessageLoopForIO::Watcher -{ -public: - static const unsigned char MSG1_SIZE = 4; - static const unsigned char MSG2_SIZE = 16; - - static const unsigned char OFF_CHANNEL1 = 0; - static const unsigned char OFF_SIZE = 4; - static const unsigned char OFF_BDADDRESS = 6; - static const unsigned char OFF_CHANNEL2 = 12; - static const unsigned char OFF_STATUS = 16; - - SocketMessageWatcher(int aFd) - : mFd(aFd) - , mClientFd(-1) - , mLen(0) - { } - - virtual ~SocketMessageWatcher() - { } - - virtual void Proceed(BluetoothStatus aStatus) = 0; - - void OnFileCanReadWithoutBlocking(int aFd) MOZ_OVERRIDE - { - BluetoothStatus status; - - switch (mLen) { - case 0: - status = RecvMsg1(); - break; - case MSG1_SIZE: - status = RecvMsg2(); - break; - default: - /* message-size error */ - status = STATUS_FAIL; - break; - } - - if (IsComplete() || status != STATUS_SUCCESS) { - mWatcher.StopWatchingFileDescriptor(); - Proceed(status); - } - } - - void OnFileCanWriteWithoutBlocking(int aFd) MOZ_OVERRIDE - { } - - void Watch() - { - MessageLoopForIO::current()->WatchFileDescriptor( - mFd, - true, - MessageLoopForIO::WATCH_READ, - &mWatcher, - this); - } - - bool IsComplete() const - { - return mLen == (MSG1_SIZE + MSG2_SIZE); - } - - int GetFd() const - { - return mFd; - } - - int32_t GetChannel1() const - { - return ReadInt32(OFF_CHANNEL1); - } - - int32_t GetSize() const - { - return ReadInt16(OFF_SIZE); - } - - nsString GetBdAddress() const - { - nsString bdAddress; - ReadBdAddress(OFF_BDADDRESS, bdAddress); - return bdAddress; - } - - int32_t GetChannel2() const - { - return ReadInt32(OFF_CHANNEL2); - } - - int32_t GetConnectionStatus() const - { - return ReadInt32(OFF_STATUS); - } - - int GetClientFd() const - { - return mClientFd; - } - -private: - BluetoothStatus RecvMsg1() - { - struct iovec iv; - memset(&iv, 0, sizeof(iv)); - iv.iov_base = mBuf; - iv.iov_len = MSG1_SIZE; - - struct msghdr msg; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iv; - msg.msg_iovlen = 1; - - ssize_t res = TEMP_FAILURE_RETRY(recvmsg(mFd, &msg, MSG_NOSIGNAL)); - if (res < 0) { - return STATUS_FAIL; - } - - mLen += res; - - return STATUS_SUCCESS; - } - - BluetoothStatus RecvMsg2() - { - struct iovec iv; - memset(&iv, 0, sizeof(iv)); - iv.iov_base = mBuf + MSG1_SIZE; - iv.iov_len = MSG2_SIZE; - - struct msghdr msg; - struct cmsghdr cmsgbuf[2 * sizeof(cmsghdr) + 0x100]; - memset(&msg, 0, sizeof(msg)); - msg.msg_iov = &iv; - msg.msg_iovlen = 1; - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); - - ssize_t res = TEMP_FAILURE_RETRY(recvmsg(mFd, &msg, MSG_NOSIGNAL)); - if (res < 0) { - return STATUS_FAIL; - } - - mLen += res; - - if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) { - return STATUS_FAIL; - } - - struct cmsghdr *cmsgptr = CMSG_FIRSTHDR(&msg); - - // Extract client fd from message header - for (; cmsgptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { - if (CMSGHDR_CONTAINS_FD(cmsgptr)) { - // if multiple file descriptors have been sent, we close - // all but the final one. - if (mClientFd != -1) { - TEMP_FAILURE_RETRY(close(mClientFd)); - } - // retrieve sent client fd - mClientFd = *(static_cast(CMSG_DATA(cmsgptr))); - } - } - - return STATUS_SUCCESS; - } - - int16_t ReadInt16(unsigned long aOffset) const - { - /* little-endian buffer */ - return (static_cast(mBuf[aOffset + 1]) << 8) | - static_cast(mBuf[aOffset]); - } - - int32_t ReadInt32(unsigned long aOffset) const - { - /* little-endian buffer */ - return (static_cast(mBuf[aOffset + 3]) << 24) | - (static_cast(mBuf[aOffset + 2]) << 16) | - (static_cast(mBuf[aOffset + 1]) << 8) | - static_cast(mBuf[aOffset]); - } - - void ReadBdAddress(unsigned long aOffset, nsAString& aBdAddress) const - { - const bt_bdaddr_t* bdAddress = - reinterpret_cast(mBuf+aOffset); - - if (NS_FAILED(Convert(*bdAddress, aBdAddress))) { - aBdAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE); - } - } - - MessageLoopForIO::FileDescriptorWatcher mWatcher; - int mFd; - int mClientFd; - unsigned char mLen; - uint8_t mBuf[MSG1_SIZE + MSG2_SIZE]; -}; - -/* |SocketMessageWatcherTask| starts a SocketMessageWatcher - * on the I/O task - */ -class SocketMessageWatcherTask MOZ_FINAL : public Task -{ -public: - SocketMessageWatcherTask(SocketMessageWatcher* aWatcher) - : mWatcher(aWatcher) - { - MOZ_ASSERT(mWatcher); - } - - void Run() MOZ_OVERRIDE - { - mWatcher->Watch(); - } - -private: - SocketMessageWatcher* mWatcher; -}; - -/* |DeleteTask| deletes a class instance on the I/O thread - */ -template -class DeleteTask MOZ_FINAL : public Task -{ -public: - DeleteTask(T* aPtr) - : mPtr(aPtr) - { } - - void Run() MOZ_OVERRIDE - { - mPtr = nullptr; - } - -private: - nsAutoPtr mPtr; -}; - -/* |ConnectWatcher| specializes SocketMessageWatcher for - * connect operations by reading the socket messages from - * Bluedroid and forwarding the connected socket to the - * resource handler. - */ -class ConnectWatcher MOZ_FINAL : public SocketMessageWatcher -{ -public: - ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes) - : SocketMessageWatcher(aFd) - , mRes(aRes) - { } - - void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE - { - if (mRes) { - DispatchBluetoothSocketHALResult( - mRes, &BluetoothSocketResultHandler::Connect, GetFd(), - GetBdAddress(), GetConnectionStatus(), aStatus); - } - MessageLoopForIO::current()->PostTask( - FROM_HERE, new DeleteTask(this)); - } - -private: - nsRefPtr mRes; -}; - -void -BluetoothSocketHALInterface::Connect(const nsAString& aBdAddr, - BluetoothSocketType aType, - const uint8_t aUuid[16], - int aChannel, bool aEncrypt, - bool aAuth, - BluetoothSocketResultHandler* aRes) -{ - int fd; - bt_status_t status; - bt_bdaddr_t bdAddr; - btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning - - if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) && - NS_SUCCEEDED(Convert(aType, type))) { - status = mInterface->connect(&bdAddr, type, aUuid, aChannel, &fd, - (BTSOCK_FLAG_ENCRYPT * aEncrypt) | - (BTSOCK_FLAG_AUTH * aAuth)); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (status == BT_STATUS_SUCCESS) { - /* receive Bluedroid's socket-setup messages */ - Task* t = new SocketMessageWatcherTask(new ConnectWatcher(fd, aRes)); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t); - } else if (aRes) { - DispatchBluetoothSocketHALResult( - aRes, &BluetoothSocketResultHandler::Connect, -1, EmptyString(), 0, - ConvertDefault(status, STATUS_FAIL)); - } -} - -/* Specializes SocketMessageWatcher for Accept operations by - * reading the socket messages from Bluedroid and forwarding - * the received client socket to the resource handler. The - * first message is received immediately. When there's a new - * connection, Bluedroid sends the 2nd message with the socket - * info and socket file descriptor. - */ -class AcceptWatcher MOZ_FINAL : public SocketMessageWatcher -{ -public: - AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes) - : SocketMessageWatcher(aFd) - , mRes(aRes) - { - /* not supplying a result handler leaks received file descriptor */ - MOZ_ASSERT(mRes); - } - - void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE - { - if (mRes) { - DispatchBluetoothSocketHALResult( - mRes, &BluetoothSocketResultHandler::Accept, GetClientFd(), - GetBdAddress(), GetConnectionStatus(), aStatus); - } - MessageLoopForIO::current()->PostTask( - FROM_HERE, new DeleteTask(this)); - } - -private: - nsRefPtr mRes; -}; - -void -BluetoothSocketHALInterface::Accept(int aFd, - BluetoothSocketResultHandler* aRes) -{ - /* receive Bluedroid's socket-setup messages and client fd */ - Task* t = new SocketMessageWatcherTask(new AcceptWatcher(aFd, aRes)); - XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t); -} - -BluetoothSocketHALInterface::BluetoothSocketHALInterface( - const btsock_interface_t* aInterface) -: mInterface(aInterface) -{ - MOZ_ASSERT(mInterface); -} - -BluetoothSocketHALInterface::~BluetoothSocketHALInterface() -{ } - -// -// Handsfree Interface -// - template<> struct interface_traits { @@ -2171,614 +39,6 @@ struct interface_traits } }; -typedef - BluetoothHALInterfaceRunnable0 - BluetoothHandsfreeHALResultRunnable; - -typedef - BluetoothHALInterfaceRunnable1 - BluetoothHandsfreeHALErrorRunnable; - -static nsresult -DispatchBluetoothHandsfreeHALResult( - BluetoothHandsfreeResultHandler* aRes, - void (BluetoothHandsfreeResultHandler::*aMethod)(), - BluetoothStatus aStatus) -{ - MOZ_ASSERT(aRes); - - nsRunnable* runnable; - - if (aStatus == STATUS_SUCCESS) { - runnable = new BluetoothHandsfreeHALResultRunnable(aRes, aMethod); - } else { - runnable = new BluetoothHandsfreeHALErrorRunnable(aRes, - &BluetoothHandsfreeResultHandler::OnError, aStatus); - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - return rv; -} - -// Notification handling -// - -static BluetoothHandsfreeNotificationHandler* sHandsfreeNotificationHandler; - -struct BluetoothHandsfreeHALCallback -{ - class HandsfreeNotificationHandlerWrapper - { - public: - typedef BluetoothHandsfreeNotificationHandler ObjectType; - - static ObjectType* GetInstance() - { - MOZ_ASSERT(NS_IsMainThread()); - - return sHandsfreeNotificationHandler; - } - }; - - // Notifications - - typedef BluetoothNotificationHALRunnable2< - HandsfreeNotificationHandlerWrapper, void, - BluetoothHandsfreeConnectionState, nsString, - BluetoothHandsfreeConnectionState, const nsAString&> - ConnectionStateNotification; - - typedef BluetoothNotificationHALRunnable2< - HandsfreeNotificationHandlerWrapper, void, - BluetoothHandsfreeAudioState, nsString, - BluetoothHandsfreeAudioState, const nsAString&> - AudioStateNotification; - - typedef BluetoothNotificationHALRunnable1< - HandsfreeNotificationHandlerWrapper, void, - BluetoothHandsfreeVoiceRecognitionState> - VoiceRecognitionNotification; - - typedef BluetoothNotificationHALRunnable0< - HandsfreeNotificationHandlerWrapper, void> - AnswerCallNotification; - - typedef BluetoothNotificationHALRunnable0< - HandsfreeNotificationHandlerWrapper, void> - HangupCallNotification; - - typedef BluetoothNotificationHALRunnable2< - HandsfreeNotificationHandlerWrapper, void, - BluetoothHandsfreeVolumeType, int> - VolumeNotification; - - typedef BluetoothNotificationHALRunnable1< - HandsfreeNotificationHandlerWrapper, void, nsString, const nsAString&> - DialCallNotification; - - typedef BluetoothNotificationHALRunnable1< - HandsfreeNotificationHandlerWrapper, void, char> - DtmfNotification; - - typedef BluetoothNotificationHALRunnable1< - HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeNRECState> - NRECNotification; - - typedef BluetoothNotificationHALRunnable1< - HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeCallHoldType> - CallHoldNotification; - - typedef BluetoothNotificationHALRunnable0< - HandsfreeNotificationHandlerWrapper, void> - CnumNotification; - - typedef BluetoothNotificationHALRunnable0< - HandsfreeNotificationHandlerWrapper, void> - CindNotification; - - typedef BluetoothNotificationHALRunnable0< - HandsfreeNotificationHandlerWrapper, void> - CopsNotification; - - typedef BluetoothNotificationHALRunnable0< - HandsfreeNotificationHandlerWrapper, void> - ClccNotification; - - typedef BluetoothNotificationHALRunnable1< - HandsfreeNotificationHandlerWrapper, void, nsCString, const nsACString&> - UnknownAtNotification; - - typedef BluetoothNotificationHALRunnable0< - HandsfreeNotificationHandlerWrapper, void> - KeyPressedNotification; - - // Bluedroid Handsfree callbacks - - static void - ConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddr) - { - ConnectionStateNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification, - aState, aBdAddr); - } - - static void - AudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddr) - { - AudioStateNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::AudioStateNotification, - aState, aBdAddr); - } - - static void - VoiceRecognition(bthf_vr_state_t aState) - { - VoiceRecognitionNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification, - aState); - } - - static void - AnswerCall() - { - AnswerCallNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::AnswerCallNotification); - } - - static void - HangupCall() - { - HangupCallNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::HangupCallNotification); - } - - static void - Volume(bthf_volume_type_t aType, int aVolume) - { - VolumeNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::VolumeNotification, - aType, aVolume); - } - - static void - DialCall(char* aNumber) - { - DialCallNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::DialCallNotification, aNumber); - } - - static void - Dtmf(char aDtmf) - { - DtmfNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::DtmfNotification, aDtmf); - } - - static void - NoiseReductionEchoCancellation(bthf_nrec_t aNrec) - { - NRECNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::NRECNotification, aNrec); - } - - static void - CallHold(bthf_chld_type_t aChld) - { - CallHoldNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::CallHoldNotification, aChld); - } - - static void - Cnum() - { - CnumNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::CnumNotification); - } - - static void - Cind() - { - CindNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::CindNotification); - } - - static void - Cops() - { - CopsNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::CopsNotification); - } - - static void - Clcc() - { - ClccNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::ClccNotification); - } - - static void - UnknownAt(char* aAtString) - { - UnknownAtNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::UnknownAtNotification, - aAtString); - } - - static void - KeyPressed() - { - KeyPressedNotification::Dispatch( - &BluetoothHandsfreeNotificationHandler::KeyPressedNotification); - } -}; - -// Interface -// - -BluetoothHandsfreeHALInterface::BluetoothHandsfreeHALInterface( - const bthf_interface_t* aInterface) -: mInterface(aInterface) -{ - MOZ_ASSERT(mInterface); -} - -BluetoothHandsfreeHALInterface::~BluetoothHandsfreeHALInterface() -{ } - -void -BluetoothHandsfreeHALInterface::Init( - BluetoothHandsfreeNotificationHandler* aNotificationHandler, - BluetoothHandsfreeResultHandler* aRes) -{ - static bthf_callbacks_t sCallbacks = { - sizeof(sCallbacks), - BluetoothHandsfreeHALCallback::ConnectionState, - BluetoothHandsfreeHALCallback::AudioState, - BluetoothHandsfreeHALCallback::VoiceRecognition, - BluetoothHandsfreeHALCallback::AnswerCall, - BluetoothHandsfreeHALCallback::HangupCall, - BluetoothHandsfreeHALCallback::Volume, - BluetoothHandsfreeHALCallback::DialCall, - BluetoothHandsfreeHALCallback::Dtmf, - BluetoothHandsfreeHALCallback::NoiseReductionEchoCancellation, - BluetoothHandsfreeHALCallback::CallHold, - BluetoothHandsfreeHALCallback::Cnum, - BluetoothHandsfreeHALCallback::Cind, - BluetoothHandsfreeHALCallback::Cops, - BluetoothHandsfreeHALCallback::Clcc, - BluetoothHandsfreeHALCallback::UnknownAt, - BluetoothHandsfreeHALCallback::KeyPressed - }; - - sHandsfreeNotificationHandler = aNotificationHandler; - - bt_status_t status = mInterface->init(&sCallbacks); - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::Init, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::Cleanup( - BluetoothHandsfreeResultHandler* aRes) -{ - mInterface->cleanup(); - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::Cleanup, STATUS_SUCCESS); - } -} - -/* Connect / Disconnect */ - -void -BluetoothHandsfreeHALInterface::Connect( - const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bt_bdaddr_t bdAddr; - - if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { - status = mInterface->connect(&bdAddr); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::Connect, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::Disconnect( - const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bt_bdaddr_t bdAddr; - - if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { - status = mInterface->disconnect(&bdAddr); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::Disconnect, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::ConnectAudio( - const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bt_bdaddr_t bdAddr; - - if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { - status = mInterface->connect_audio(&bdAddr); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::ConnectAudio, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::DisconnectAudio( - const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bt_bdaddr_t bdAddr; - - if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { - status = mInterface->disconnect_audio(&bdAddr); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::DisconnectAudio, - ConvertDefault(status, STATUS_FAIL)); - } -} - -/* Voice Recognition */ - -void -BluetoothHandsfreeHALInterface::StartVoiceRecognition( - BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status = mInterface->start_voice_recognition(); - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::StopVoiceRecognition( - BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status = mInterface->stop_voice_recognition(); - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition, - ConvertDefault(status, STATUS_FAIL)); - } -} - -/* Volume */ - -void -BluetoothHandsfreeHALInterface::VolumeControl( - BluetoothHandsfreeVolumeType aType, int aVolume, - BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bthf_volume_type_t type = BTHF_VOLUME_TYPE_SPK; - - if (NS_SUCCEEDED(Convert(aType, type))) { - status = mInterface->volume_control(type, aVolume); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::VolumeControl, - ConvertDefault(status, STATUS_FAIL)); - } -} - -/* Device status */ - -void -BluetoothHandsfreeHALInterface::DeviceStatusNotification( - BluetoothHandsfreeNetworkState aNtkState, - BluetoothHandsfreeServiceType aSvcType, int aSignal, - int aBattChg, BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bthf_network_state_t ntkState = BTHF_NETWORK_STATE_NOT_AVAILABLE; - bthf_service_type_t svcType = BTHF_SERVICE_TYPE_HOME; - - if (NS_SUCCEEDED(Convert(aNtkState, ntkState)) && - NS_SUCCEEDED(Convert(aSvcType, svcType))) { - status = mInterface->device_status_notification(ntkState, svcType, - aSignal, aBattChg); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::DeviceStatusNotification, - ConvertDefault(status, STATUS_FAIL)); - } -} - -/* Responses */ - -void -BluetoothHandsfreeHALInterface::CopsResponse( - const char* aCops, BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status = mInterface->cops_response(aCops); - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::CopsResponse, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::CindResponse( - int aSvc, int aNumActive, int aNumHeld, - BluetoothHandsfreeCallState aCallSetupState, - int aSignal, int aRoam, int aBattChg, - BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE; - - if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState))) { - status = mInterface->cind_response(aSvc, aNumActive, aNumHeld, - callSetupState, aSignal, - aRoam, aBattChg); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::CindResponse, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::FormattedAtResponse( - const char* aRsp, BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status = mInterface->formatted_at_response(aRsp); - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::AtResponse( - BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, - BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bthf_at_response_t responseCode = BTHF_AT_RESPONSE_ERROR; - - if (NS_SUCCEEDED(Convert(aResponseCode, responseCode))) { - status = mInterface->at_response(responseCode, aErrorCode); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::AtResponse, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothHandsfreeHALInterface::ClccResponse( - int aIndex, - BluetoothHandsfreeCallDirection aDir, - BluetoothHandsfreeCallState aState, - BluetoothHandsfreeCallMode aMode, - BluetoothHandsfreeCallMptyType aMpty, - const nsAString& aNumber, - BluetoothHandsfreeCallAddressType aType, - BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bthf_call_direction_t dir = BTHF_CALL_DIRECTION_OUTGOING; - bthf_call_state_t state = BTHF_CALL_STATE_ACTIVE; - bthf_call_mode_t mode = BTHF_CALL_TYPE_VOICE; - bthf_call_mpty_type_t mpty = BTHF_CALL_MPTY_TYPE_SINGLE; - bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN; - - if (NS_SUCCEEDED(Convert(aDir, dir)) && - NS_SUCCEEDED(Convert(aState, state)) && - NS_SUCCEEDED(Convert(aMode, mode)) && - NS_SUCCEEDED(Convert(aMpty, mpty)) && - NS_SUCCEEDED(Convert(aType, type))) { - status = mInterface->clcc_response(aIndex, dir, state, mode, mpty, - NS_ConvertUTF16toUTF8(aNumber).get(), - type); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::ClccResponse, - ConvertDefault(status, STATUS_FAIL)); - } -} - -/* Phone State */ - -void -BluetoothHandsfreeHALInterface::PhoneStateChange(int aNumActive, int aNumHeld, - BluetoothHandsfreeCallState aCallSetupState, const nsAString& aNumber, - BluetoothHandsfreeCallAddressType aType, - BluetoothHandsfreeResultHandler* aRes) -{ - bt_status_t status; - bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE; - bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN; - - if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState)) && - NS_SUCCEEDED(Convert(aType, type))) { - status = mInterface->phone_state_change( - aNumActive, aNumHeld, callSetupState, - NS_ConvertUTF16toUTF8(aNumber).get(), type); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothHandsfreeHALResult( - aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange, - ConvertDefault(status, STATUS_FAIL)); - } -} - -// -// Bluetooth Advanced Audio Interface -// - template<> struct interface_traits { @@ -2790,182 +50,6 @@ struct interface_traits } }; -typedef - BluetoothHALInterfaceRunnable0 - BluetoothA2dpHALResultRunnable; - -typedef - BluetoothHALInterfaceRunnable1 - BluetoothA2dpHALErrorRunnable; - -static nsresult -DispatchBluetoothA2dpHALResult( - BluetoothA2dpResultHandler* aRes, - void (BluetoothA2dpResultHandler::*aMethod)(), - BluetoothStatus aStatus) -{ - MOZ_ASSERT(aRes); - - nsRunnable* runnable; - - if (aStatus == STATUS_SUCCESS) { - runnable = new BluetoothA2dpHALResultRunnable(aRes, aMethod); - } else { - runnable = new BluetoothA2dpHALErrorRunnable(aRes, - &BluetoothA2dpResultHandler::OnError, aStatus); - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - return rv; -} - -// Notification handling -// - -static BluetoothA2dpNotificationHandler* sA2dpNotificationHandler; - -struct BluetoothA2dpHALCallback -{ - class A2dpNotificationHandlerWrapper - { - public: - typedef BluetoothA2dpNotificationHandler ObjectType; - - static ObjectType* GetInstance() - { - MOZ_ASSERT(NS_IsMainThread()); - - return sA2dpNotificationHandler; - } - }; - - // Notifications - - typedef BluetoothNotificationHALRunnable2< - A2dpNotificationHandlerWrapper, void, - BluetoothA2dpConnectionState, nsString, - BluetoothA2dpConnectionState, const nsAString&> - ConnectionStateNotification; - - typedef BluetoothNotificationHALRunnable2< - A2dpNotificationHandlerWrapper, void, - BluetoothA2dpAudioState, nsString, - BluetoothA2dpAudioState, const nsAString&> - AudioStateNotification; - - // Bluedroid A2DP callbacks - - static void - ConnectionState(btav_connection_state_t aState, bt_bdaddr_t* aBdAddr) - { - ConnectionStateNotification::Dispatch( - &BluetoothA2dpNotificationHandler::ConnectionStateNotification, - aState, aBdAddr); - } - - static void - AudioState(btav_audio_state_t aState, bt_bdaddr_t* aBdAddr) - { - AudioStateNotification::Dispatch( - &BluetoothA2dpNotificationHandler::AudioStateNotification, - aState, aBdAddr); - } -}; - -// Interface -// - -BluetoothA2dpHALInterface::BluetoothA2dpHALInterface( - const btav_interface_t* aInterface) -: mInterface(aInterface) -{ - MOZ_ASSERT(mInterface); -} - -BluetoothA2dpHALInterface::~BluetoothA2dpHALInterface() -{ } - -void -BluetoothA2dpHALInterface::Init( - BluetoothA2dpNotificationHandler* aNotificationHandler, - BluetoothA2dpResultHandler* aRes) -{ - static btav_callbacks_t sCallbacks = { - sizeof(sCallbacks), - BluetoothA2dpHALCallback::ConnectionState, - BluetoothA2dpHALCallback::AudioState - }; - - sA2dpNotificationHandler = aNotificationHandler; - - bt_status_t status = mInterface->init(&sCallbacks); - - if (aRes) { - DispatchBluetoothA2dpHALResult(aRes, - &BluetoothA2dpResultHandler::Init, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothA2dpHALInterface::Cleanup(BluetoothA2dpResultHandler* aRes) -{ - mInterface->cleanup(); - - if (aRes) { - DispatchBluetoothA2dpHALResult(aRes, - &BluetoothA2dpResultHandler::Cleanup, - STATUS_SUCCESS); - } -} - -void -BluetoothA2dpHALInterface::Connect(const nsAString& aBdAddr, - BluetoothA2dpResultHandler* aRes) -{ - bt_status_t status; - bt_bdaddr_t bdAddr; - - if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { - status = mInterface->connect(&bdAddr); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothA2dpHALResult( - aRes, &BluetoothA2dpResultHandler::Connect, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothA2dpHALInterface::Disconnect(const nsAString& aBdAddr, - BluetoothA2dpResultHandler* aRes) -{ - bt_status_t status; - bt_bdaddr_t bdAddr; - - if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { - status = mInterface->disconnect(&bdAddr); - } else { - status = BT_STATUS_PARM_INVALID; - } - - if (aRes) { - DispatchBluetoothA2dpHALResult( - aRes, &BluetoothA2dpResultHandler::Disconnect, - ConvertDefault(status, STATUS_FAIL)); - } -} - -// -// Bluetooth AVRCP Interface -// - #if ANDROID_VERSION >= 18 template<> struct interface_traits @@ -2979,604 +63,19 @@ struct interface_traits }; #endif -typedef - BluetoothHALInterfaceRunnable0 - BluetoothAvrcpHALResultRunnable; - -typedef - BluetoothHALInterfaceRunnable1 - BluetoothAvrcpHALErrorRunnable; - -static nsresult -DispatchBluetoothAvrcpHALResult( - BluetoothAvrcpResultHandler* aRes, - void (BluetoothAvrcpResultHandler::*aMethod)(), - BluetoothStatus aStatus) -{ - MOZ_ASSERT(aRes); - - nsRunnable* runnable; - - if (aStatus == STATUS_SUCCESS) { - runnable = new BluetoothAvrcpHALResultRunnable(aRes, aMethod); - } else { - runnable = new BluetoothAvrcpHALErrorRunnable(aRes, - &BluetoothAvrcpResultHandler::OnError, aStatus); - } - nsresult rv = NS_DispatchToMainThread(runnable); - if (NS_FAILED(rv)) { - BT_WARNING("NS_DispatchToMainThread failed: %X", rv); - } - return rv; -} - -// Notification handling -// - -static BluetoothAvrcpNotificationHandler* sAvrcpNotificationHandler; - -struct BluetoothAvrcpCallback -{ - class AvrcpNotificationHandlerWrapper - { - public: - typedef BluetoothAvrcpNotificationHandler ObjectType; - - static ObjectType* GetInstance() - { - MOZ_ASSERT(NS_IsMainThread()); - - return sAvrcpNotificationHandler; - } - }; - - // Notifications - - typedef BluetoothNotificationHALRunnable0 - GetPlayStatusNotification; - - typedef BluetoothNotificationHALRunnable0 - ListPlayerAppAttrNotification; - - typedef BluetoothNotificationHALRunnable1 - ListPlayerAppValuesNotification; - - typedef BluetoothNotificationHALRunnable2, - uint8_t, const BluetoothAvrcpPlayerAttribute*> - GetPlayerAppValueNotification; - - typedef BluetoothNotificationHALRunnable2, - uint8_t, const BluetoothAvrcpPlayerAttribute*> - GetPlayerAppAttrsTextNotification; - - typedef BluetoothNotificationHALRunnable3, - uint8_t, uint8_t, const uint8_t*> - GetPlayerAppValuesTextNotification; - - typedef BluetoothNotificationHALRunnable1 - SetPlayerAppValueNotification; - - typedef BluetoothNotificationHALRunnable2, - uint8_t, const BluetoothAvrcpMediaAttribute*> - GetElementAttrNotification; - - typedef BluetoothNotificationHALRunnable2 - RegisterNotificationNotification; - - typedef BluetoothNotificationHALRunnable2 - RemoteFeatureNotification; - - typedef BluetoothNotificationHALRunnable2 - VolumeChangeNotification; - - typedef BluetoothNotificationHALRunnable2 - PassthroughCmdNotification; - - // Bluedroid AVRCP callbacks - -#if ANDROID_VERSION >= 18 - static void - GetPlayStatus() - { - GetPlayStatusNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::GetPlayStatusNotification); - } - - static void - ListPlayerAppAttr() - { - ListPlayerAppAttrNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification); - } - - static void - ListPlayerAppValues(btrc_player_attr_t aAttrId) - { - ListPlayerAppValuesNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification, - aAttrId); - } - - static void - GetPlayerAppValue(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs) - { - GetPlayerAppValueNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification, - aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); - } - - static void - GetPlayerAppAttrsText(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs) - { - GetPlayerAppAttrsTextNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification, - aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); - } - - static void - GetPlayerAppValuesText(uint8_t aAttrId, uint8_t aNumVals, uint8_t* aVals) - { - GetPlayerAppValuesTextNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification, - aAttrId, aNumVals, ConvertArray(aVals, aNumVals)); - } - - static void - SetPlayerAppValue(btrc_player_settings_t* aVals) - { - SetPlayerAppValueNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification, - *aVals); - } - - static void - GetElementAttr(uint8_t aNumAttrs, btrc_media_attr_t* aAttrs) - { - GetElementAttrNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::GetElementAttrNotification, - aNumAttrs, ConvertArray(aAttrs, aNumAttrs)); - } - - static void - RegisterNotification(btrc_event_id_t aEvent, uint32_t aParam) - { - RegisterNotificationNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::RegisterNotificationNotification, - aEvent, aParam); - } -#endif // ANDROID_VERSION >= 18 - -#if ANDROID_VERSION >= 19 - static void - RemoteFeature(bt_bdaddr_t* aBdAddr, btrc_remote_features_t aFeatures) - { - RemoteFeatureNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::RemoteFeatureNotification, - aBdAddr, aFeatures); - } - - static void - VolumeChange(uint8_t aVolume, uint8_t aCType) - { - VolumeChangeNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::VolumeChangeNotification, - aVolume, aCType); - } - - static void - PassthroughCmd(int aId, int aKeyState) - { - PassthroughCmdNotification::Dispatch( - &BluetoothAvrcpNotificationHandler::PassthroughCmdNotification, - aId, aKeyState); - } -#endif // ANDROID_VERSION >= 19 -}; - -// Interface -// - -BluetoothAvrcpHALInterface::BluetoothAvrcpHALInterface( -#if ANDROID_VERSION >= 18 - const btrc_interface_t* aInterface -#endif - ) -#if ANDROID_VERSION >= 18 -: mInterface(aInterface) -#endif -{ -#if ANDROID_VERSION >= 18 - MOZ_ASSERT(mInterface); -#endif -} - -BluetoothAvrcpHALInterface::~BluetoothAvrcpHALInterface() -{ } - -void -BluetoothAvrcpHALInterface::Init( - BluetoothAvrcpNotificationHandler* aNotificationHandler, - BluetoothAvrcpResultHandler* aRes) -{ -#if ANDROID_VERSION >= 18 - static btrc_callbacks_t sCallbacks = { - sizeof(sCallbacks), -#if ANDROID_VERSION >= 19 - BluetoothAvrcpCallback::RemoteFeature, -#endif - BluetoothAvrcpCallback::GetPlayStatus, - BluetoothAvrcpCallback::ListPlayerAppAttr, - BluetoothAvrcpCallback::ListPlayerAppValues, - BluetoothAvrcpCallback::GetPlayerAppValue, - BluetoothAvrcpCallback::GetPlayerAppAttrsText, - BluetoothAvrcpCallback::GetPlayerAppValuesText, - BluetoothAvrcpCallback::SetPlayerAppValue, - BluetoothAvrcpCallback::GetElementAttr, - BluetoothAvrcpCallback::RegisterNotification -#if ANDROID_VERSION >= 19 - , - BluetoothAvrcpCallback::VolumeChange, - BluetoothAvrcpCallback::PassthroughCmd -#endif - }; -#endif // ANDROID_VERSION >= 18 - - sAvrcpNotificationHandler = aNotificationHandler; - -#if ANDROID_VERSION >= 18 - bt_status_t status = mInterface->init(&sCallbacks); -#else - bt_status_t status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult(aRes, &BluetoothAvrcpResultHandler::Init, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::Cleanup(BluetoothAvrcpResultHandler* aRes) -{ -#if ANDROID_VERSION >= 18 - mInterface->cleanup(); -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult(aRes, &BluetoothAvrcpResultHandler::Cleanup, - STATUS_SUCCESS); - } -} - -void -BluetoothAvrcpHALInterface::GetPlayStatusRsp( - ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos, - BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - btrc_play_status_t playStatus = BTRC_PLAYSTATE_STOPPED; - - if (!(NS_FAILED(Convert(aPlayStatus, playStatus)))) { - status = mInterface->get_play_status_rsp(playStatus, aSongLen, aSongPos); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::ListPlayerAppAttrRsp( - int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs, - BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - ConvertArray pAttrsArray(aPAttrs, aNumAttr); - nsAutoArrayPtr pAttrs; - - if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) { - status = mInterface->list_player_app_attr_rsp(aNumAttr, pAttrs); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::ListPlayerAppValueRsp( - int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes) -{ -#if ANDROID_VERSION >= 18 - bt_status_t status = mInterface->list_player_app_value_rsp(aNumVal, aPVals); -#else - bt_status_t status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::GetPlayerAppValueRsp( - uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues, - BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - btrc_player_settings_t pVals; - - /* FIXME: you need to implement the missing conversion functions */ - NS_NOTREACHED("Conversion function missing"); - - if (false /* TODO: we don't support any player app values currently */) { - status = mInterface->get_player_app_value_rsp(&pVals); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::GetPlayerAppAttrTextRsp( - int aNumAttr, const uint8_t* aIds, const char** aTexts, - BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - btrc_player_setting_text_t* aPAttrs; - - /* FIXME: you need to implement the missing conversion functions */ - NS_NOTREACHED("Conversion function missing"); - - if (false /* TODO: we don't support any attributes currently */) { - status = mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::GetPlayerAppValueTextRsp( - int aNumVal, const uint8_t* aIds, const char** aTexts, - BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - btrc_player_setting_text_t* pVals; - - /* FIXME: you need to implement the missing conversion functions */ - NS_NOTREACHED("Conversion function missing"); - - if (false /* TODO: we don't support any values currently */) { - status = mInterface->get_player_app_value_text_rsp(aNumVal, pVals); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::GetElementAttrRsp( - uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttrs, - BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - ConvertArray pAttrsArray(aAttrs, aNumAttr); - nsAutoArrayPtr pAttrs; - - if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) { - status = mInterface->get_element_attr_rsp(aNumAttr, pAttrs); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::SetPlayerAppValueRsp( - BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - btrc_status_t rspStatus = BTRC_STS_BAD_CMD; // silences compiler warning - - if (NS_SUCCEEDED(Convert(aRspStatus, rspStatus))) { - status = mInterface->set_player_app_value_rsp(rspStatus); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::RegisterNotificationRsp( - BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType, - const BluetoothAvrcpNotificationParam& aParam, - BluetoothAvrcpResultHandler* aRes) -{ - bt_status_t status; - -#if ANDROID_VERSION >= 18 - nsresult rv; - btrc_event_id_t event = { }; - btrc_notification_type_t type = BTRC_NOTIFICATION_TYPE_INTERIM; - btrc_register_notification_t param; - - switch (aEvent) { - case AVRCP_EVENT_PLAY_STATUS_CHANGED: - rv = Convert(aParam.mPlayStatus, param.play_status); - break; - case AVRCP_EVENT_TRACK_CHANGE: - MOZ_ASSERT(sizeof(aParam.mTrack) == sizeof(param.track)); - memcpy(param.track, aParam.mTrack, sizeof(param.track)); - rv = NS_OK; - break; - case AVRCP_EVENT_TRACK_REACHED_END: - NS_NOTREACHED("Unknown conversion"); - rv = NS_ERROR_ILLEGAL_VALUE; - break; - case AVRCP_EVENT_TRACK_REACHED_START: - NS_NOTREACHED("Unknown conversion"); - rv = NS_ERROR_ILLEGAL_VALUE; - break; - case AVRCP_EVENT_PLAY_POS_CHANGED: - param.song_pos = aParam.mSongPos; - rv = NS_OK; - break; - case AVRCP_EVENT_APP_SETTINGS_CHANGED: - NS_NOTREACHED("Unknown conversion"); - rv = NS_ERROR_ILLEGAL_VALUE; - break; - default: - NS_NOTREACHED("Unknown conversion"); - rv = NS_ERROR_ILLEGAL_VALUE; - break; - } - - if (NS_SUCCEEDED(rv) && - NS_SUCCEEDED(Convert(aEvent, event)) && - NS_SUCCEEDED(Convert(aType, type))) { - status = mInterface->register_notification_rsp(event, type, ¶m); - } else { - status = BT_STATUS_PARM_INVALID; - } -#else - status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, - ConvertDefault(status, STATUS_FAIL)); - } -} - -void -BluetoothAvrcpHALInterface::SetVolume(uint8_t aVolume, - BluetoothAvrcpResultHandler* aRes) -{ -#if ANDROID_VERSION >= 19 - bt_status_t status = mInterface->set_volume(aVolume); -#else - bt_status_t status = BT_STATUS_UNSUPPORTED; -#endif - - if (aRes) { - DispatchBluetoothAvrcpHALResult( - aRes, &BluetoothAvrcpResultHandler::SetVolume, - ConvertDefault(status, STATUS_FAIL)); - } -} - -// -// Bluetooth Core Interface -// - typedef BluetoothHALInterfaceRunnable0 BluetoothHALResultRunnable; typedef BluetoothHALInterfaceRunnable1 + BluetoothStatus, BluetoothStatus> BluetoothHALErrorRunnable; static nsresult DispatchBluetoothHALResult(BluetoothResultHandler* aRes, - void (BluetoothResultHandler::*aMethod)(), - BluetoothStatus aStatus) + void (BluetoothResultHandler::*aMethod)(), + BluetoothStatus aStatus) { MOZ_ASSERT(aRes); @@ -3585,9 +84,8 @@ DispatchBluetoothHALResult(BluetoothResultHandler* aRes, if (aStatus == STATUS_SUCCESS) { runnable = new BluetoothHALResultRunnable(aRes, aMethod); } else { - runnable = new - BluetoothHALErrorRunnable(aRes, &BluetoothResultHandler::OnError, - aStatus); + runnable = new BluetoothHALErrorRunnable( + aRes, &BluetoothResultHandler::OnError, aStatus); } nsresult rv = NS_DispatchToMainThread(runnable); if (NS_FAILED(rv)) { @@ -3619,27 +117,27 @@ struct BluetoothCallback // Notifications typedef BluetoothNotificationHALRunnable1 + bool> AdapterStateChangedNotification; typedef BluetoothNotificationHALRunnable3, - BluetoothStatus, int, - const BluetoothProperty*> + BluetoothStatus, int, + nsAutoArrayPtr, + BluetoothStatus, int, + const BluetoothProperty*> AdapterPropertiesNotification; typedef BluetoothNotificationHALRunnable4, - BluetoothStatus, const nsAString&, - int, const BluetoothProperty*> + BluetoothStatus, nsString, int, + nsAutoArrayPtr, + BluetoothStatus, const nsAString&, + int, const BluetoothProperty*> RemoteDevicePropertiesNotification; typedef BluetoothNotificationHALRunnable2, - int, const BluetoothProperty*> + int, + nsAutoArrayPtr, + int, const BluetoothProperty*> DeviceFoundNotification; typedef BluetoothNotificationHALRunnable1 + nsString, nsString, uint32_t, + const nsAString&, const nsAString&> PinRequestNotification; typedef BluetoothNotificationHALRunnable5 + nsString, nsString, uint32_t, + nsString, uint32_t, + const nsAString&, const nsAString&, + uint32_t, const nsAString&> SspRequestNotification; typedef BluetoothNotificationHALRunnable3 + BluetoothStatus, nsString, + BluetoothBondState, + BluetoothStatus, const nsAString&> BondStateChangedNotification; typedef BluetoothNotificationHALRunnable3 + BluetoothStatus, nsString, bool, + BluetoothStatus, const nsAString&> AclStateChangedNotification; typedef BluetoothNotificationHALRunnable3, - uint8_t, uint16_t, const uint8_t*> + uint16_t, nsAutoArrayPtr, + uint8_t, uint16_t, const uint8_t*> DutModeRecvNotification; typedef BluetoothNotificationHALRunnable2 + BluetoothStatus, uint16_t> LeTestModeNotification; // Bluedroid callbacks @@ -3921,7 +419,7 @@ BluetoothHALInterface::Init( if (aRes) { DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Init, - ConvertDefault(status, STATUS_FAIL)); + ConvertDefault(status, STATUS_FAIL)); } } @@ -3932,7 +430,7 @@ BluetoothHALInterface::Cleanup(BluetoothResultHandler* aRes) if (aRes) { DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Cleanup, - STATUS_SUCCESS); + STATUS_SUCCESS); } sNotificationHandler = nullptr; @@ -3945,7 +443,7 @@ BluetoothHALInterface::Enable(BluetoothResultHandler* aRes) if (aRes) { DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Enable, - ConvertDefault(status, STATUS_FAIL)); + ConvertDefault(status, STATUS_FAIL)); } } @@ -3956,7 +454,7 @@ BluetoothHALInterface::Disable(BluetoothResultHandler* aRes) if (aRes) { DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Disable, - ConvertDefault(status, STATUS_FAIL)); + ConvertDefault(status, STATUS_FAIL)); } } @@ -3969,14 +467,14 @@ BluetoothHALInterface::GetAdapterProperties(BluetoothResultHandler* aRes) if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::GetAdapterProperties, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::GetAdapterProperties, + ConvertDefault(status, STATUS_FAIL)); } } void BluetoothHALInterface::GetAdapterProperty(const nsAString& aName, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { int status; bt_property_type_t type; @@ -3992,8 +490,8 @@ BluetoothHALInterface::GetAdapterProperty(const nsAString& aName, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::GetAdapterProperties, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::GetAdapterProperties, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4013,8 +511,8 @@ BluetoothHALInterface::SetAdapterProperty( if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::SetAdapterProperty, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::SetAdapterProperty, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4035,8 +533,8 @@ BluetoothHALInterface::GetRemoteDeviceProperties( if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::GetRemoteDeviceProperties, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::GetRemoteDeviceProperties, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4061,8 +559,8 @@ BluetoothHALInterface::GetRemoteDeviceProperty( if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::GetRemoteDeviceProperty, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::GetRemoteDeviceProperty, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4087,8 +585,8 @@ BluetoothHALInterface::SetRemoteDeviceProperty( if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::SetRemoteDeviceProperty, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::SetRemoteDeviceProperty, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4096,8 +594,8 @@ BluetoothHALInterface::SetRemoteDeviceProperty( void BluetoothHALInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr, - const uint8_t aUuid[16], - BluetoothResultHandler* aRes) + const uint8_t aUuid[16], + BluetoothResultHandler* aRes) { int status; bt_bdaddr_t remoteAddr; @@ -4112,14 +610,14 @@ BluetoothHALInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::GetRemoteServiceRecord, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::GetRemoteServiceRecord, + ConvertDefault(status, STATUS_FAIL)); } } void BluetoothHALInterface::GetRemoteServices(const nsAString& aRemoteAddr, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { int status; bt_bdaddr_t remoteAddr; @@ -4132,8 +630,8 @@ BluetoothHALInterface::GetRemoteServices(const nsAString& aRemoteAddr, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::GetRemoteServices, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::GetRemoteServices, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4146,8 +644,8 @@ BluetoothHALInterface::StartDiscovery(BluetoothResultHandler* aRes) if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::StartDiscovery, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::StartDiscovery, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4158,8 +656,8 @@ BluetoothHALInterface::CancelDiscovery(BluetoothResultHandler* aRes) if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::CancelDiscovery, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::CancelDiscovery, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4167,7 +665,7 @@ BluetoothHALInterface::CancelDiscovery(BluetoothResultHandler* aRes) void BluetoothHALInterface::CreateBond(const nsAString& aBdAddr, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { bt_bdaddr_t bdAddr; int status; @@ -4180,14 +678,14 @@ BluetoothHALInterface::CreateBond(const nsAString& aBdAddr, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::CreateBond, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::CreateBond, + ConvertDefault(status, STATUS_FAIL)); } } void BluetoothHALInterface::RemoveBond(const nsAString& aBdAddr, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { bt_bdaddr_t bdAddr; int status; @@ -4200,14 +698,14 @@ BluetoothHALInterface::RemoveBond(const nsAString& aBdAddr, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::RemoveBond, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::RemoveBond, + ConvertDefault(status, STATUS_FAIL)); } } void BluetoothHALInterface::CancelBond(const nsAString& aBdAddr, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { bt_bdaddr_t bdAddr; int status; @@ -4220,8 +718,8 @@ BluetoothHALInterface::CancelBond(const nsAString& aBdAddr, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::CancelBond, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::CancelBond, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4229,8 +727,8 @@ BluetoothHALInterface::CancelBond(const nsAString& aBdAddr, void BluetoothHALInterface::PinReply(const nsAString& aBdAddr, bool aAccept, - const nsAString& aPinCode, - BluetoothResultHandler* aRes) + const nsAString& aPinCode, + BluetoothResultHandler* aRes) { int status; bt_bdaddr_t bdAddr; @@ -4248,16 +746,16 @@ BluetoothHALInterface::PinReply(const nsAString& aBdAddr, bool aAccept, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::PinReply, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::PinReply, + ConvertDefault(status, STATUS_FAIL)); } } void BluetoothHALInterface::SspReply(const nsAString& aBdAddr, - const nsAString& aVariant, - bool aAccept, uint32_t aPasskey, - BluetoothResultHandler* aRes) + const nsAString& aVariant, + bool aAccept, uint32_t aPasskey, + BluetoothResultHandler* aRes) { int status; bt_bdaddr_t bdAddr; @@ -4274,8 +772,8 @@ BluetoothHALInterface::SspReply(const nsAString& aBdAddr, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::SspReply, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::SspReply, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4283,7 +781,7 @@ BluetoothHALInterface::SspReply(const nsAString& aBdAddr, void BluetoothHALInterface::DutModeConfigure(bool aEnable, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { int status; uint8_t enable; @@ -4296,21 +794,21 @@ BluetoothHALInterface::DutModeConfigure(bool aEnable, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::DutModeConfigure, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::DutModeConfigure, + ConvertDefault(status, STATUS_FAIL)); } } void BluetoothHALInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { int status = mInterface->dut_mode_send(aOpcode, aBuf, aLen); if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::DutModeSend, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::DutModeSend, + ConvertDefault(status, STATUS_FAIL)); } } @@ -4318,7 +816,7 @@ BluetoothHALInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen void BluetoothHALInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, - BluetoothResultHandler* aRes) + BluetoothResultHandler* aRes) { #if ANDROID_VERSION >= 18 int status = mInterface->le_test_mode(aOpcode, aBuf, aLen); @@ -4328,8 +826,8 @@ BluetoothHALInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen, if (aRes) { DispatchBluetoothHALResult(aRes, - &BluetoothResultHandler::LeTestMode, - ConvertDefault(status, STATUS_FAIL)); + &BluetoothResultHandler::LeTestMode, + ConvertDefault(status, STATUS_FAIL)); } } diff --git a/dom/bluetooth/bluedroid/BluetoothHALInterface.h b/dom/bluetooth/bluedroid/BluetoothHALInterface.h index b1b793bc801e..9c81eab79c7a 100644 --- a/dom/bluetooth/bluedroid/BluetoothHALInterface.h +++ b/dom/bluetooth/bluedroid/BluetoothHALInterface.h @@ -8,224 +8,10 @@ #define mozilla_dom_bluetooth_bluedroid_bluetoothhalinterface_h__ #include -#include -#include -#include -#if ANDROID_VERSION >= 18 -#include -#endif #include "BluetoothInterface.h" BEGIN_BLUETOOTH_NAMESPACE -class BluetoothHALInterface; - -// -// Socket Interface -// - -class BluetoothSocketHALInterface MOZ_FINAL - : public BluetoothSocketInterface -{ -public: - friend class BluetoothHALInterface; - - void Listen(BluetoothSocketType aType, - const nsAString& aServiceName, - const uint8_t aServiceUuid[16], - int aChannel, bool aEncrypt, bool aAuth, - BluetoothSocketResultHandler* aRes); - - void Connect(const nsAString& aBdAddr, - BluetoothSocketType aType, - const uint8_t aUuid[16], - int aChannel, bool aEncrypt, bool aAuth, - BluetoothSocketResultHandler* aRes); - - void Accept(int aFd, BluetoothSocketResultHandler* aRes); - -protected: - BluetoothSocketHALInterface(const btsock_interface_t* aInterface); - ~BluetoothSocketHALInterface(); - -private: - const btsock_interface_t* mInterface; -}; - -// -// Handsfree Interface -// - -class BluetoothHandsfreeHALInterface MOZ_FINAL - : public BluetoothHandsfreeInterface -{ -public: - friend class BluetoothHALInterface; - - void Init(BluetoothHandsfreeNotificationHandler* aNotificationHandler, - BluetoothHandsfreeResultHandler* aRes); - void Cleanup(BluetoothHandsfreeResultHandler* aRes); - - /* Connect / Disconnect */ - - void Connect(const nsAString& aBdAddr, - BluetoothHandsfreeResultHandler* aRes); - void Disconnect(const nsAString& aBdAddr, - BluetoothHandsfreeResultHandler* aRes); - void ConnectAudio(const nsAString& aBdAddr, - BluetoothHandsfreeResultHandler* aRes); - void DisconnectAudio(const nsAString& aBdAddr, - BluetoothHandsfreeResultHandler* aRes); - - /* Voice Recognition */ - - void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); - void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); - - /* Volume */ - - void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume, - BluetoothHandsfreeResultHandler* aRes); - - /* Device status */ - - void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState, - BluetoothHandsfreeServiceType aSvcType, - int aSignal, int aBattChg, - BluetoothHandsfreeResultHandler* aRes); - - /* Responses */ - - void CopsResponse(const char* aCops, - BluetoothHandsfreeResultHandler* aRes); - void CindResponse(int aSvc, int aNumActive, int aNumHeld, - BluetoothHandsfreeCallState aCallSetupState, int aSignal, - int aRoam, int aBattChg, - BluetoothHandsfreeResultHandler* aRes); - void FormattedAtResponse(const char* aRsp, - BluetoothHandsfreeResultHandler* aRes); - void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, - BluetoothHandsfreeResultHandler* aRes); - void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir, - BluetoothHandsfreeCallState aState, - BluetoothHandsfreeCallMode aMode, - BluetoothHandsfreeCallMptyType aMpty, - const nsAString& aNumber, - BluetoothHandsfreeCallAddressType aType, - BluetoothHandsfreeResultHandler* aRes); - - /* Phone State */ - - void PhoneStateChange(int aNumActive, int aNumHeld, - BluetoothHandsfreeCallState aCallSetupState, - const nsAString& aNumber, - BluetoothHandsfreeCallAddressType aType, - BluetoothHandsfreeResultHandler* aRes); - -protected: - BluetoothHandsfreeHALInterface(const bthf_interface_t* aInterface); - ~BluetoothHandsfreeHALInterface(); - -private: - const bthf_interface_t* mInterface; -}; - -// -// Bluetooth Advanced Audio Interface -// - -class BluetoothA2dpHALInterface MOZ_FINAL - : public BluetoothA2dpInterface -{ -public: - friend class BluetoothHALInterface; - - void Init(BluetoothA2dpNotificationHandler* aNotificationHandler, - BluetoothA2dpResultHandler* aRes); - void Cleanup(BluetoothA2dpResultHandler* aRes); - - void Connect(const nsAString& aBdAddr, - BluetoothA2dpResultHandler* aRes); - void Disconnect(const nsAString& aBdAddr, - BluetoothA2dpResultHandler* aRes); - -protected: - BluetoothA2dpHALInterface(const btav_interface_t* aInterface); - ~BluetoothA2dpHALInterface(); - -private: - const btav_interface_t* mInterface; -}; - -// -// Bluetooth AVRCP Interface -// - -class BluetoothAvrcpHALInterface MOZ_FINAL - : public BluetoothAvrcpInterface -{ -public: - friend class BluetoothHALInterface; - - void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler, - BluetoothAvrcpResultHandler* aRes); - void Cleanup(BluetoothAvrcpResultHandler* aRes); - - void GetPlayStatusRsp(ControlPlayStatus aPlayStatus, - uint32_t aSongLen, uint32_t aSongPos, - BluetoothAvrcpResultHandler* aRes); - - void ListPlayerAppAttrRsp(int aNumAttr, - const BluetoothAvrcpPlayerAttribute* aPAttrs, - BluetoothAvrcpResultHandler* aRes); - void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals, - BluetoothAvrcpResultHandler* aRes); - - /* TODO: redesign this interface once we actually use it */ - void GetPlayerAppValueRsp(uint8_t aNumAttrs, - const uint8_t* aIds, const uint8_t* aValues, - BluetoothAvrcpResultHandler* aRes); - /* TODO: redesign this interface once we actually use it */ - void GetPlayerAppAttrTextRsp(int aNumAttr, - const uint8_t* aIds, const char** aTexts, - BluetoothAvrcpResultHandler* aRes); - /* TODO: redesign this interface once we actually use it */ - void GetPlayerAppValueTextRsp(int aNumVal, - const uint8_t* aIds, const char** aTexts, - BluetoothAvrcpResultHandler* aRes); - - void GetElementAttrRsp(uint8_t aNumAttr, - const BluetoothAvrcpElementAttribute* aAttr, - BluetoothAvrcpResultHandler* aRes); - - void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus, - BluetoothAvrcpResultHandler* aRes); - - void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent, - BluetoothAvrcpNotification aType, - const BluetoothAvrcpNotificationParam& aParam, - BluetoothAvrcpResultHandler* aRes); - - void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes); - -protected: - BluetoothAvrcpHALInterface( -#if ANDROID_VERSION >= 18 - const btrc_interface_t* aInterface -#endif - ); - ~BluetoothAvrcpHALInterface(); - -private: -#if ANDROID_VERSION >= 18 - const btrc_interface_t* mInterface; -#endif -}; - -// -// Bluetooth Core Interface -// - class BluetoothHALInterface MOZ_FINAL : public BluetoothInterface { public: diff --git a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp new file mode 100644 index 000000000000..b996363d59b8 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp @@ -0,0 +1,616 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "BluetoothHandsfreeHALInterface.h" +#include "BluetoothHALHelpers.h" + +BEGIN_BLUETOOTH_NAMESPACE + +typedef + BluetoothHALInterfaceRunnable0 + BluetoothHandsfreeHALResultRunnable; + +typedef + BluetoothHALInterfaceRunnable1 + BluetoothHandsfreeHALErrorRunnable; + +static nsresult +DispatchBluetoothHandsfreeHALResult( + BluetoothHandsfreeResultHandler* aRes, + void (BluetoothHandsfreeResultHandler::*aMethod)(), + BluetoothStatus aStatus) +{ + MOZ_ASSERT(aRes); + + nsRunnable* runnable; + + if (aStatus == STATUS_SUCCESS) { + runnable = new BluetoothHandsfreeHALResultRunnable(aRes, aMethod); + } else { + runnable = new BluetoothHandsfreeHALErrorRunnable(aRes, + &BluetoothHandsfreeResultHandler::OnError, aStatus); + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + return rv; +} + +// Notification handling +// + +static BluetoothHandsfreeNotificationHandler* sHandsfreeNotificationHandler; + +struct BluetoothHandsfreeHALCallback +{ + class HandsfreeNotificationHandlerWrapper + { + public: + typedef BluetoothHandsfreeNotificationHandler ObjectType; + + static ObjectType* GetInstance() + { + MOZ_ASSERT(NS_IsMainThread()); + + return sHandsfreeNotificationHandler; + } + }; + + // Notifications + + typedef BluetoothNotificationHALRunnable2< + HandsfreeNotificationHandlerWrapper, void, + BluetoothHandsfreeConnectionState, nsString, + BluetoothHandsfreeConnectionState, const nsAString&> + ConnectionStateNotification; + + typedef BluetoothNotificationHALRunnable2< + HandsfreeNotificationHandlerWrapper, void, + BluetoothHandsfreeAudioState, nsString, + BluetoothHandsfreeAudioState, const nsAString&> + AudioStateNotification; + + typedef BluetoothNotificationHALRunnable1< + HandsfreeNotificationHandlerWrapper, void, + BluetoothHandsfreeVoiceRecognitionState> + VoiceRecognitionNotification; + + typedef BluetoothNotificationHALRunnable0< + HandsfreeNotificationHandlerWrapper, void> + AnswerCallNotification; + + typedef BluetoothNotificationHALRunnable0< + HandsfreeNotificationHandlerWrapper, void> + HangupCallNotification; + + typedef BluetoothNotificationHALRunnable2< + HandsfreeNotificationHandlerWrapper, void, + BluetoothHandsfreeVolumeType, int> + VolumeNotification; + + typedef BluetoothNotificationHALRunnable1< + HandsfreeNotificationHandlerWrapper, void, nsString, const nsAString&> + DialCallNotification; + + typedef BluetoothNotificationHALRunnable1< + HandsfreeNotificationHandlerWrapper, void, char> + DtmfNotification; + + typedef BluetoothNotificationHALRunnable1< + HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeNRECState> + NRECNotification; + + typedef BluetoothNotificationHALRunnable1< + HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeCallHoldType> + CallHoldNotification; + + typedef BluetoothNotificationHALRunnable0< + HandsfreeNotificationHandlerWrapper, void> + CnumNotification; + + typedef BluetoothNotificationHALRunnable0< + HandsfreeNotificationHandlerWrapper, void> + CindNotification; + + typedef BluetoothNotificationHALRunnable0< + HandsfreeNotificationHandlerWrapper, void> + CopsNotification; + + typedef BluetoothNotificationHALRunnable0< + HandsfreeNotificationHandlerWrapper, void> + ClccNotification; + + typedef BluetoothNotificationHALRunnable1< + HandsfreeNotificationHandlerWrapper, void, nsCString, const nsACString&> + UnknownAtNotification; + + typedef BluetoothNotificationHALRunnable0< + HandsfreeNotificationHandlerWrapper, void> + KeyPressedNotification; + + // Bluedroid Handsfree callbacks + + static void + ConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddr) + { + ConnectionStateNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification, + aState, aBdAddr); + } + + static void + AudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddr) + { + AudioStateNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::AudioStateNotification, + aState, aBdAddr); + } + + static void + VoiceRecognition(bthf_vr_state_t aState) + { + VoiceRecognitionNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification, + aState); + } + + static void + AnswerCall() + { + AnswerCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::AnswerCallNotification); + } + + static void + HangupCall() + { + HangupCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::HangupCallNotification); + } + + static void + Volume(bthf_volume_type_t aType, int aVolume) + { + VolumeNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VolumeNotification, + aType, aVolume); + } + + static void + DialCall(char* aNumber) + { + DialCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DialCallNotification, aNumber); + } + + static void + Dtmf(char aDtmf) + { + DtmfNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DtmfNotification, aDtmf); + } + + static void + NoiseReductionEchoCancellation(bthf_nrec_t aNrec) + { + NRECNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::NRECNotification, aNrec); + } + + static void + CallHold(bthf_chld_type_t aChld) + { + CallHoldNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CallHoldNotification, aChld); + } + + static void + Cnum() + { + CnumNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CnumNotification); + } + + static void + Cind() + { + CindNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CindNotification); + } + + static void + Cops() + { + CopsNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CopsNotification); + } + + static void + Clcc() + { + ClccNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::ClccNotification); + } + + static void + UnknownAt(char* aAtString) + { + UnknownAtNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::UnknownAtNotification, + aAtString); + } + + static void + KeyPressed() + { + KeyPressedNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::KeyPressedNotification); + } +}; + +// Interface +// + +BluetoothHandsfreeHALInterface::BluetoothHandsfreeHALInterface( + const bthf_interface_t* aInterface) +: mInterface(aInterface) +{ + MOZ_ASSERT(mInterface); +} + +BluetoothHandsfreeHALInterface::~BluetoothHandsfreeHALInterface() +{ } + +void +BluetoothHandsfreeHALInterface::Init( + BluetoothHandsfreeNotificationHandler* aNotificationHandler, + BluetoothHandsfreeResultHandler* aRes) +{ + static bthf_callbacks_t sCallbacks = { + sizeof(sCallbacks), + BluetoothHandsfreeHALCallback::ConnectionState, + BluetoothHandsfreeHALCallback::AudioState, + BluetoothHandsfreeHALCallback::VoiceRecognition, + BluetoothHandsfreeHALCallback::AnswerCall, + BluetoothHandsfreeHALCallback::HangupCall, + BluetoothHandsfreeHALCallback::Volume, + BluetoothHandsfreeHALCallback::DialCall, + BluetoothHandsfreeHALCallback::Dtmf, + BluetoothHandsfreeHALCallback::NoiseReductionEchoCancellation, + BluetoothHandsfreeHALCallback::CallHold, + BluetoothHandsfreeHALCallback::Cnum, + BluetoothHandsfreeHALCallback::Cind, + BluetoothHandsfreeHALCallback::Cops, + BluetoothHandsfreeHALCallback::Clcc, + BluetoothHandsfreeHALCallback::UnknownAt, + BluetoothHandsfreeHALCallback::KeyPressed + }; + + sHandsfreeNotificationHandler = aNotificationHandler; + + bt_status_t status = mInterface->init(&sCallbacks); + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::Init, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::Cleanup( + BluetoothHandsfreeResultHandler* aRes) +{ + mInterface->cleanup(); + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::Cleanup, STATUS_SUCCESS); + } +} + +/* Connect / Disconnect */ + +void +BluetoothHandsfreeHALInterface::Connect( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->connect(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::Connect, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::Disconnect( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->disconnect(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::Disconnect, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::ConnectAudio( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->connect_audio(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::ConnectAudio, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::DisconnectAudio( + const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->disconnect_audio(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::DisconnectAudio, + ConvertDefault(status, STATUS_FAIL)); + } +} + +/* Voice Recognition */ + +void +BluetoothHandsfreeHALInterface::StartVoiceRecognition( + BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status = mInterface->start_voice_recognition(); + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::StopVoiceRecognition( + BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status = mInterface->stop_voice_recognition(); + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition, + ConvertDefault(status, STATUS_FAIL)); + } +} + +/* Volume */ + +void +BluetoothHandsfreeHALInterface::VolumeControl( + BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bthf_volume_type_t type = BTHF_VOLUME_TYPE_SPK; + + if (NS_SUCCEEDED(Convert(aType, type))) { + status = mInterface->volume_control(type, aVolume); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::VolumeControl, + ConvertDefault(status, STATUS_FAIL)); + } +} + +/* Device status */ + +void +BluetoothHandsfreeHALInterface::DeviceStatusNotification( + BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, int aSignal, + int aBattChg, BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bthf_network_state_t ntkState = BTHF_NETWORK_STATE_NOT_AVAILABLE; + bthf_service_type_t svcType = BTHF_SERVICE_TYPE_HOME; + + if (NS_SUCCEEDED(Convert(aNtkState, ntkState)) && + NS_SUCCEEDED(Convert(aSvcType, svcType))) { + status = mInterface->device_status_notification(ntkState, svcType, + aSignal, aBattChg); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::DeviceStatusNotification, + ConvertDefault(status, STATUS_FAIL)); + } +} + +/* Responses */ + +void +BluetoothHandsfreeHALInterface::CopsResponse( + const char* aCops, BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status = mInterface->cops_response(aCops); + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::CopsResponse, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::CindResponse( + int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + int aSignal, int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE; + + if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState))) { + status = mInterface->cind_response(aSvc, aNumActive, aNumHeld, + callSetupState, aSignal, + aRoam, aBattChg); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::CindResponse, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::FormattedAtResponse( + const char* aRsp, BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status = mInterface->formatted_at_response(aRsp); + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::AtResponse( + BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bthf_at_response_t responseCode = BTHF_AT_RESPONSE_ERROR; + + if (NS_SUCCEEDED(Convert(aResponseCode, responseCode))) { + status = mInterface->at_response(responseCode, aErrorCode); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::AtResponse, + ConvertDefault(status, STATUS_FAIL)); + } +} + +void +BluetoothHandsfreeHALInterface::ClccResponse( + int aIndex, + BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bthf_call_direction_t dir = BTHF_CALL_DIRECTION_OUTGOING; + bthf_call_state_t state = BTHF_CALL_STATE_ACTIVE; + bthf_call_mode_t mode = BTHF_CALL_TYPE_VOICE; + bthf_call_mpty_type_t mpty = BTHF_CALL_MPTY_TYPE_SINGLE; + bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN; + + if (NS_SUCCEEDED(Convert(aDir, dir)) && + NS_SUCCEEDED(Convert(aState, state)) && + NS_SUCCEEDED(Convert(aMode, mode)) && + NS_SUCCEEDED(Convert(aMpty, mpty)) && + NS_SUCCEEDED(Convert(aType, type))) { + status = mInterface->clcc_response(aIndex, dir, state, mode, mpty, + NS_ConvertUTF16toUTF8(aNumber).get(), + type); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::ClccResponse, + ConvertDefault(status, STATUS_FAIL)); + } +} + +/* Phone State */ + +void +BluetoothHandsfreeHALInterface::PhoneStateChange(int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes) +{ + bt_status_t status; + bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE; + bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN; + + if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState)) && + NS_SUCCEEDED(Convert(aType, type))) { + status = mInterface->phone_state_change( + aNumActive, aNumHeld, callSetupState, + NS_ConvertUTF16toUTF8(aNumber).get(), type); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothHandsfreeHALResult( + aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange, + ConvertDefault(status, STATUS_FAIL)); + } +} + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h new file mode 100644 index 000000000000..f53d4251fb65 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h @@ -0,0 +1,95 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothhandsfreehalinterface_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothhandsfreehalinterface_h__ + +#include +#include +#include "BluetoothCommon.h" +#include "BluetoothInterface.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothHALInterface; + +class BluetoothHandsfreeHALInterface MOZ_FINAL + : public BluetoothHandsfreeInterface +{ +public: + friend class BluetoothHALInterface; + + void Init(BluetoothHandsfreeNotificationHandler* aNotificationHandler, + BluetoothHandsfreeResultHandler* aRes); + void Cleanup(BluetoothHandsfreeResultHandler* aRes); + + /* Connect / Disconnect */ + + void Connect(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void Disconnect(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void ConnectAudio(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + void DisconnectAudio(const nsAString& aBdAddr, + BluetoothHandsfreeResultHandler* aRes); + + /* Voice Recognition */ + + void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); + void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes); + + /* Volume */ + + void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume, + BluetoothHandsfreeResultHandler* aRes); + + /* Device status */ + + void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState, + BluetoothHandsfreeServiceType aSvcType, + int aSignal, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + + /* Responses */ + + void CopsResponse(const char* aCops, + BluetoothHandsfreeResultHandler* aRes); + void CindResponse(int aSvc, int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, int aSignal, + int aRoam, int aBattChg, + BluetoothHandsfreeResultHandler* aRes); + void FormattedAtResponse(const char* aRsp, + BluetoothHandsfreeResultHandler* aRes); + void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode, + BluetoothHandsfreeResultHandler* aRes); + void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir, + BluetoothHandsfreeCallState aState, + BluetoothHandsfreeCallMode aMode, + BluetoothHandsfreeCallMptyType aMpty, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + + /* Phone State */ + + void PhoneStateChange(int aNumActive, int aNumHeld, + BluetoothHandsfreeCallState aCallSetupState, + const nsAString& aNumber, + BluetoothHandsfreeCallAddressType aType, + BluetoothHandsfreeResultHandler* aRes); + +protected: + BluetoothHandsfreeHALInterface(const bthf_interface_t* aInterface); + ~BluetoothHandsfreeHALInterface(); + +private: + const bthf_interface_t* mInterface; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff --git a/dom/bluetooth/bluedroid/BluetoothSocketHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothSocketHALInterface.cpp new file mode 100644 index 000000000000..8268df279120 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothSocketHALInterface.cpp @@ -0,0 +1,480 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "BluetoothSocketHALInterface.h" +#include +#include +#include +#include "BluetoothHALHelpers.h" +#include "nsXULAppAPI.h" + +BEGIN_BLUETOOTH_NAMESPACE + +typedef + BluetoothHALInterfaceRunnable1 + BluetoothSocketHALIntResultRunnable; + +typedef + BluetoothHALInterfaceRunnable3 + BluetoothSocketHALIntStringIntResultRunnable; + +typedef + BluetoothHALInterfaceRunnable1 + BluetoothSocketHALErrorRunnable; + +static nsresult +DispatchBluetoothSocketHALResult( + BluetoothSocketResultHandler* aRes, + void (BluetoothSocketResultHandler::*aMethod)(int), int aArg, + BluetoothStatus aStatus) +{ + MOZ_ASSERT(aRes); + + nsRunnable* runnable; + + if (aStatus == STATUS_SUCCESS) { + runnable = new BluetoothSocketHALIntResultRunnable(aRes, aMethod, aArg); + } else { + runnable = new BluetoothSocketHALErrorRunnable(aRes, + &BluetoothSocketResultHandler::OnError, aStatus); + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + return rv; +} + +static nsresult +DispatchBluetoothSocketHALResult( + BluetoothSocketResultHandler* aRes, + void (BluetoothSocketResultHandler::*aMethod)(int, const nsAString&, int), + int aArg1, const nsAString& aArg2, int aArg3, BluetoothStatus aStatus) +{ + MOZ_ASSERT(aRes); + + nsRunnable* runnable; + + if (aStatus == STATUS_SUCCESS) { + runnable = new BluetoothSocketHALIntStringIntResultRunnable( + aRes, aMethod, aArg1, aArg2, aArg3); + } else { + runnable = new BluetoothSocketHALErrorRunnable(aRes, + &BluetoothSocketResultHandler::OnError, aStatus); + } + nsresult rv = NS_DispatchToMainThread(runnable); + if (NS_FAILED(rv)) { + BT_WARNING("NS_DispatchToMainThread failed: %X", rv); + } + return rv; +} + +void +BluetoothSocketHALInterface::Listen(BluetoothSocketType aType, + const nsAString& aServiceName, + const uint8_t aServiceUuid[16], + int aChannel, bool aEncrypt, + bool aAuth, + BluetoothSocketResultHandler* aRes) +{ + int fd; + bt_status_t status; + btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning + + if (NS_SUCCEEDED(Convert(aType, type))) { + status = mInterface->listen(type, + NS_ConvertUTF16toUTF8(aServiceName).get(), + aServiceUuid, aChannel, &fd, + (BTSOCK_FLAG_ENCRYPT * aEncrypt) | + (BTSOCK_FLAG_AUTH * aAuth)); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (aRes) { + DispatchBluetoothSocketHALResult( + aRes, &BluetoothSocketResultHandler::Listen, fd, + ConvertDefault(status, STATUS_FAIL)); + } +} + +#define CMSGHDR_CONTAINS_FD(_cmsghdr) \ + ( ((_cmsghdr)->cmsg_level == SOL_SOCKET) && \ + ((_cmsghdr)->cmsg_type == SCM_RIGHTS) ) + +/* |SocketMessageWatcher| receives Bluedroid's socket setup + * messages on the I/O thread. You need to inherit from this + * class to make use of it. + * + * Bluedroid sends two socket info messages (20 bytes) at + * the beginning of a connection to both peers. + * + * - 1st message: [channel:4] + * - 2nd message: [size:2][bd address:6][channel:4][connection status:4] + * + * On the server side, the second message will contain a + * socket file descriptor for the connection. The client + * uses the original file descriptor. + */ +class SocketMessageWatcher : public MessageLoopForIO::Watcher +{ +public: + static const unsigned char MSG1_SIZE = 4; + static const unsigned char MSG2_SIZE = 16; + + static const unsigned char OFF_CHANNEL1 = 0; + static const unsigned char OFF_SIZE = 4; + static const unsigned char OFF_BDADDRESS = 6; + static const unsigned char OFF_CHANNEL2 = 12; + static const unsigned char OFF_STATUS = 16; + + SocketMessageWatcher(int aFd) + : mFd(aFd) + , mClientFd(-1) + , mLen(0) + { } + + virtual ~SocketMessageWatcher() + { } + + virtual void Proceed(BluetoothStatus aStatus) = 0; + + void OnFileCanReadWithoutBlocking(int aFd) MOZ_OVERRIDE + { + BluetoothStatus status; + + switch (mLen) { + case 0: + status = RecvMsg1(); + break; + case MSG1_SIZE: + status = RecvMsg2(); + break; + default: + /* message-size error */ + status = STATUS_FAIL; + break; + } + + if (IsComplete() || status != STATUS_SUCCESS) { + mWatcher.StopWatchingFileDescriptor(); + Proceed(status); + } + } + + void OnFileCanWriteWithoutBlocking(int aFd) MOZ_OVERRIDE + { } + + void Watch() + { + MessageLoopForIO::current()->WatchFileDescriptor( + mFd, + true, + MessageLoopForIO::WATCH_READ, + &mWatcher, + this); + } + + bool IsComplete() const + { + return mLen == (MSG1_SIZE + MSG2_SIZE); + } + + int GetFd() const + { + return mFd; + } + + int32_t GetChannel1() const + { + return ReadInt32(OFF_CHANNEL1); + } + + int32_t GetSize() const + { + return ReadInt16(OFF_SIZE); + } + + nsString GetBdAddress() const + { + nsString bdAddress; + ReadBdAddress(OFF_BDADDRESS, bdAddress); + return bdAddress; + } + + int32_t GetChannel2() const + { + return ReadInt32(OFF_CHANNEL2); + } + + int32_t GetConnectionStatus() const + { + return ReadInt32(OFF_STATUS); + } + + int GetClientFd() const + { + return mClientFd; + } + +private: + BluetoothStatus RecvMsg1() + { + struct iovec iv; + memset(&iv, 0, sizeof(iv)); + iv.iov_base = mBuf; + iv.iov_len = MSG1_SIZE; + + struct msghdr msg; + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iv; + msg.msg_iovlen = 1; + + ssize_t res = TEMP_FAILURE_RETRY(recvmsg(mFd, &msg, MSG_NOSIGNAL)); + if (res < 0) { + return STATUS_FAIL; + } + + mLen += res; + + return STATUS_SUCCESS; + } + + BluetoothStatus RecvMsg2() + { + struct iovec iv; + memset(&iv, 0, sizeof(iv)); + iv.iov_base = mBuf + MSG1_SIZE; + iv.iov_len = MSG2_SIZE; + + struct msghdr msg; + struct cmsghdr cmsgbuf[2 * sizeof(cmsghdr) + 0x100]; + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iv; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + + ssize_t res = TEMP_FAILURE_RETRY(recvmsg(mFd, &msg, MSG_NOSIGNAL)); + if (res < 0) { + return STATUS_FAIL; + } + + mLen += res; + + if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) { + return STATUS_FAIL; + } + + struct cmsghdr *cmsgptr = CMSG_FIRSTHDR(&msg); + + // Extract client fd from message header + for (; cmsgptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + if (CMSGHDR_CONTAINS_FD(cmsgptr)) { + // if multiple file descriptors have been sent, we close + // all but the final one. + if (mClientFd != -1) { + TEMP_FAILURE_RETRY(close(mClientFd)); + } + // retrieve sent client fd + mClientFd = *(static_cast(CMSG_DATA(cmsgptr))); + } + } + + return STATUS_SUCCESS; + } + + int16_t ReadInt16(unsigned long aOffset) const + { + /* little-endian buffer */ + return (static_cast(mBuf[aOffset + 1]) << 8) | + static_cast(mBuf[aOffset]); + } + + int32_t ReadInt32(unsigned long aOffset) const + { + /* little-endian buffer */ + return (static_cast(mBuf[aOffset + 3]) << 24) | + (static_cast(mBuf[aOffset + 2]) << 16) | + (static_cast(mBuf[aOffset + 1]) << 8) | + static_cast(mBuf[aOffset]); + } + + void ReadBdAddress(unsigned long aOffset, nsAString& aBdAddress) const + { + const bt_bdaddr_t* bdAddress = + reinterpret_cast(mBuf+aOffset); + + if (NS_FAILED(Convert(*bdAddress, aBdAddress))) { + aBdAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE); + } + } + + MessageLoopForIO::FileDescriptorWatcher mWatcher; + int mFd; + int mClientFd; + unsigned char mLen; + uint8_t mBuf[MSG1_SIZE + MSG2_SIZE]; +}; + +/* |SocketMessageWatcherTask| starts a SocketMessageWatcher + * on the I/O task + */ +class SocketMessageWatcherTask MOZ_FINAL : public Task +{ +public: + SocketMessageWatcherTask(SocketMessageWatcher* aWatcher) + : mWatcher(aWatcher) + { + MOZ_ASSERT(mWatcher); + } + + void Run() MOZ_OVERRIDE + { + mWatcher->Watch(); + } + +private: + SocketMessageWatcher* mWatcher; +}; + +/* |DeleteTask| deletes a class instance on the I/O thread + */ +template +class DeleteTask MOZ_FINAL : public Task +{ +public: + DeleteTask(T* aPtr) + : mPtr(aPtr) + { } + + void Run() MOZ_OVERRIDE + { + mPtr = nullptr; + } + +private: + nsAutoPtr mPtr; +}; + +/* |ConnectWatcher| specializes SocketMessageWatcher for + * connect operations by reading the socket messages from + * Bluedroid and forwarding the connected socket to the + * resource handler. + */ +class ConnectWatcher MOZ_FINAL : public SocketMessageWatcher +{ +public: + ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes) + : SocketMessageWatcher(aFd) + , mRes(aRes) + { } + + void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE + { + if (mRes) { + DispatchBluetoothSocketHALResult( + mRes, &BluetoothSocketResultHandler::Connect, GetFd(), + GetBdAddress(), GetConnectionStatus(), aStatus); + } + MessageLoopForIO::current()->PostTask( + FROM_HERE, new DeleteTask(this)); + } + +private: + nsRefPtr mRes; +}; + +void +BluetoothSocketHALInterface::Connect(const nsAString& aBdAddr, + BluetoothSocketType aType, + const uint8_t aUuid[16], + int aChannel, bool aEncrypt, + bool aAuth, + BluetoothSocketResultHandler* aRes) +{ + int fd; + bt_status_t status; + bt_bdaddr_t bdAddr; + btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) && + NS_SUCCEEDED(Convert(aType, type))) { + status = mInterface->connect(&bdAddr, type, aUuid, aChannel, &fd, + (BTSOCK_FLAG_ENCRYPT * aEncrypt) | + (BTSOCK_FLAG_AUTH * aAuth)); + } else { + status = BT_STATUS_PARM_INVALID; + } + + if (status == BT_STATUS_SUCCESS) { + /* receive Bluedroid's socket-setup messages */ + Task* t = new SocketMessageWatcherTask(new ConnectWatcher(fd, aRes)); + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t); + } else if (aRes) { + DispatchBluetoothSocketHALResult( + aRes, &BluetoothSocketResultHandler::Connect, -1, EmptyString(), 0, + ConvertDefault(status, STATUS_FAIL)); + } +} + +/* Specializes SocketMessageWatcher for Accept operations by + * reading the socket messages from Bluedroid and forwarding + * the received client socket to the resource handler. The + * first message is received immediately. When there's a new + * connection, Bluedroid sends the 2nd message with the socket + * info and socket file descriptor. + */ +class AcceptWatcher MOZ_FINAL : public SocketMessageWatcher +{ +public: + AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes) + : SocketMessageWatcher(aFd) + , mRes(aRes) + { + /* not supplying a result handler leaks received file descriptor */ + MOZ_ASSERT(mRes); + } + + void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE + { + if (mRes) { + DispatchBluetoothSocketHALResult( + mRes, &BluetoothSocketResultHandler::Accept, GetClientFd(), + GetBdAddress(), GetConnectionStatus(), aStatus); + } + MessageLoopForIO::current()->PostTask( + FROM_HERE, new DeleteTask(this)); + } + +private: + nsRefPtr mRes; +}; + +void +BluetoothSocketHALInterface::Accept(int aFd, + BluetoothSocketResultHandler* aRes) +{ + /* receive Bluedroid's socket-setup messages and client fd */ + Task* t = new SocketMessageWatcherTask(new AcceptWatcher(aFd, aRes)); + XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t); +} + +BluetoothSocketHALInterface::BluetoothSocketHALInterface( + const btsock_interface_t* aInterface) +: mInterface(aInterface) +{ + MOZ_ASSERT(mInterface); +} + +BluetoothSocketHALInterface::~BluetoothSocketHALInterface() +{ } + +END_BLUETOOTH_NAMESPACE diff --git a/dom/bluetooth/bluedroid/BluetoothSocketHALInterface.h b/dom/bluetooth/bluedroid/BluetoothSocketHALInterface.h new file mode 100644 index 000000000000..0aef3d6929b8 --- /dev/null +++ b/dom/bluetooth/bluedroid/BluetoothSocketHALInterface.h @@ -0,0 +1,49 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_bluetooth_bluedroid_bluetoothsockethalinterface_h__ +#define mozilla_dom_bluetooth_bluedroid_bluetoothsockethalinterface_h__ + +#include +#include +#include "BluetoothCommon.h" +#include "BluetoothInterface.h" + +BEGIN_BLUETOOTH_NAMESPACE + +class BluetoothHALInterface; + +class BluetoothSocketHALInterface MOZ_FINAL + : public BluetoothSocketInterface +{ +public: + friend class BluetoothHALInterface; + + void Listen(BluetoothSocketType aType, + const nsAString& aServiceName, + const uint8_t aServiceUuid[16], + int aChannel, bool aEncrypt, bool aAuth, + BluetoothSocketResultHandler* aRes); + + void Connect(const nsAString& aBdAddr, + BluetoothSocketType aType, + const uint8_t aUuid[16], + int aChannel, bool aEncrypt, bool aAuth, + BluetoothSocketResultHandler* aRes); + + void Accept(int aFd, BluetoothSocketResultHandler* aRes); + +protected: + BluetoothSocketHALInterface(const btsock_interface_t* aInterface); + ~BluetoothSocketHALInterface(); + +private: + const btsock_interface_t* mInterface; +}; + +END_BLUETOOTH_NAMESPACE + +#endif diff --git a/dom/bluetooth/moz.build b/dom/bluetooth/moz.build index b1942dbad2c4..167c54ce67bc 100644 --- a/dom/bluetooth/moz.build +++ b/dom/bluetooth/moz.build @@ -45,11 +45,16 @@ if CONFIG['MOZ_B2G_BT']: DEFINES['MOZ_B2G_BT_BLUEZ'] = True elif CONFIG['MOZ_B2G_BT_BLUEDROID']: SOURCES += [ + 'bluedroid/BluetoothA2dpHALInterface.cpp', 'bluedroid/BluetoothA2dpManager.cpp', + 'bluedroid/BluetoothAvrcpHALInterface.cpp', + 'bluedroid/BluetoothHALHelpers.cpp', 'bluedroid/BluetoothHALInterface.cpp', + 'bluedroid/BluetoothHandsfreeHALInterface.cpp', 'bluedroid/BluetoothOppManager.cpp', 'bluedroid/BluetoothServiceBluedroid.cpp', 'bluedroid/BluetoothSocket.cpp', + 'bluedroid/BluetoothSocketHALInterface.cpp', 'bluedroid/BluetoothUtils.cpp', ] LOCAL_INCLUDES += [