Bug 1102703: (3/10) Extend internal interfaces to sync with android lollipop and bluez 5.26 (handsfree) r=btian, r=tzimmermann
authorBruce Sun <brsun@mozilla.com>
Fri, 09 Jan 2015 13:35:01 +0800
changeset 236002 b852f5939562a6498a82631584ab4f7621164ad5
parent 236001 966899f3040027eee652d1aa43d2822a30d4d4dd
child 236003 4ab94ffcee0c68f672b62ab0513eff7d45e6a07b
push id384
push usermartin.thomson@gmail.com
push dateFri, 09 Jan 2015 21:26:39 +0000
reviewersbtian, tzimmermann
bugs1102703
milestone37.0a1
Bug 1102703: (3/10) Extend internal interfaces to sync with android lollipop and bluez 5.26 (handsfree) r=btian, r=tzimmermann
dom/bluetooth/BluetoothCommon.h
dom/bluetooth/BluetoothInterface.h
dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h
dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h
dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
--- a/dom/bluetooth/BluetoothCommon.h
+++ b/dom/bluetooth/BluetoothCommon.h
@@ -317,16 +317,22 @@ enum BluetoothHandsfreeConnectionState
   HFP_CONNECTION_STATE_DISCONNECTING
 };
 
 enum BluetoothHandsfreeNetworkState {
   HFP_NETWORK_STATE_NOT_AVAILABLE,
   HFP_NETWORK_STATE_AVAILABLE
 };
 
+enum BluetoothHandsfreeWbsConfig {
+  HFP_WBS_NONE, /* Neither CVSD nor mSBC codec, but other optional codec.*/
+  HFP_WBS_NO,   /* CVSD */
+  HFP_WBS_YES   /* mSBC */
+};
+
 enum BluetoothHandsfreeNRECState {
   HFP_NREC_STOPPED,
   HFP_NREC_STARTED
 };
 
 enum BluetoothHandsfreeServiceType {
   HFP_SERVICE_TYPE_HOME,
   HFP_SERVICE_TYPE_ROAMING
--- a/dom/bluetooth/BluetoothInterface.h
+++ b/dom/bluetooth/BluetoothInterface.h
@@ -75,69 +75,82 @@ public:
   { }
 
   virtual void
   AudioStateNotification(BluetoothHandsfreeAudioState aState,
                          const nsAString& aBdAddr)
   { }
 
   virtual void
-  VoiceRecognitionNotification(BluetoothHandsfreeVoiceRecognitionState aState)
+  VoiceRecognitionNotification(BluetoothHandsfreeVoiceRecognitionState aState,
+                               const nsAString& aBdAddr)
   { }
 
   virtual void
-  AnswerCallNotification()
+  AnswerCallNotification(const nsAString& aBdAddr)
+  { }
+
+  virtual void
+  HangupCallNotification(const nsAString& aBdAddr)
   { }
 
   virtual void
-  HangupCallNotification()
+  VolumeNotification(BluetoothHandsfreeVolumeType aType,
+                     int aVolume,
+                     const nsAString& aBdAddr)
   { }
 
   virtual void
-  VolumeNotification(BluetoothHandsfreeVolumeType aType, int aVolume)
+  DialCallNotification(const nsAString& aNumber,
+                       const nsAString& aBdAddr)
   { }
 
   virtual void
-  DialCallNotification(const nsAString& aNumber)
-  { }
-
-  virtual void
-  DtmfNotification(char aDtmf)
+  DtmfNotification(char aDtmf,
+                   const nsAString& aBdAddr)
   { }
 
   virtual void
-  NRECNotification(BluetoothHandsfreeNRECState aNrec)
+  NRECNotification(BluetoothHandsfreeNRECState aNrec,
+                   const nsAString& aBdAddr)
   { }
 
   virtual void
-  CallHoldNotification(BluetoothHandsfreeCallHoldType aChld)
+  WbsNotification(BluetoothHandsfreeWbsConfig aWbs,
+                  const nsAString& aBdAddr)
   { }
 
   virtual void
-  CnumNotification()
+  CallHoldNotification(BluetoothHandsfreeCallHoldType aChld,
+                       const nsAString& aBdAddr)
+  { }
+
+  virtual void
+  CnumNotification(const nsAString& aBdAddr)
   { }
 
   virtual void
-  CindNotification()
+  CindNotification(const nsAString& aBdAddr)
   { }
 
   virtual void
-  CopsNotification()
+  CopsNotification(const nsAString& aBdAddr)
   { }
 
   virtual void
-  ClccNotification()
+  ClccNotification(const nsAString& aBdAddr)
   { }
 
   virtual void
-  UnknownAtNotification(const nsACString& aAtString)
+  UnknownAtNotification(const nsACString& aAtString,
+                        const nsAString& aBdAddr)
   { }
 
   virtual void
-  KeyPressedNotification()
+  KeyPressedNotification(const nsAString& aBdAddr)
   { }
 
 protected:
   BluetoothHandsfreeNotificationHandler()
   { }
 };
 
 class BluetoothHandsfreeResultHandler
@@ -168,82 +181,95 @@ public:
   virtual void DeviceStatusNotification() { }
 
   virtual void CopsResponse() { }
   virtual void CindResponse() { }
   virtual void FormattedAtResponse() { }
   virtual void AtResponse() { }
   virtual void ClccResponse() { }
   virtual void PhoneStateChange() { }
+
+  virtual void ConfigureWbs() { }
 };
 
 class BluetoothHandsfreeInterface
 {
 public:
   virtual void Init(
     BluetoothHandsfreeNotificationHandler* aNotificationHandler,
-    BluetoothHandsfreeResultHandler* aRes) = 0;
+    int aMaxNumClients, BluetoothHandsfreeResultHandler* aRes) = 0;
   virtual void Cleanup(BluetoothHandsfreeResultHandler* aRes) = 0;
 
   /* Connect / Disconnect */
 
   virtual void Connect(const nsAString& aBdAddr,
                        BluetoothHandsfreeResultHandler* aRes) = 0;
   virtual void Disconnect(const nsAString& aBdAddr,
                           BluetoothHandsfreeResultHandler* aRes) = 0;
   virtual void ConnectAudio(const nsAString& aBdAddr,
                             BluetoothHandsfreeResultHandler* aRes) = 0;
   virtual void DisconnectAudio(const nsAString& aBdAddr,
                                BluetoothHandsfreeResultHandler* aRes) = 0;
 
   /* Voice Recognition */
 
-  virtual void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes) = 0;
-  virtual void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes) = 0;
+  virtual void StartVoiceRecognition(const nsAString& aBdAddr,
+                                     BluetoothHandsfreeResultHandler* aRes) = 0;
+  virtual void StopVoiceRecognition(const nsAString& aBdAddr,
+                                    BluetoothHandsfreeResultHandler* aRes) = 0;
 
   /* Volume */
 
   virtual void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
+                             const nsAString& aBdAddr,
                              BluetoothHandsfreeResultHandler* aRes) = 0;
 
   /* Device status */
 
   virtual void DeviceStatusNotification(
     BluetoothHandsfreeNetworkState aNtkState,
     BluetoothHandsfreeServiceType aSvcType,
     int aSignal, int aBattChg, BluetoothHandsfreeResultHandler* aRes) = 0;
 
   /* Responses */
 
