Bug 1102703: (6/10) Porting bluetooth interface of android lollipop (handsfree) r=shawnjohnjr, r=btian, r=tzimmermann
authorBruce Sun <brsun@mozilla.com>
Fri, 09 Jan 2015 13:37:40 +0800
changeset 248816 e8a635821772f9c9e074915b07a1fdc794cd09fb
parent 248815 c2b2ab12dfdd5ba36e401bca83a8e872d4531f76
child 248817 d75205e308d8862995cbfabd31c8ba0e8e5e0cd4
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshawnjohnjr, btian, tzimmermann
bugs1102703
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1102703: (6/10) Porting bluetooth interface of android lollipop (handsfree) r=shawnjohnjr, r=btian, r=tzimmermann
dom/bluetooth/bluedroid/BluetoothHALHelpers.h
dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
--- a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h
+++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h
@@ -778,16 +778,46 @@ Convert(BluetoothTransport aIn, int& aOu
     return NS_ERROR_ILLEGAL_VALUE;
   }
   aOut = sTransport[aIn];
   return NS_OK;
 }
 
 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
  * 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 <typename T>
--- a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
@@ -110,16 +110,22 @@ struct BluetoothHandsfreeHALCallback
   typedef BluetoothNotificationHALRunnable2<
     HandsfreeNotificationHandlerWrapper, void,
     BluetoothHandsfreeNRECState, nsString,
     BluetoothHandsfreeNRECState, const nsAString&>
     NRECNotification;
 
   typedef BluetoothNotificationHALRunnable2<
     HandsfreeNotificationHandlerWrapper, void,
+    BluetoothHandsfreeWbsConfig, nsString,
+    BluetoothHandsfreeWbsConfig, const nsAString&>
+    WbsNotification;
+
+  typedef BluetoothNotificationHALRunnable2<
+    HandsfreeNotificationHandlerWrapper, void,
     BluetoothHandsfreeCallHoldType, nsString,
     BluetoothHandsfreeCallHoldType, const nsAString&>
     CallHoldNotification;
 
   typedef BluetoothNotificationHALRunnable1<
     HandsfreeNotificationHandlerWrapper, void,
     nsString, const nsAString&>
     CnumNotification;
@@ -149,155 +155,316 @@ struct BluetoothHandsfreeHALCallback
     nsString, const nsAString&>
     KeyPressedNotification;
 
   // Bluedroid Handsfree callbacks
 
   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));
     } else if (aState == BTHF_CONNECTION_STATE_DISCONNECTED) {
       memset(&sConnectedDeviceAddress, 0,
              sizeof(sConnectedDeviceAddress));
     }
