Bug 1102703 - Porting bluetooth interface of android lollipop (handsfree). r=shawnjohnjr, r=btian, r=tzimmermann
☠☠ backed out by b4926227268f ☠ ☠
authorBruce Sun <brsun@mozilla.com>
Thu, 08 Jan 2015 11:48:21 +0800
changeset 222694 ff47d1b9e86cd3cb2e56c5ab36011161e65de5b3
parent 222693 ece26b235282103462be87d39e3bdbc973c06d32
child 222695 f62155e4fb9c32f91e21395bab8b870b992f0388
push id10716
push userkwierso@gmail.com
push dateFri, 09 Jan 2015 01:17:28 +0000
treeherderfx-team@0f98d51a4a49 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshawnjohnjr, btian, tzimmermann
bugs1102703
milestone37.0a1
Bug 1102703 - 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));
   }
 }