-  virtual void CopsResponse(const char* aCops,
+  virtual void CopsResponse(const char* aCops, const nsAString& aBdAddr,
                             BluetoothHandsfreeResultHandler* aRes) = 0;
   virtual void CindResponse(int aSvc, int aNumActive, int aNumHeld,
                             BluetoothHandsfreeCallState aCallSetupState,
                             int aSignal, int aRoam, int aBattChg,
+                            const nsAString& aBdAddr,
                             BluetoothHandsfreeResultHandler* aRes) = 0;
-  virtual void FormattedAtResponse(const char* aRsp,
+  virtual void FormattedAtResponse(const char* aRsp, const nsAString& aBdAddr,
                                    BluetoothHandsfreeResultHandler* aRes) = 0;
-  virtual void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+  virtual void AtResponse(BluetoothHandsfreeAtResponse aResponseCode,
+                          int aErrorCode, const nsAString& aBdAddr,
                           BluetoothHandsfreeResultHandler* aRes) = 0;
   virtual void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
                             BluetoothHandsfreeCallState aState,
                             BluetoothHandsfreeCallMode aMode,
                             BluetoothHandsfreeCallMptyType aMpty,
                             const nsAString& aNumber,
                             BluetoothHandsfreeCallAddressType aType,
+                            const nsAString& aBdAddr,
                             BluetoothHandsfreeResultHandler* aRes) = 0;
 
   /* Phone State */
 
   virtual void PhoneStateChange(int aNumActive, int aNumHeld,
                                 BluetoothHandsfreeCallState aCallSetupState,
                                 const nsAString& aNumber,
                                 BluetoothHandsfreeCallAddressType aType,
                                 BluetoothHandsfreeResultHandler* aRes) = 0;
 
+  /* Wide Band Speech */
+  virtual void ConfigureWbs(const nsAString& aBdAddr,
+                            BluetoothHandsfreeWbsConfig aConfig,
+                            BluetoothHandsfreeResultHandler* aRes) = 0;
+
 protected:
   BluetoothHandsfreeInterface();
   virtual ~BluetoothHandsfreeInterface();
 };
 
 //
 // Bluetooth Advanced Audio Interface
 //
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
@@ -12,16 +12,19 @@ BEGIN_BLUETOOTH_NAMESPACE
 
 //
 // Handsfree module
 //
 
 BluetoothHandsfreeNotificationHandler*
   BluetoothDaemonHandsfreeModule::sNotificationHandler;
 
+nsString BluetoothDaemonHandsfreeModule::sConnectedDeviceAddress(
+  NS_ConvertUTF8toUTF16(BLUETOOTH_ADDRESS_NONE));
+
 void
 BluetoothDaemonHandsfreeModule::SetNotificationHandler(
   BluetoothHandsfreeNotificationHandler* aNotificationHandler)
 {
   sNotificationHandler = aNotificationHandler;
 }
 
 nsresult
@@ -404,16 +407,29 @@ BluetoothDaemonHandsfreeModule::PhoneSta
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
+nsresult
+BluetoothDaemonHandsfreeModule::ConfigureWbsCmd(
+  const nsAString& aBdAddr,
+  BluetoothHandsfreeWbsConfig aConfig,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // TODO: to be implemented
+
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
 // Responses
 //
 
 void
 BluetoothDaemonHandsfreeModule::ErrorRsp(
   const BluetoothDaemonPDUHeader& aHeader,
   BluetoothDaemonPDU& aPDU, BluetoothHandsfreeResultHandler* aRes)
 {
@@ -657,16 +673,22 @@ public:
     }
 
     /* Read address */
     rv = UnpackPDU(
       pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
     if (NS_FAILED(rv)) {
       return rv;
     }
+
+    if (aArg1 == HFP_CONNECTION_STATE_CONNECTED) {
+      sConnectedDeviceAddress = aArg2;
+    } else if (aArg1 == HFP_CONNECTION_STATE_DISCONNECTED) {
+      sConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
+    }
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::ConnectionStateNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -681,18 +703,17 @@ class BluetoothDaemonHandsfreeModule::Au
   : private PDUInitOp
 {
 public:
   AudioStateInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
-  operator () (BluetoothHandsfreeAudioState& aArg1,
-               nsString& aArg2) const
+  operator () (BluetoothHandsfreeAudioState& aArg1, nsString& aArg2) const
   {
     BluetoothDaemonPDU& pdu = GetPDU();
 
     /* Read state */
     nsresult rv = UnpackPDU(pdu, aArg1);
     if (NS_FAILED(rv)) {
       return rv;
     }
@@ -712,68 +733,142 @@ void
 BluetoothDaemonHandsfreeModule::AudioStateNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   AudioStateNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::AudioStateNotification,
     AudioStateInitOp(aPDU));
 }
 
+// Init operator class for VoiceRecognitionNotification
+class BluetoothDaemonHandsfreeModule::VoiceRecognitionInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  VoiceRecognitionInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (BluetoothHandsfreeVoiceRecognitionState& aArg1,
+               nsString& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read state */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read address */
+    // TODO
+    aArg2 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   VoiceRecognitionNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification,
-    UnpackPDUInitOp(aPDU));
+    VoiceRecognitionInitOp(aPDU));
 }
 
+// Init operator class for AnswerCallNotification
+class BluetoothDaemonHandsfreeModule::AnswerCallInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  AnswerCallInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1) const
+  {
+    /* Read address */
+    // TODO
+    aArg1 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::AnswerCallNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   AnswerCallNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::AnswerCallNotification,
-    UnpackPDUInitOp(aPDU));
+    AnswerCallInitOp(aPDU));
 }
 
+// Init operator class for HangupCallNotification
+class BluetoothDaemonHandsfreeModule::HangupCallInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  HangupCallInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1) const
+  {
+    /* Read address */
+    // TODO
+    aArg1 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::HangupCallNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   HangupCallNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::HangupCallNotification,
-    UnpackPDUInitOp(aPDU));
+    HangupCallInitOp(aPDU));
 }
 
 // Init operator class for VolumeNotification
 class BluetoothDaemonHandsfreeModule::VolumeInitOp MOZ_FINAL
   : private PDUInitOp
 {
 public:
   VolumeInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
-  operator () (BluetoothHandsfreeVolumeType& aArg1, int& aArg2) const
+  operator () (BluetoothHandsfreeVolumeType& aArg1, int& aArg2,
+               nsString& aArg3) const
   {
     BluetoothDaemonPDU& pdu = GetPDU();
 
     /* Read volume type */
     nsresult rv = UnpackPDU(pdu, aArg1);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     /* Read volume */
     rv = UnpackPDU(pdu, UnpackConversion<uint8_t, int>(aArg2));
     if (NS_FAILED(rv)) {
       return rv;
     }
+
+    /* Read address */
+    // TODO
+    aArg3 = sConnectedDeviceAddress;
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::VolumeNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -788,138 +883,334 @@ class BluetoothDaemonHandsfreeModule::Di
   : private PDUInitOp
 {
 public:
   DialCallInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
-  operator () (nsString& aArg1) const
+  operator () (nsString& aArg1, nsString& aArg2) const
   {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
     /* Read number */
-    nsresult rv = UnpackPDU(GetPDU(), UnpackString0(aArg1));
+    nsresult rv = UnpackPDU(pdu, UnpackString0(aArg1));
     if (NS_FAILED(rv)) {
       return rv;
     }
+
+    /* Read address */
+    // TODO
+    aArg2 = sConnectedDeviceAddress;
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::DialCallNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   DialCallNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::DialCallNotification,
     DialCallInitOp(aPDU));
 }
 
+// Init operator class for DtmfNotification
+class BluetoothDaemonHandsfreeModule::DtmfInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  DtmfInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (char& aArg1, nsString& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read tone */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read address */
+    // TODO
+    aArg2 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::DtmfNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   DtmfNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::DtmfNotification,
-    UnpackPDUInitOp(aPDU));
+    DtmfInitOp(aPDU));
 }
 