+#endif
 
     ConnectionStateNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification,
       aState, aBdAddr);
   }
 
   static void
   AudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddr)
   {
     AudioStateNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::AudioStateNotification,
       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)
   {
     VoiceRecognitionNotification::Dispatch(
       &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()
   {
     AnswerCallNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::AnswerCallNotification,
       &sConnectedDeviceAddress);
   }
+#endif
 
+#if ANDROID_VERSION >= 21
+  static void
+  HangupCall(bt_bdaddr_t* aBdAddr)
+  {
+    HangupCallNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::HangupCallNotification,
+      aBdAddr);
+  }
+#else
   static void
   HangupCall()
   {
     HangupCallNotification::Dispatch(
       &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)
   {
     VolumeNotification::Dispatch(
       &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)
   {
     DialCallNotification::Dispatch(
       &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)
   {
     DtmfNotification::Dispatch(
       &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)
   {
     NRECNotification::Dispatch(
       &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)
   {
     CallHoldNotification::Dispatch(
       &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()
   {
     CnumNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::CnumNotification,
       &sConnectedDeviceAddress);
   }
+#endif
 
+#if ANDROID_VERSION >= 21
+  static void
+  Cind(bt_bdaddr_t* aBdAddr)
+  {
+    CindNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::CindNotification,
+      aBdAddr);
+  }
+#else
   static void
   Cind()
   {
     CindNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::CindNotification,
       &sConnectedDeviceAddress);
   }
+#endif
 
+#if ANDROID_VERSION >= 21
+  static void
+  Cops(bt_bdaddr_t* aBdAddr)
+  {
+    CopsNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::CopsNotification,
+      aBdAddr);
+  }
+#else
   static void
   Cops()
   {
     CopsNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::CopsNotification,
       &sConnectedDeviceAddress);
   }
+#endif
 
+#if ANDROID_VERSION >= 21
+  static void
+  Clcc(bt_bdaddr_t* aBdAddr)
+  {
+    ClccNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::ClccNotification,
+      aBdAddr);
+  }
+#else
   static void
   Clcc()
   {
     ClccNotification::Dispatch(
       &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)
   {
     UnknownAtNotification::Dispatch(
       &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()
   {
     KeyPressedNotification::Dispatch(
       &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
 //
 
 BluetoothHandsfreeHALInterface::BluetoothHandsfreeHALInterface(
   const bthf_interface_t* aInterface)
 : mInterface(aInterface)
 {
@@ -318,28 +485,35 @@ BluetoothHandsfreeHALInterface::Init(
     BluetoothHandsfreeHALCallback::AudioState,
     BluetoothHandsfreeHALCallback::VoiceRecognition,
     BluetoothHandsfreeHALCallback::AnswerCall,
     BluetoothHandsfreeHALCallback::HangupCall,
     BluetoothHandsfreeHALCallback::Volume,
     BluetoothHandsfreeHALCallback::DialCall,
     BluetoothHandsfreeHALCallback::Dtmf,
     BluetoothHandsfreeHALCallback::NoiseReductionEchoCancellation,
+#if ANDROID_VERSION >= 21
+    BluetoothHandsfreeHALCallback::WideBandSpeech,
+#endif
     BluetoothHandsfreeHALCallback::CallHold,
     BluetoothHandsfreeHALCallback::Cnum,
     BluetoothHandsfreeHALCallback::Cind,
     BluetoothHandsfreeHALCallback::Cops,
     BluetoothHandsfreeHALCallback::Clcc,
     BluetoothHandsfreeHALCallback::UnknownAt,
     BluetoothHandsfreeHALCallback::KeyPressed
   };
 
   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(
       aRes, &BluetoothHandsfreeResultHandler::Init,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
@@ -439,31 +613,55 @@ BluetoothHandsfreeHALInterface::Disconne
 
 /* Voice Recognition */
 
 void
 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(
       aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 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(
       aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
@@ -472,18 +670,26 @@ BluetoothHandsfreeHALInterface::StopVoic
 void
 BluetoothHandsfreeHALInterface::VolumeControl(
   BluetoothHandsfreeVolumeType aType, int aVolume, const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   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;
   }
 
   if (aRes) {
     DispatchBluetoothHandsfreeHALResult(
       aRes, &BluetoothHandsfreeResultHandler::VolumeControl,
       ConvertDefault(status, STATUS_FAIL));
@@ -519,17 +725,29 @@ BluetoothHandsfreeHALInterface::DeviceSt
 
 /* Responses */
 
 void
 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(
       aRes, &BluetoothHandsfreeResultHandler::CopsResponse,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
@@ -539,37 +757,59 @@ BluetoothHandsfreeHALInterface::CindResp
   BluetoothHandsfreeCallState aCallSetupState,
   int aSignal, int aRoam, int aBattChg,
   const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   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;
   }
 
   if (aRes) {
     DispatchBluetoothHandsfreeHALResult(
       aRes, &BluetoothHandsfreeResultHandler::CindResponse,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 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(
       aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
@@ -577,18 +817,26 @@ void
 BluetoothHandsfreeHALInterface::AtResponse(
   BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
   const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   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;
   }
 
   if (aRes) {
     DispatchBluetoothHandsfreeHALResult(
       aRes, &BluetoothHandsfreeResultHandler::AtResponse,
       ConvertDefault(status, STATUS_FAIL));
@@ -609,24 +857,38 @@ BluetoothHandsfreeHALInterface::ClccResp
 {
   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 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)) &&
       NS_SUCCEEDED(Convert(aMpty, mpty)) &&
       NS_SUCCEEDED(Convert(aType, type))) {
     status = mInterface->clcc_response(aIndex, dir, state, mode, mpty,
                                        NS_ConvertUTF16toUTF8(aNumber).get(),
                                        type);
+#endif
   } else {
     status = BT_STATUS_PARM_INVALID;
   }
 
   if (aRes) {
     DispatchBluetoothHandsfreeHALResult(
       aRes, &BluetoothHandsfreeResultHandler::ClccResponse,
       ConvertDefault(status, STATUS_FAIL));
@@ -664,19 +926,31 @@ BluetoothHandsfreeHALInterface::PhoneSta
 /* Wide Band Speech */
 
 void
 BluetoothHandsfreeHALInterface::ConfigureWbs(
   const nsAString& aBdAddr,
   BluetoothHandsfreeWbsConfig aConfig,
   BluetoothHandsfreeResultHandler* aRes)
 {
-  // TODO: to be implemented
+  bt_status_t status;
+
+#if ANDROID_VERSION >= 21
+  bt_bdaddr_t bdAddr;
+  bthf_wbs_config_t wbsConfig;
 
-  bt_status_t status = BT_STATUS_UNSUPPORTED;
+  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(
       aRes, &BluetoothHandsfreeResultHandler::ConfigureWbs,
       ConvertDefault(status, STATUS_FAIL));
   }
 }