From ee6dcf6c1d4a74fd414d6357b872e70ac9f47e1b Mon Sep 17 00:00:00 2001 From: Bruce Sun Date: Thu, 8 Jan 2015 11:48:21 +0800 Subject: [PATCH] Bug 1102703 - Porting bluetooth interface of android lollipop (handsfree). r=shawnjohnjr, r=btian, r=tzimmermann --- dom/bluetooth/bluedroid/BluetoothHALHelpers.h | 30 ++ .../BluetoothHandsfreeHALInterface.cpp | 286 +++++++++++++++++- 2 files changed, 310 insertions(+), 6 deletions(-) diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h index ad6565075787..4827f7f3c735 100644 --- a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h +++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h @@ -783,6 +783,36 @@ Convert(BluetoothTransport aIn, int& aOut) nsresult Convert(const bt_activity_energy_info& aIn, BluetoothActivityEnergyInfo& aOut); + +inline nsresult +Convert(bthf_wbs_config_t aIn, BluetoothHandsfreeWbsConfig& aOut) +{ + static const BluetoothHandsfreeWbsConfig sWbsConfig[] = { + CONVERT(BTHF_WBS_NONE, HFP_WBS_NONE), + CONVERT(BTHF_WBS_NO, HFP_WBS_NO), + CONVERT(BTHF_WBS_YES, HFP_WBS_YES) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sWbsConfig))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sWbsConfig[aIn]; + return NS_OK; +} + +inline nsresult +Convert(BluetoothHandsfreeWbsConfig aIn, bthf_wbs_config_t& aOut) +{ + static const bthf_wbs_config_t sWbsConfig[] = { + CONVERT(HFP_WBS_NONE, BTHF_WBS_NONE), + CONVERT(HFP_WBS_NO, BTHF_WBS_NO), + CONVERT(HFP_WBS_YES, BTHF_WBS_YES) + }; + if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sWbsConfig))) { + return NS_ERROR_ILLEGAL_VALUE; + } + aOut = sWbsConfig[aIn]; + return NS_OK; +} #endif // ANDROID_VERSION >= 21 /* |ConvertArray| is a helper for converting arrays. Pass an diff --git a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp index 9c6f62cbf5bf..373a887d1c20 100644 --- a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp +++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp @@ -113,6 +113,12 @@ struct BluetoothHandsfreeHALCallback BluetoothHandsfreeNRECState, const nsAString&> NRECNotification; + typedef BluetoothNotificationHALRunnable2< + HandsfreeNotificationHandlerWrapper, void, + BluetoothHandsfreeWbsConfig, nsString, + BluetoothHandsfreeWbsConfig, const nsAString&> + WbsNotification; + typedef BluetoothNotificationHALRunnable2< HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeCallHoldType, nsString, @@ -154,6 +160,7 @@ struct BluetoothHandsfreeHALCallback static void ConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddr) { +#if ANDROID_VERSION < 21 if (aState == BTHF_CONNECTION_STATE_CONNECTED && aBdAddr) { memcpy(&sConnectedDeviceAddress, aBdAddr, sizeof(sConnectedDeviceAddress)); @@ -161,6 +168,7 @@ struct BluetoothHandsfreeHALCallback memset(&sConnectedDeviceAddress, 0, sizeof(sConnectedDeviceAddress)); } +#endif ConnectionStateNotification::Dispatch( &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification, @@ -175,6 +183,15 @@ struct BluetoothHandsfreeHALCallback aState, aBdAddr); } +#if ANDROID_VERSION >= 21 + static void + VoiceRecognition(bthf_vr_state_t aState, bt_bdaddr_t* aBdAddr) + { + VoiceRecognitionNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification, + aState, aBdAddr); + } +#else static void VoiceRecognition(bthf_vr_state_t aState) { @@ -182,7 +199,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification, aState, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + AnswerCall(bt_bdaddr_t* aBdAddr) + { + AnswerCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::AnswerCallNotification, + aBdAddr); + } +#else static void AnswerCall() { @@ -190,7 +217,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::AnswerCallNotification, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + HangupCall(bt_bdaddr_t* aBdAddr) + { + HangupCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::HangupCallNotification, + aBdAddr); + } +#else static void HangupCall() { @@ -198,7 +235,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::HangupCallNotification, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + Volume(bthf_volume_type_t aType, int aVolume, bt_bdaddr_t* aBdAddr) + { + VolumeNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::VolumeNotification, + aType, aVolume, aBdAddr); + } +#else static void Volume(bthf_volume_type_t aType, int aVolume) { @@ -206,7 +253,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::VolumeNotification, aType, aVolume, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + DialCall(char* aNumber, bt_bdaddr_t* aBdAddr) + { + DialCallNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DialCallNotification, + aNumber, aBdAddr); + } +#else static void DialCall(char* aNumber) { @@ -214,7 +271,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::DialCallNotification, aNumber, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + Dtmf(char aDtmf, bt_bdaddr_t* aBdAddr) + { + DtmfNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::DtmfNotification, + aDtmf, aBdAddr); + } +#else static void Dtmf(char aDtmf) { @@ -222,7 +289,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::DtmfNotification, aDtmf, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + NoiseReductionEchoCancellation(bthf_nrec_t aNrec, bt_bdaddr_t* aBdAddr) + { + NRECNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::NRECNotification, + aNrec, aBdAddr); + } +#else static void NoiseReductionEchoCancellation(bthf_nrec_t aNrec) { @@ -230,7 +307,27 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::NRECNotification, aNrec, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + WideBandSpeech(bthf_wbs_config_t aWbs, bt_bdaddr_t* aBdAddr) + { + WbsNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::WbsNotification, + aWbs, aBdAddr); + } +#endif + +#if ANDROID_VERSION >= 21 + static void + CallHold(bthf_chld_type_t aChld, bt_bdaddr_t* aBdAddr) + { + CallHoldNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CallHoldNotification, + aChld, aBdAddr); + } +#else static void CallHold(bthf_chld_type_t aChld) { @@ -238,7 +335,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::CallHoldNotification, aChld, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + Cnum(bt_bdaddr_t* aBdAddr) + { + CnumNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CnumNotification, + aBdAddr); + } +#else static void Cnum() { @@ -246,7 +353,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::CnumNotification, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + Cind(bt_bdaddr_t* aBdAddr) + { + CindNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CindNotification, + aBdAddr); + } +#else static void Cind() { @@ -254,7 +371,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::CindNotification, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + Cops(bt_bdaddr_t* aBdAddr) + { + CopsNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::CopsNotification, + aBdAddr); + } +#else static void Cops() { @@ -262,7 +389,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::CopsNotification, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + Clcc(bt_bdaddr_t* aBdAddr) + { + ClccNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::ClccNotification, + aBdAddr); + } +#else static void Clcc() { @@ -270,7 +407,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::ClccNotification, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + UnknownAt(char* aAtString, bt_bdaddr_t* aBdAddr) + { + UnknownAtNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::UnknownAtNotification, + aAtString, aBdAddr); + } +#else static void UnknownAt(char* aAtString) { @@ -278,7 +425,17 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::UnknownAtNotification, aAtString, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION >= 21 + static void + KeyPressed(bt_bdaddr_t* aBdAddr) + { + KeyPressedNotification::Dispatch( + &BluetoothHandsfreeNotificationHandler::KeyPressedNotification, + aBdAddr); + } +#else static void KeyPressed() { @@ -286,13 +443,23 @@ struct BluetoothHandsfreeHALCallback &BluetoothHandsfreeNotificationHandler::KeyPressedNotification, &sConnectedDeviceAddress); } +#endif +#if ANDROID_VERSION < 21 + /* |sConnectedDeviceAddress| stores Bluetooth device address of the + * connected device. Before Android Lollipop, we maintain this address by + * ourselves through ConnectionState(); after Android Lollipop, every callback + * carries this address directly so we don't have to keep it. + */ static bt_bdaddr_t sConnectedDeviceAddress; +#endif }; +#if ANDROID_VERSION < 21 bt_bdaddr_t BluetoothHandsfreeHALCallback::sConnectedDeviceAddress = { {0, 0, 0, 0, 0, 0} }; +#endif // Interface // @@ -323,6 +490,9 @@ BluetoothHandsfreeHALInterface::Init( BluetoothHandsfreeHALCallback::DialCall, BluetoothHandsfreeHALCallback::Dtmf, BluetoothHandsfreeHALCallback::NoiseReductionEchoCancellation, +#if ANDROID_VERSION >= 21 + BluetoothHandsfreeHALCallback::WideBandSpeech, +#endif BluetoothHandsfreeHALCallback::CallHold, BluetoothHandsfreeHALCallback::Cnum, BluetoothHandsfreeHALCallback::Cind, @@ -334,7 +504,11 @@ BluetoothHandsfreeHALInterface::Init( sHandsfreeNotificationHandler = aNotificationHandler; +#if ANDROID_VERSION >= 21 + bt_status_t status = mInterface->init(&sCallbacks, aMaxNumClients); +#else bt_status_t status = mInterface->init(&sCallbacks); +#endif if (aRes) { DispatchBluetoothHandsfreeHALResult( @@ -444,7 +618,19 @@ BluetoothHandsfreeHALInterface::StartVoiceRecognition( const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) { - bt_status_t status = mInterface->start_voice_recognition(); + bt_status_t status; + +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->start_voice_recognition(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = mInterface->start_voice_recognition(); +#endif if (aRes) { DispatchBluetoothHandsfreeHALResult( @@ -458,7 +644,19 @@ BluetoothHandsfreeHALInterface::StopVoiceRecognition( const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) { - bt_status_t status = mInterface->stop_voice_recognition(); + bt_status_t status; + +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->stop_voice_recognition(&bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = mInterface->stop_voice_recognition(); +#endif if (aRes) { DispatchBluetoothHandsfreeHALResult( @@ -477,8 +675,16 @@ BluetoothHandsfreeHALInterface::VolumeControl( bt_status_t status; bthf_volume_type_t type = BTHF_VOLUME_TYPE_SPK; +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aType, type)) && + NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->volume_control(type, aVolume, &bdAddr); +#else if (NS_SUCCEEDED(Convert(aType, type))) { status = mInterface->volume_control(type, aVolume); +#endif } else { status = BT_STATUS_PARM_INVALID; } @@ -524,7 +730,19 @@ BluetoothHandsfreeHALInterface::CopsResponse( const char* aCops, const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) { - bt_status_t status = mInterface->cops_response(aCops); + bt_status_t status; + +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->cops_response(aCops, &bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = mInterface->cops_response(aCops); +#endif if (aRes) { DispatchBluetoothHandsfreeHALResult( @@ -544,10 +762,20 @@ BluetoothHandsfreeHALInterface::CindResponse( bt_status_t status; bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE; +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState)) && + NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->cind_response(aSvc, aNumActive, aNumHeld, + callSetupState, aSignal, + aRoam, aBattChg, &bdAddr); +#else if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState))) { status = mInterface->cind_response(aSvc, aNumActive, aNumHeld, callSetupState, aSignal, aRoam, aBattChg); +#endif } else { status = BT_STATUS_PARM_INVALID; } @@ -564,7 +792,19 @@ BluetoothHandsfreeHALInterface::FormattedAtResponse( const char* aRsp, const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes) { - bt_status_t status = mInterface->formatted_at_response(aRsp); + bt_status_t status; + +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->formatted_at_response(aRsp, &bdAddr); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = mInterface->formatted_at_response(aRsp); +#endif if (aRes) { DispatchBluetoothHandsfreeHALResult( @@ -582,8 +822,16 @@ BluetoothHandsfreeHALInterface::AtResponse( bt_status_t status; bthf_at_response_t responseCode = BTHF_AT_RESPONSE_ERROR; +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + if (NS_SUCCEEDED(Convert(aResponseCode, responseCode)) && + NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->at_response(responseCode, aErrorCode, &bdAddr); +#else if (NS_SUCCEEDED(Convert(aResponseCode, responseCode))) { status = mInterface->at_response(responseCode, aErrorCode); +#endif } else { status = BT_STATUS_PARM_INVALID; } @@ -614,6 +862,19 @@ BluetoothHandsfreeHALInterface::ClccResponse( bthf_call_mpty_type_t mpty = BTHF_CALL_MPTY_TYPE_SINGLE; bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN; +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + + 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)) && + NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) { + status = mInterface->clcc_response(aIndex, dir, state, mode, mpty, + NS_ConvertUTF16toUTF8(aNumber).get(), + type, &bdAddr); +#else if (NS_SUCCEEDED(Convert(aDir, dir)) && NS_SUCCEEDED(Convert(aState, state)) && NS_SUCCEEDED(Convert(aMode, mode)) && @@ -622,6 +883,7 @@ BluetoothHandsfreeHALInterface::ClccResponse( status = mInterface->clcc_response(aIndex, dir, state, mode, mpty, NS_ConvertUTF16toUTF8(aNumber).get(), type); +#endif } else { status = BT_STATUS_PARM_INVALID; } @@ -669,9 +931,21 @@ BluetoothHandsfreeHALInterface::ConfigureWbs( BluetoothHandsfreeWbsConfig aConfig, BluetoothHandsfreeResultHandler* aRes) { - // TODO: to be implemented + bt_status_t status; - bt_status_t status = BT_STATUS_UNSUPPORTED; +#if ANDROID_VERSION >= 21 + bt_bdaddr_t bdAddr; + bthf_wbs_config_t wbsConfig; + + if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) && + NS_SUCCEEDED(Convert(aConfig, wbsConfig))) { + status = mInterface->configure_wbs(&bdAddr, wbsConfig); + } else { + status = BT_STATUS_PARM_INVALID; + } +#else + status = BT_STATUS_UNSUPPORTED; +#endif if (aRes) { DispatchBluetoothHandsfreeHALResult(