+// Init operator class for NRECNotification
+class BluetoothDaemonHandsfreeModule::NRECInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  NRECInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (BluetoothHandsfreeNRECState& aArg1, nsString& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read state */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read address */
+    // TODO
+    aArg2 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::NRECNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   NRECNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::NRECNotification,
-    UnpackPDUInitOp(aPDU));
+    NRECInitOp(aPDU));
 }
 
+// Init operator class for CallHoldNotification
+class BluetoothDaemonHandsfreeModule::CallHoldInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  CallHoldInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (BluetoothHandsfreeCallHoldType& aArg1, nsString& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read type */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read address */
+    // TODO
+    aArg2 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::CallHoldNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   CallHoldNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::CallHoldNotification,
-    UnpackPDUInitOp(aPDU));
+    CallHoldInitOp(aPDU));
 }
 
+// Init operator class for CnumNotification
+class BluetoothDaemonHandsfreeModule::CnumInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  CnumInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1) const
+  {
+    /* Read address */
+    // TODO
+    aArg1 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::CnumNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   CnumNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::CnumNotification,
-    UnpackPDUInitOp(aPDU));
+    CnumInitOp(aPDU));
 }
 
+// Init operator class for CindNotification
+class BluetoothDaemonHandsfreeModule::CindInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  CindInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1) const
+  {
+    /* Read address */
+    // TODO
+    aArg1 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::CindNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   CindNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::CindNotification,
-    UnpackPDUInitOp(aPDU));
+    CindInitOp(aPDU));
 }
 
+// Init operator class for CopsNotification
+class BluetoothDaemonHandsfreeModule::CopsInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  CopsInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1) const
+  {
+    /* Read address */
+    // TODO
+    aArg1 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::CopsNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   CopsNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::CopsNotification,
-    UnpackPDUInitOp(aPDU));
+    CopsInitOp(aPDU));
 }
 
+// Init operator class for ClccNotification
+class BluetoothDaemonHandsfreeModule::ClccInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  ClccInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1) const
+  {
+    /* Read address */
+    // TODO
+    aArg1 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::ClccNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   ClccNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::ClccNotification,
-    UnpackPDUInitOp(aPDU));
+    ClccInitOp(aPDU));
 }
 
 // Init operator class for UnknownAtNotification
 class BluetoothDaemonHandsfreeModule::UnknownAtInitOp MOZ_FINAL
   : private PDUInitOp
 {
 public:
   UnknownAtInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
-  operator () (nsCString& aArg1) const
+  operator () (nsCString& aArg1, nsString& aArg2) const
   {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
     /* Read string */
-    nsresult rv = UnpackPDU(GetPDU(), UnpackCString0(aArg1));
+    nsresult rv = UnpackPDU(pdu, UnpackCString0(aArg1));
     if (NS_FAILED(rv)) {
       return rv;
     }
+
+    /* Read address */
+    // TODO
+    aArg2 = sConnectedDeviceAddress;
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::UnknownAtNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   UnknownAtNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::UnknownAtNotification,
     UnknownAtInitOp(aPDU));
 }
 
+// Init operator class for KeyPressedNotification
+class BluetoothDaemonHandsfreeModule::KeyPressedInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  KeyPressedInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1) const
+  {
+    /* Read address */
+    // TODO
+    aArg1 = sConnectedDeviceAddress;
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
 void
 BluetoothDaemonHandsfreeModule::KeyPressedNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
 {
   KeyPressedNotification::Dispatch(
     &BluetoothHandsfreeNotificationHandler::KeyPressedNotification,
-    UnpackPDUInitOp(aPDU));
+    KeyPressedInitOp(aPDU));
 }
 
 void
 BluetoothDaemonHandsfreeModule::HandleNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
   void* aUserData)
 {
   static void (BluetoothDaemonHandsfreeModule::* const HandleNtf[])(
@@ -992,17 +1283,17 @@ public:
 
 private:
   nsRefPtr<BluetoothHandsfreeResultHandler> mRes;
 };
 
 void
 BluetoothDaemonHandsfreeInterface::Init(
   BluetoothHandsfreeNotificationHandler* aNotificationHandler,
-  BluetoothHandsfreeResultHandler* aRes)
+  int aMaxNumClients, BluetoothHandsfreeResultHandler* aRes)
 {
   // Set notification handler _before_ registering the module. It could
   // happen that we receive notifications, before the result handler runs.
   mModule->SetNotificationHandler(aNotificationHandler);
 
   InitResultHandler* res;
 
   if (aRes) {
@@ -1105,37 +1396,37 @@ BluetoothDaemonHandsfreeInterface::Disco
 
   mModule->DisconnectAudioCmd(aBdAddr, aRes);
 }
 
 /* Voice Recognition */
 
 void
 BluetoothDaemonHandsfreeInterface::StartVoiceRecognition(
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->StartVoiceRecognitionCmd(aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::StopVoiceRecognition(
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->StopVoiceRecognitionCmd(aRes);
 }
 
 /* Volume */
 
 void
 BluetoothDaemonHandsfreeInterface::VolumeControl(
-  BluetoothHandsfreeVolumeType aType, int aVolume,
+  BluetoothHandsfreeVolumeType aType, int aVolume, const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->VolumeControlCmd(aType, aVolume, aRes);
 }
 
 /* Device status */
@@ -1151,63 +1442,66 @@ BluetoothDaemonHandsfreeInterface::Devic
   mModule->DeviceStatusNotificationCmd(aNtkState, aSvcType, aSignal,
                                        aBattChg, aRes);
 }
 
 /* Responses */
 
 void
 BluetoothDaemonHandsfreeInterface::CopsResponse(
-  const char* aCops, BluetoothHandsfreeResultHandler* aRes)
+  const char* aCops, const nsAString& aBdAddr,
+  BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->CopsResponseCmd(aCops, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::CindResponse(
   int aSvc, int aNumActive, int aNumHeld,
   BluetoothHandsfreeCallState aCallSetupState,
   int aSignal, int aRoam, int aBattChg,
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->CindResponseCmd(aSvc, aNumActive, aNumHeld, aCallSetupState,
                            aSignal, aRoam, aBattChg, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::FormattedAtResponse(
-  const char* aRsp, BluetoothHandsfreeResultHandler* aRes)
+  const char* aRsp, const nsAString& aBdAddr,
+  BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->FormattedAtResponseCmd(aRsp, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::AtResponse(
   BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->AtResponseCmd(aResponseCode, aErrorCode, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::ClccResponse(
   int aIndex, BluetoothHandsfreeCallDirection aDir,
   BluetoothHandsfreeCallState aState,
   BluetoothHandsfreeCallMode aMode,
   BluetoothHandsfreeCallMptyType aMpty,
   const nsAString& aNumber,
   BluetoothHandsfreeCallAddressType aType,
+  const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->ClccResponseCmd(aIndex, aDir, aState, aMode, aMpty, aNumber,
                            aType, aRes);
 }
 
@@ -1222,16 +1516,28 @@ BluetoothDaemonHandsfreeInterface::Phone
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->PhoneStateChangeCmd(aNumActive, aNumHeld, aCallSetupState, aNumber,
                                aType, aRes);
 }
 
+/* Wide Band Speech */
+
+void
+BluetoothDaemonHandsfreeInterface::ConfigureWbs(
+  const nsAString& aBdAddr, BluetoothHandsfreeWbsConfig aConfig,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  MOZ_ASSERT(mModule);
+
+  mModule->ConfigureWbsCmd(aBdAddr, aConfig, aRes);
+}
+
 void
 BluetoothDaemonHandsfreeInterface::DispatchError(
   BluetoothHandsfreeResultHandler* aRes, BluetoothStatus aStatus)
 {
   BluetoothResultRunnable1<BluetoothHandsfreeResultHandler, void,
                            BluetoothStatus, BluetoothStatus>::Dispatch(
     aRes, &BluetoothHandsfreeResultHandler::OnError,
     ConstantInitOp1<BluetoothStatus>(aStatus));
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h
@@ -106,16 +106,22 @@ public:
   /* Phone State */
 
   nsresult PhoneStateChangeCmd(int aNumActive, int aNumHeld,
                                BluetoothHandsfreeCallState aCallSetupState,
                                const nsAString& aNumber,
                                BluetoothHandsfreeCallAddressType aType,
                                BluetoothHandsfreeResultHandler* aRes);
 
+  /* Wide Band Speech */
+
+  nsresult ConfigureWbsCmd(const nsAString& aBdAddr,
+                           BluetoothHandsfreeWbsConfig aConfig,
+                           BluetoothHandsfreeResultHandler* aRes);
+
 protected:
   nsresult Send(BluetoothDaemonPDU* aPDU,
                 BluetoothHandsfreeResultHandler* aRes);
 
   void HandleSvc(const BluetoothDaemonPDUHeader& aHeader,
                  BluetoothDaemonPDU& aPDU, void* aUserData);
 
   //
@@ -208,70 +214,103 @@ protected:
 
   typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
                                          BluetoothHandsfreeAudioState,
                                          nsString,
                                          BluetoothHandsfreeAudioState,
                                          const nsAString&>
     AudioStateNotification;
 
-  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
-    BluetoothHandsfreeVoiceRecognitionState>
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    BluetoothHandsfreeVoiceRecognitionState, nsString,
+    BluetoothHandsfreeVoiceRecognitionState, const nsAString&>
     VoiceRecognitionNotification;
 
-  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+    nsString,
+    const nsAString&>
     AnswerCallNotification;
 
-  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+    nsString,
+    const nsAString&>
     HangupCallNotification;
 
+  typedef BluetoothNotificationRunnable3<NotificationHandlerWrapper, void,
+    BluetoothHandsfreeVolumeType, int, nsString,
+    BluetoothHandsfreeVolumeType, int, const nsAString&>
+    VolumeNotification;
+
   typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
-                                         BluetoothHandsfreeVolumeType, int>
-    VolumeNotification;
-
-  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
-                                         nsString, const nsAString&>
+    nsString, nsString,
+    const nsAString&, const nsAString&>
     DialCallNotification;
 
-  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
-                                         char>
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    char, nsString,
+    char, const nsAString&>
     DtmfNotification;
 
-  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
-                                         BluetoothHandsfreeNRECState>
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    BluetoothHandsfreeNRECState, nsString,
+    BluetoothHandsfreeNRECState, const nsAString&>
     NRECNotification;
 
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    BluetoothHandsfreeCallHoldType, nsString,
+    BluetoothHandsfreeCallHoldType, const nsAString&>
+    CallHoldNotification;
+
   typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
-                                         BluetoothHandsfreeCallHoldType>
-    CallHoldNotification;
-
-  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+    nsString,
+    const nsAString&>
     CnumNotification;
 
-  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+    nsString,
+    const nsAString&>
     CindNotification;
 
-  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+    nsString,
+    const nsAString&>
     CopsNotification;
 
-  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+    nsString,
+    const nsAString&>
     ClccNotification;
 
-  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
-                                         nsCString, const nsACString&>
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    nsCString, nsString,
+    const nsACString&, const nsAString&>
     UnknownAtNotification;
 
-  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+    nsString,
+    const nsAString&>
     KeyPressedNotification;
 
+  class ConnectionStateInitOp;
   class AudioStateInitOp;
-  class ConnectionStateInitOp;
+  class VoiceRecognitionInitOp;
+  class AnswerCallInitOp;
+  class HangupCallInitOp;
+  class VolumeInitOp;
   class DialCallInitOp;
+  class DtmfInitOp;
+  class NRECInitOp;
+  class CallHoldInitOp;
+  class CnumInitOp;
+  class CindInitOp;
+  class CopsInitOp;
+  class ClccInitOp;
   class VolumeInitOp;
   class UnknownAtInitOp;
+  class KeyPressedInitOp;
 
   void ConnectionStateNtf(const BluetoothDaemonPDUHeader& aHeader,
                           BluetoothDaemonPDU& aPDU);
 
   void AudioStateNtf(const BluetoothDaemonPDUHeader& aHeader,
                      BluetoothDaemonPDU& aPDU);
 
   void VoiceRecognitionNtf(const BluetoothDaemonPDUHeader& aHeader,
@@ -316,16 +355,17 @@ protected:
   void KeyPressedNtf(const BluetoothDaemonPDUHeader& aHeader,
                      BluetoothDaemonPDU& aPDU);
 
   void HandleNtf(const BluetoothDaemonPDUHeader& aHeader,
                  BluetoothDaemonPDU& aPDU,
                  void* aUserData);
 
   static BluetoothHandsfreeNotificationHandler* sNotificationHandler;
+  static nsString sConnectedDeviceAddress;
 };
 
 class BluetoothDaemonHandsfreeInterface MOZ_FINAL
   : public BluetoothHandsfreeInterface
 {
   class CleanupResultHandler;
   class InitResultHandler;
 
@@ -336,75 +376,86 @@ class BluetoothDaemonHandsfreeInterface 
   };
 
 public:
   BluetoothDaemonHandsfreeInterface(BluetoothDaemonHandsfreeModule* aModule);
   ~BluetoothDaemonHandsfreeInterface();
 
   void Init(
     BluetoothHandsfreeNotificationHandler* aNotificationHandler,
-    BluetoothHandsfreeResultHandler* aRes);
+    int aMaxNumClients, 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);
+  void StartVoiceRecognition(const nsAString& aBdAddr,
+                             BluetoothHandsfreeResultHandler* aRes);
+  void StopVoiceRecognition(const nsAString& aBdAddr,
+                            BluetoothHandsfreeResultHandler* aRes);
 
   /* Volume */
 
   void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
+                     const nsAString& aBdAddr,
                      BluetoothHandsfreeResultHandler* aRes);
 
   /* Device status */
 
   void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
                                 BluetoothHandsfreeServiceType aSvcType,
                                 int aSignal, int aBattChg,
                                 BluetoothHandsfreeResultHandler* aRes);
 
   /* Responses */
 
-  void CopsResponse(const char* aCops,
+  void CopsResponse(const char* aCops, const nsAString& aBdAddr,
                     BluetoothHandsfreeResultHandler* aRes);
   void CindResponse(int aSvc, int aNumActive, int aNumHeld,
                     BluetoothHandsfreeCallState aCallSetupState,
                     int aSignal, int aRoam, int aBattChg,
+                    const nsAString& aBdAddr,
                     BluetoothHandsfreeResultHandler* aRes);
-  void FormattedAtResponse(const char* aRsp,
+  void FormattedAtResponse(const char* aRsp, const nsAString& aBdAddr,
                            BluetoothHandsfreeResultHandler* aRes);
   void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+                  const nsAString& aBdAddr,
                   BluetoothHandsfreeResultHandler* aRes);
   void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
                     BluetoothHandsfreeCallState aState,
                     BluetoothHandsfreeCallMode aMode,
                     BluetoothHandsfreeCallMptyType aMpty,
                     const nsAString& aNumber,
                     BluetoothHandsfreeCallAddressType aType,
+                    const nsAString& aBdAddr,
                     BluetoothHandsfreeResultHandler* aRes);
 
   /* Phone State */
 
   void PhoneStateChange(int aNumActive, int aNumHeld,
                         BluetoothHandsfreeCallState aCallSetupState,
                         const nsAString& aNumber,
                         BluetoothHandsfreeCallAddressType aType,
                         BluetoothHandsfreeResultHandler* aRes);
 
+  /* Wide Band Speech */
+  void ConfigureWbs(const nsAString& aBdAddr,
+                    BluetoothHandsfreeWbsConfig aConfig,
+                    BluetoothHandsfreeResultHandler* aRes);
+
 private:
   void DispatchError(BluetoothHandsfreeResultHandler* aRes,
                      BluetoothStatus aStatus);
 
   BluetoothDaemonHandsfreeModule* mModule;
 };
 
 END_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
@@ -70,79 +70,103 @@ struct BluetoothHandsfreeHALCallback
     ConnectionStateNotification;
 
   typedef BluetoothNotificationHALRunnable2<
     HandsfreeNotificationHandlerWrapper, void,
     BluetoothHandsfreeAudioState, nsString,
     BluetoothHandsfreeAudioState, const nsAString&>
     AudioStateNotification;
 
-  typedef BluetoothNotificationHALRunnable1<
+  typedef BluetoothNotificationHALRunnable2<
     HandsfreeNotificationHandlerWrapper, void,
-    BluetoothHandsfreeVoiceRecognitionState>
+    BluetoothHandsfreeVoiceRecognitionState, nsString,
+    BluetoothHandsfreeVoiceRecognitionState, const nsAString&>
     VoiceRecognitionNotification;
 
-  typedef BluetoothNotificationHALRunnable0<
-    HandsfreeNotificationHandlerWrapper, void>
+  typedef BluetoothNotificationHALRunnable1<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, const nsAString&>
     AnswerCallNotification;
 
-  typedef BluetoothNotificationHALRunnable0<
-    HandsfreeNotificationHandlerWrapper, void>
+  typedef BluetoothNotificationHALRunnable1<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, const nsAString&>
     HangupCallNotification;
 
+  typedef BluetoothNotificationHALRunnable3<
+    HandsfreeNotificationHandlerWrapper, void,
+    BluetoothHandsfreeVolumeType, int, nsString,
+    BluetoothHandsfreeVolumeType, int, const nsAString&>
+    VolumeNotification;
+
+  typedef BluetoothNotificationHALRunnable2<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, nsString, const nsAString&, const nsAString&>
+    DialCallNotification;
+
+  typedef BluetoothNotificationHALRunnable2<
+    HandsfreeNotificationHandlerWrapper, void,
+    char, nsString, char, const nsAString&>
+    DtmfNotification;
+
   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>
+    BluetoothHandsfreeNRECState, nsString,
+    BluetoothHandsfreeNRECState, const nsAString&>
     NRECNotification;
 
-  typedef BluetoothNotificationHALRunnable1<
-    HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeCallHoldType>
+  typedef BluetoothNotificationHALRunnable2<
+    HandsfreeNotificationHandlerWrapper, void,
+    BluetoothHandsfreeCallHoldType, nsString,
+    BluetoothHandsfreeCallHoldType, const nsAString&>
     CallHoldNotification;
 
-  typedef BluetoothNotificationHALRunnable0<
-    HandsfreeNotificationHandlerWrapper, void>
+  typedef BluetoothNotificationHALRunnable1<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, const nsAString&>
     CnumNotification;
 
-  typedef BluetoothNotificationHALRunnable0<
-    HandsfreeNotificationHandlerWrapper, void>
+  typedef BluetoothNotificationHALRunnable1<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, const nsAString&>
     CindNotification;
 
-  typedef BluetoothNotificationHALRunnable0<
-    HandsfreeNotificationHandlerWrapper, void>
+  typedef BluetoothNotificationHALRunnable1<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, const nsAString&>
     CopsNotification;
 
-  typedef BluetoothNotificationHALRunnable0<
-    HandsfreeNotificationHandlerWrapper, void>
+  typedef BluetoothNotificationHALRunnable1<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, const nsAString&>
     ClccNotification;
 
+  typedef BluetoothNotificationHALRunnable2<
+    HandsfreeNotificationHandlerWrapper, void,
+    nsCString, nsString, const nsACString&, const nsAString&>
+    UnknownAtNotification;
+
   typedef BluetoothNotificationHALRunnable1<
-    HandsfreeNotificationHandlerWrapper, void, nsCString, const nsACString&>
-    UnknownAtNotification;
-
-  typedef BluetoothNotificationHALRunnable0<
-    HandsfreeNotificationHandlerWrapper, void>
+    HandsfreeNotificationHandlerWrapper, void,
+    nsString, const nsAString&>
     KeyPressedNotification;
 
   // Bluedroid Handsfree callbacks
 
   static void
   ConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddr)
   {
+    if (aState == BTHF_CONNECTION_STATE_CONNECTED && aBdAddr) {
+      memcpy(&sConnectedDeviceAddress, aBdAddr,
+             sizeof(sConnectedDeviceAddress));
+    } else if (aState == BTHF_CONNECTION_STATE_DISCONNECTED) {
+      memset(&sConnectedDeviceAddress, 0,
+             sizeof(sConnectedDeviceAddress));
+    }
+
     ConnectionStateNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification,
       aState, aBdAddr);
   }
 
   static void
   AudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddr)
   {
@@ -151,111 +175,128 @@ struct BluetoothHandsfreeHALCallback
       aState, aBdAddr);
   }
 
   static void
   VoiceRecognition(bthf_vr_state_t aState)
   {
     VoiceRecognitionNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification,
-      aState);
+      aState, &sConnectedDeviceAddress);
   }
 
   static void
   AnswerCall()
   {
     AnswerCallNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::AnswerCallNotification);
+      &BluetoothHandsfreeNotificationHandler::AnswerCallNotification,
+      &sConnectedDeviceAddress);
   }
 
   static void
   HangupCall()
   {
     HangupCallNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::HangupCallNotification);
+      &BluetoothHandsfreeNotificationHandler::HangupCallNotification,
+      &sConnectedDeviceAddress);
   }
 
   static void
   Volume(bthf_volume_type_t aType, int aVolume)
   {
     VolumeNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::VolumeNotification,
-      aType, aVolume);
+      aType, aVolume, &sConnectedDeviceAddress);
   }
 
   static void
   DialCall(char* aNumber)
   {
     DialCallNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::DialCallNotification, aNumber);
+      &BluetoothHandsfreeNotificationHandler::DialCallNotification,
+      aNumber, &sConnectedDeviceAddress);
   }
 
   static void
   Dtmf(char aDtmf)
   {
     DtmfNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::DtmfNotification, aDtmf);
+      &BluetoothHandsfreeNotificationHandler::DtmfNotification,
+      aDtmf, &sConnectedDeviceAddress);
   }
 
   static void
   NoiseReductionEchoCancellation(bthf_nrec_t aNrec)
   {
     NRECNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::NRECNotification, aNrec);
+      &BluetoothHandsfreeNotificationHandler::NRECNotification,
+      aNrec, &sConnectedDeviceAddress);
   }
 
   static void
   CallHold(bthf_chld_type_t aChld)
   {
     CallHoldNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::CallHoldNotification, aChld);
+      &BluetoothHandsfreeNotificationHandler::CallHoldNotification,
+      aChld, &sConnectedDeviceAddress);
   }
 
   static void
   Cnum()
   {
     CnumNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::CnumNotification);
+      &BluetoothHandsfreeNotificationHandler::CnumNotification,
+      &sConnectedDeviceAddress);
   }
 
   static void
   Cind()
   {
     CindNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::CindNotification);
+      &BluetoothHandsfreeNotificationHandler::CindNotification,
+      &sConnectedDeviceAddress);
   }
 
   static void
   Cops()
   {
     CopsNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::CopsNotification);
+      &BluetoothHandsfreeNotificationHandler::CopsNotification,
+      &sConnectedDeviceAddress);
   }
 
   static void
   Clcc()
   {
     ClccNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::ClccNotification);
+      &BluetoothHandsfreeNotificationHandler::ClccNotification,
+      &sConnectedDeviceAddress);
   }
 
   static void
   UnknownAt(char* aAtString)
   {
     UnknownAtNotification::Dispatch(
       &BluetoothHandsfreeNotificationHandler::UnknownAtNotification,
-      aAtString);
+      aAtString, &sConnectedDeviceAddress);
   }
 
   static void
   KeyPressed()
   {
     KeyPressedNotification::Dispatch(
-      &BluetoothHandsfreeNotificationHandler::KeyPressedNotification);
+      &BluetoothHandsfreeNotificationHandler::KeyPressedNotification,
+      &sConnectedDeviceAddress);
   }
+
+  static bt_bdaddr_t sConnectedDeviceAddress;
+};
+
+bt_bdaddr_t BluetoothHandsfreeHALCallback::sConnectedDeviceAddress = {
+  {0, 0, 0, 0, 0, 0}
 };
 
 // Interface
 //
 
 BluetoothHandsfreeHALInterface::BluetoothHandsfreeHALInterface(
   const bthf_interface_t* aInterface)
 : mInterface(aInterface)
@@ -264,17 +305,17 @@ BluetoothHandsfreeHALInterface::Bluetoot
 }
 
 BluetoothHandsfreeHALInterface::~BluetoothHandsfreeHALInterface()
 { }
 
 void
 BluetoothHandsfreeHALInterface::Init(
   BluetoothHandsfreeNotificationHandler* aNotificationHandler,
-  BluetoothHandsfreeResultHandler* aRes)
+  int aMaxNumClients, BluetoothHandsfreeResultHandler* aRes)
 {
   static bthf_callbacks_t sCallbacks = {
     sizeof(sCallbacks),
     BluetoothHandsfreeHALCallback::ConnectionState,
     BluetoothHandsfreeHALCallback::AudioState,
     BluetoothHandsfreeHALCallback::VoiceRecognition,
     BluetoothHandsfreeHALCallback::AnswerCall,
     BluetoothHandsfreeHALCallback::HangupCall,
@@ -395,45 +436,47 @@ BluetoothHandsfreeHALInterface::Disconne
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Voice Recognition */
 
 void
 BluetoothHandsfreeHALInterface::StartVoiceRecognition(
+  const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   bt_status_t status = mInterface->start_voice_recognition();
 
   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();
 
   if (aRes) {
     DispatchBluetoothHandsfreeHALResult(
       aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Volume */
 
 void
 BluetoothHandsfreeHALInterface::VolumeControl(
-  BluetoothHandsfreeVolumeType aType, int aVolume,
+  BluetoothHandsfreeVolumeType aType, int aVolume, const nsAString& aBdAddr,
   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 {
@@ -473,32 +516,34 @@ BluetoothHandsfreeHALInterface::DeviceSt
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Responses */
 
 void
 BluetoothHandsfreeHALInterface::CopsResponse(
-  const char* aCops, BluetoothHandsfreeResultHandler* aRes)
+  const char* aCops, const nsAString& aBdAddr,
+  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,
+  const nsAString& aBdAddr,
   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,
@@ -511,30 +556,32 @@ BluetoothHandsfreeHALInterface::CindResp
     DispatchBluetoothHandsfreeHALResult(
       aRes, &BluetoothHandsfreeResultHandler::CindResponse,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothHandsfreeHALInterface::FormattedAtResponse(
-  const char* aRsp, BluetoothHandsfreeResultHandler* aRes)
+  const char* aRsp, const nsAString& aBdAddr,
+  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,
+  const nsAString& aBdAddr,
   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 {
@@ -552,16 +599,17 @@ void
 BluetoothHandsfreeHALInterface::ClccResponse(
   int aIndex,
   BluetoothHandsfreeCallDirection aDir,
   BluetoothHandsfreeCallState aState,
   BluetoothHandsfreeCallMode aMode,
   BluetoothHandsfreeCallMptyType aMpty,
   const nsAString& aNumber,
   BluetoothHandsfreeCallAddressType aType,
+  const nsAString& aBdAddr,
   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;
@@ -608,9 +656,28 @@ BluetoothHandsfreeHALInterface::PhoneSta
 
   if (aRes) {
     DispatchBluetoothHandsfreeHALResult(
       aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange,
       ConvertDefault(status, STATUS_FAIL));
   }
 }
 
+/* Wide Band Speech */
+
+void
+BluetoothHandsfreeHALInterface::ConfigureWbs(
+  const nsAString& aBdAddr,
+  BluetoothHandsfreeWbsConfig aConfig,
+  BluetoothHandsfreeResultHandler* aRes)
+{
+  // TODO: to be implemented
+
+  bt_status_t status = BT_STATUS_UNSUPPORTED;
+
+  if (aRes) {
+    DispatchBluetoothHandsfreeHALResult(
+      aRes, &BluetoothHandsfreeResultHandler::ConfigureWbs,
+      ConvertDefault(status, STATUS_FAIL));
+  }
+}
+
 END_BLUETOOTH_NAMESPACE
--- a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h
+++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h
@@ -18,75 +18,87 @@ class BluetoothHALInterface;
 
 class BluetoothHandsfreeHALInterface MOZ_FINAL
   : public BluetoothHandsfreeInterface
 {
 public:
   friend class BluetoothHALInterface;
 
   void Init(BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+            int aMaxNumClients,
             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);
+  void StartVoiceRecognition(const nsAString& aBdAddr,
+                             BluetoothHandsfreeResultHandler* aRes);
+  void StopVoiceRecognition(const nsAString& aBdAddr,
+                            BluetoothHandsfreeResultHandler* aRes);
 
   /* Volume */
 
   void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
+                     const nsAString& aBdAddr,
                      BluetoothHandsfreeResultHandler* aRes);
 
   /* Device status */
 
   void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
                                 BluetoothHandsfreeServiceType aSvcType,
                                 int aSignal, int aBattChg,
                                 BluetoothHandsfreeResultHandler* aRes);
 
   /* Responses */
 
-  void CopsResponse(const char* aCops,
+  void CopsResponse(const char* aCops, const nsAString& aBdAddr,
                     BluetoothHandsfreeResultHandler* aRes);
   void CindResponse(int aSvc, int aNumActive, int aNumHeld,
                     BluetoothHandsfreeCallState aCallSetupState, int aSignal,
-                    int aRoam, int aBattChg,
+                    int aRoam, int aBattChg, const nsAString& aBdAddr,
                     BluetoothHandsfreeResultHandler* aRes);
-  void FormattedAtResponse(const char* aRsp,
+  void FormattedAtResponse(const char* aRsp, const nsAString& aBdAddr,
                            BluetoothHandsfreeResultHandler* aRes);
   void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+                  const nsAString& aBdAddr,
                   BluetoothHandsfreeResultHandler* aRes);
   void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
                     BluetoothHandsfreeCallState aState,
                     BluetoothHandsfreeCallMode aMode,
                     BluetoothHandsfreeCallMptyType aMpty,
                     const nsAString& aNumber,
                     BluetoothHandsfreeCallAddressType aType,
+                    const nsAString& aBdAddr,
                     BluetoothHandsfreeResultHandler* aRes);
 
   /* Phone State */
 
   void PhoneStateChange(int aNumActive, int aNumHeld,
                         BluetoothHandsfreeCallState aCallSetupState,
                         const nsAString& aNumber,
                         BluetoothHandsfreeCallAddressType aType,
                         BluetoothHandsfreeResultHandler* aRes);
 
+  /* Wide Band Speech */
+
+  void ConfigureWbs(const nsAString& aBdAddr,
+                    BluetoothHandsfreeWbsConfig aConfig,
+                    BluetoothHandsfreeResultHandler* aRes);
+
 protected:
   BluetoothHandsfreeHALInterface(const bthf_interface_t* aInterface);
   ~BluetoothHandsfreeHALInterface();
 
 private:
   const bthf_interface_t* mInterface;
 };
 
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -52,16 +52,18 @@ namespace {
 
   // Wait 3.7 seconds until Dialer stops playing busy tone. '3' seconds is the
   // time window set in Dialer and the extra '0.7' second is a magic number.
   // The mechanism should be revised once we know the exact time at which
   // Dialer stops playing.
   static int sBusyToneInterval = 3700; //unit: ms
 } // anonymous namespace
 
+const int BluetoothHfpManager::MAX_NUM_CLIENTS = 1;
+
 static bool
 IsValidDtmf(const char aChar) {
   // Valid DTMF: [*#0-9ABCD]
   return (aChar == '*' || aChar == '#') ||
          (aChar >= '0' && aChar <= '9') ||
          (aChar >= 'A' && aChar <= 'D');
 }
 
@@ -303,17 +305,17 @@ public:
      */
     RunInit();
   }
 
   void RunInit()
   {
     BluetoothHfpManager* hfpManager = BluetoothHfpManager::Get();
 
-    mInterface->Init(hfpManager, this);
+    mInterface->Init(hfpManager, BluetoothHfpManager::MAX_NUM_CLIENTS, this);
   }
 
 private:
   BluetoothHandsfreeInterface* mInterface;
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
 class InitResultHandlerRunnable MOZ_FINAL : public nsRunnable
@@ -633,18 +635,19 @@ BluetoothHfpManager::HandleVolumeChanged
   if (mReceiveVgsFlag) {
     mReceiveVgsFlag = false;
     return;
   }
 
   // Only send volume back when there's a connected headset
   if (IsConnected()) {
     NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
-    sBluetoothHfpInterface->VolumeControl(HFP_VOLUME_TYPE_SPEAKER, mCurrentVgs,
-                                          new VolumeControlResultHandler());
+    sBluetoothHfpInterface->VolumeControl(
+      HFP_VOLUME_TYPE_SPEAKER, mCurrentVgs, mDeviceAddress,
+      new VolumeControlResultHandler());
   }
 }
 
 void
 BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId)
 {
   nsCOMPtr<nsIMobileConnectionService> mcService =
     do_GetService(NS_MOBILE_CONNECTION_SERVICE_CONTRACTID);
@@ -762,17 +765,17 @@ BluetoothHfpManager::SendCLCC(Call& aCal
   if (callState == HFP_CALL_STATE_INCOMING &&
       FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
     callState = HFP_CALL_STATE_WAITING;
   }
 
   sBluetoothHfpInterface->ClccResponse(
     aIndex, aCall.mDirection, callState, HFP_CALL_MODE_VOICE,
     HFP_CALL_MPTY_TYPE_SINGLE, aCall.mNumber,
-    aCall.mType, new ClccResponseResultHandler());
+    aCall.mType, mDeviceAddress, new ClccResponseResultHandler());
 }
 
 class FormattedAtResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -782,17 +785,17 @@ public:
 };
 
 void
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->FormattedAtResponse(
-    aMessage, new FormattedAtResponseResultHandler());
+    aMessage, mDeviceAddress, new FormattedAtResponseResultHandler());
 }
 
 class AtResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -802,17 +805,17 @@ public:
 };
 
 void
 BluetoothHfpManager::SendResponse(BluetoothHandsfreeAtResponse aResponseCode)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->AtResponse(
-    aResponseCode, 0, new AtResponseResultHandler());
+    aResponseCode, 0, mDeviceAddress, new AtResponseResultHandler());
 }
 
 class PhoneStateChangeResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -1356,34 +1359,34 @@ BluetoothHfpManager::AudioStateNotificat
   if (aState == HFP_AUDIO_STATE_CONNECTED ||
       aState == HFP_AUDIO_STATE_DISCONNECTED) {
     NotifyConnectionStateChanged(
       NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
   }
 }
 
 void
-BluetoothHfpManager::AnswerCallNotification()
+BluetoothHfpManager::AnswerCallNotification(const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NotifyDialer(NS_LITERAL_STRING("ATA"));
 }
 
 void
-BluetoothHfpManager::HangupCallNotification()
+BluetoothHfpManager::HangupCallNotification(const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NotifyDialer(NS_LITERAL_STRING("CHUP"));
 }
 
 void
 BluetoothHfpManager::VolumeNotification(
-  BluetoothHandsfreeVolumeType aType, int aVolume)
+  BluetoothHandsfreeVolumeType aType, int aVolume, const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE_VOID(aVolume >= 0 && aVolume <= 15);
 
   if (aType == HFP_VOLUME_TYPE_MICROPHONE) {
     mCurrentVgm = aVolume;
   } else if (aType == HFP_VOLUME_TYPE_SPEAKER) {
@@ -1400,29 +1403,30 @@ BluetoothHfpManager::VolumeNotification(
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     NS_ENSURE_TRUE_VOID(os);
 
     os->NotifyObservers(nullptr, "bluetooth-volume-change", data.get());
   }
 }
 
 void
-BluetoothHfpManager::DtmfNotification(char aDtmf)
+BluetoothHfpManager::DtmfNotification(char aDtmf, const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE_VOID(IsValidDtmf(aDtmf));
 
   nsAutoCString message("VTS=");
   message += aDtmf;
   NotifyDialer(NS_ConvertUTF8toUTF16(message));
 }
 
 void
-BluetoothHfpManager::CallHoldNotification(BluetoothHandsfreeCallHoldType aChld)
+BluetoothHfpManager::CallHoldNotification(BluetoothHandsfreeCallHoldType aChld,
+                                          const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!IsSupportedChld((int)aChld)) {
     // We currently don't support Enhanced Call Control.
     // AT+CHLD=1x and AT+CHLD=2x will be ignored
     SendResponse(HFP_AT_RESPONSE_ERROR);
     return;
@@ -1430,17 +1434,18 @@ BluetoothHfpManager::CallHoldNotificatio
 
   SendResponse(HFP_AT_RESPONSE_OK);
 
   nsAutoCString message("CHLD=");
   message.AppendInt((int)aChld);
   NotifyDialer(NS_ConvertUTF8toUTF16(message));
 }
 
-void BluetoothHfpManager::DialCallNotification(const nsAString& aNumber)
+void BluetoothHfpManager::DialCallNotification(const nsAString& aNumber,
+                                               const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCString message = NS_ConvertUTF16toUTF8(aNumber);
 
   // There are three cases based on aNumber,
   // 1) Empty value:    Redial, BLDN
   // 2) >xxx:           Memory dial, ATD>xxx
@@ -1471,17 +1476,17 @@ void BluetoothHfpManager::DialCallNotifi
 
     nsAutoCString newMsg("ATD");
     newMsg += StringHead(message, message.Length() - 1);
     NotifyDialer(NS_ConvertUTF8toUTF16(newMsg));
   }
 }
 
 void
-BluetoothHfpManager::CnumNotification()
+BluetoothHfpManager::CnumNotification(const nsAString& aBdAddress)
 {
   static const uint8_t sAddressType[] {
     [HFP_CALL_ADDRESS_TYPE_UNKNOWN] = 0x81,
     [HFP_CALL_ADDRESS_TYPE_INTERNATIONAL] = 0x91 // for completeness
   };
 
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -1505,57 +1510,59 @@ public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::CindResponse failed: %d",
                (int)aStatus);
   }
 };
 
 void
-BluetoothHfpManager::CindNotification()
+BluetoothHfpManager::CindNotification(const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
   int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
   BluetoothHandsfreeCallState callState =
     ConvertToBluetoothHandsfreeCallState(GetCallSetupState());
 
-  sBluetoothHfpInterface->CindResponse(mService, numActive, numHeld,
-                                       callState, mSignal, mRoam, mBattChg,
-                                       new CindResponseResultHandler());
+  sBluetoothHfpInterface->CindResponse(
+    mService, numActive, numHeld,
+    callState, mSignal, mRoam, mBattChg,
+    aBdAddress,
+    new CindResponseResultHandler());
 }
 
 class CopsResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::CopsResponse failed: %d",
                (int)aStatus);
   }
 };
 
 void
-BluetoothHfpManager::CopsNotification()
+BluetoothHfpManager::CopsNotification(const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->CopsResponse(
     NS_ConvertUTF16toUTF8(mOperatorName).get(),
-    new CopsResponseResultHandler());
+    aBdAddress, new CopsResponseResultHandler());
 }
 
 void
-BluetoothHfpManager::ClccNotification()
+BluetoothHfpManager::ClccNotification(const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   uint32_t callNumbers = mCurrentCallArray.Length();
   uint32_t i;
   for (i = 1; i < callNumbers; i++) {
     SendCLCC(mCurrentCallArray[i], i);
   }
@@ -1566,27 +1573,28 @@ BluetoothHfpManager::ClccNotification()
 
     SendCLCC(mCdmaSecondCall, 2);
   }
 
   SendResponse(HFP_AT_RESPONSE_OK);
 }
 
 void
-BluetoothHfpManager::UnknownAtNotification(const nsACString& aAtString)
+BluetoothHfpManager::UnknownAtNotification(const nsACString& aAtString,
+                                           const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   BT_LOGR("[%s]", nsCString(aAtString).get());
 
   SendResponse(HFP_AT_RESPONSE_ERROR);
 }
 
 void
-BluetoothHfpManager::KeyPressedNotification()
+BluetoothHfpManager::KeyPressedNotification(const nsAString& aBdAddress)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   bool hasActiveCall =
     (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED) > 0);
 
   // Refer to AOSP HeadsetStateMachine.processKeyPressed
   if (FindFirstCall(nsITelephonyService::CALL_STATE_INCOMING)
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
@@ -72,16 +72,18 @@ public:
 
 class BluetoothHfpManager : public BluetoothHfpManagerBase
                           , public BluetoothHandsfreeNotificationHandler
                           , public BatteryObserver
 {
 public:
   BT_DECL_HFP_MGR_BASE
 
+  static const int MAX_NUM_CLIENTS;
+
   void OnConnectError();
   void OnDisconnectError();
 
   virtual void GetName(nsACString& aName)
   {
     aName.AssignLiteral("HFP/HSP");
   }
 
@@ -112,29 +114,34 @@ public:
   //
   // Bluetooth notifications
   //
 
   void ConnectionStateNotification(BluetoothHandsfreeConnectionState aState,
                                    const nsAString& aBdAddress) MOZ_OVERRIDE;
   void AudioStateNotification(BluetoothHandsfreeAudioState aState,
                               const nsAString& aBdAddress) MOZ_OVERRIDE;
-  void AnswerCallNotification() MOZ_OVERRIDE;
-  void HangupCallNotification() MOZ_OVERRIDE;
+  void AnswerCallNotification(const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void HangupCallNotification(const nsAString& aBdAddress) MOZ_OVERRIDE;
   void VolumeNotification(BluetoothHandsfreeVolumeType aType,
-                          int aVolume) MOZ_OVERRIDE;
-  void DtmfNotification(char aDtmf) MOZ_OVERRIDE;
-  void CallHoldNotification(BluetoothHandsfreeCallHoldType aChld) MOZ_OVERRIDE;
-  void DialCallNotification(const nsAString& aNumber) MOZ_OVERRIDE;
-  void CnumNotification() MOZ_OVERRIDE;
-  void CindNotification() MOZ_OVERRIDE;
-  void CopsNotification() MOZ_OVERRIDE;
-  void ClccNotification() MOZ_OVERRIDE;
-  void UnknownAtNotification(const nsACString& aAtString) MOZ_OVERRIDE;
-  void KeyPressedNotification() MOZ_OVERRIDE;
+                          int aVolume,
+                          const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void DtmfNotification(char aDtmf,
+                        const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void CallHoldNotification(BluetoothHandsfreeCallHoldType aChld,
+                            const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void DialCallNotification(const nsAString& aNumber,
+                            const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void CnumNotification(const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void CindNotification(const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void CopsNotification(const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void ClccNotification(const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void UnknownAtNotification(const nsACString& aAtString,
+                             const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void KeyPressedNotification(const nsAString& aBdAddress) MOZ_OVERRIDE;
 
 private:
   class GetVolumeTask;
   class CloseScoTask;
   class CloseScoRunnable;
   class RespondToBLDNTask;
   class MainThreadTask;