Bug 1102703: (9/10) Porting bluetooth interface of bluez 5.26 (handsfree) r=btian, f=tzimmermann
authorBruce Sun <brsun@mozilla.com>
Fri, 09 Jan 2015 13:39:27 +0800
changeset 236008 fc0b50dc40fe0e54ed26a515c7c4cec9e9eef0bd
parent 236007 24505b76d6ad652d7822cb49bf846cd631bcc7b2
child 236009 bf12689b10f8a449d90196b1ea5bbcc9bd198709
push id384
push usermartin.thomson@gmail.com
push dateFri, 09 Jan 2015 21:26:39 +0000
reviewersbtian
bugs1102703
milestone37.0a1
Bug 1102703: (9/10) Porting bluetooth interface of bluez 5.26 (handsfree) r=btian, f=tzimmermann
dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h
dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.cpp
@@ -12,18 +12,20 @@ BEGIN_BLUETOOTH_NAMESPACE
 
 //
 // Handsfree module
 //
 
 BluetoothHandsfreeNotificationHandler*
   BluetoothDaemonHandsfreeModule::sNotificationHandler;
 
+#if ANDROID_VERSION < 21
 nsString BluetoothDaemonHandsfreeModule::sConnectedDeviceAddress(
   NS_ConvertUTF8toUTF16(BLUETOOTH_ADDRESS_NONE));
+#endif
 
 void
 BluetoothDaemonHandsfreeModule::SetNotificationHandler(
   BluetoothHandsfreeNotificationHandler* aNotificationHandler)
 {
   sNotificationHandler = aNotificationHandler;
 }
 
@@ -145,63 +147,86 @@ BluetoothDaemonHandsfreeModule::Disconne
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::StartVoiceRecognitionCmd(
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_START_VOICE_RECOGNITION,
-                           0)); // No payload
+                           6)); // Address (BlueZ 5.25)
 
-  nsresult rv = Send(pdu, aRes);
+  nsresult rv;
+#if ANDROID_VERSION >= 21
+  rv = PackPDU(
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+#endif
+  rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::StopVoiceRecognitionCmd(
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_STOP_VOICE_RECOGNITION,
-                           0)); // No payload
+                           6)); // Address (BlueZ 5.25)
 
-  nsresult rv = Send(pdu, aRes);
+  nsresult rv;
+#if ANDROID_VERSION >= 21
+  rv = PackPDU(
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+#endif
+  rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::VolumeControlCmd(
   BluetoothHandsfreeVolumeType aType, int aVolume,
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_VOLUME_CONTROL,
                            1 + // Volume type
-                           1)); // Volume
+                           1 + // Volume
+                           6)); // Address (BlueZ 5.25)
 
+#if ANDROID_VERSION >= 21
+  nsresult rv = PackPDU(
+    aType, PackConversion<int, uint8_t>(aVolume),
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+#else
   nsresult rv = PackPDU(aType, PackConversion<int, uint8_t>(aVolume), *pdu);
+#endif
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
@@ -234,109 +259,146 @@ BluetoothDaemonHandsfreeModule::DeviceSt
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::CopsResponseCmd(
-  const char* aCops, BluetoothHandsfreeResultHandler* aRes)
+  const char* aCops, const nsAString& aRemoteAddr,
+  BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_COPS_RESPONSE,
-                           0)); // Dynamically allocated
+                           0 + // Dynamically allocated
+                           6)); // Address (BlueZ 5.25)
 
+#if ANDROID_VERSION >= 21
+  nsresult rv = PackPDU(
+    PackCString0(nsDependentCString(aCops)),
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+#else
   nsresult rv = PackPDU(PackCString0(nsDependentCString(aCops)), *pdu);
+#endif
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::CindResponseCmd(
   int aSvc, int aNumActive, int aNumHeld,
   BluetoothHandsfreeCallState aCallSetupState,
   int aSignal, int aRoam, int aBattChg,
+  const nsAString& aRemoteAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CIND_RESPONSE,
                            1 + // Service
                            1 + // # Active
                            1 + // # Held
                            1 + // Call state
                            1 + // Signal strength
                            1 + // Roaming
-                           1)); // Battery level
+                           1 + // Battery level
+                           6)); // Address (BlueZ 5.25)
 
+#if ANDROID_VERSION >= 21
+  nsresult rv = PackPDU(
+    PackConversion<int, uint8_t>(aSvc),
+    PackConversion<int, uint8_t>(aNumActive),
+    PackConversion<int, uint8_t>(aNumHeld),
+    aCallSetupState,
+    PackConversion<int, uint8_t>(aSignal),
+    PackConversion<int, uint8_t>(aRoam),
+    PackConversion<int, uint8_t>(aBattChg),
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+#else
   nsresult rv = PackPDU(PackConversion<int, uint8_t>(aSvc),
                         PackConversion<int, uint8_t>(aNumActive),
                         PackConversion<int, uint8_t>(aNumHeld),
                         aCallSetupState,
                         PackConversion<int, uint8_t>(aSignal),
                         PackConversion<int, uint8_t>(aRoam),
                         PackConversion<int, uint8_t>(aBattChg), *pdu);
+#endif
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::FormattedAtResponseCmd(
-  const char* aRsp, BluetoothHandsfreeResultHandler* aRes)
+  const char* aRsp, const nsAString& aRemoteAddr,
+  BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_FORMATTED_AT_RESPONSE,
-                           0)); // Dynamically allocated
+                           0 + // Dynamically allocated
+                           6)); // Address (BlueZ 5.25)
 
+#if ANDROID_VERSION >= 21
+  nsresult rv = PackPDU(
+    PackCString0(nsDependentCString(aRsp)),
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+#else
   nsresult rv = PackPDU(PackCString0(nsDependentCString(aRsp)), *pdu);
+#endif
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
   return NS_OK;
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::AtResponseCmd(
   BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_AT_RESPONSE,
                            1 + // AT Response code
-                           1)); // Error code
+                           1 + // Error code
+                           6)); // Address (BlueZ 5.25)
 
+#if ANDROID_VERSION >= 21
+  nsresult rv = PackPDU(
+    aResponseCode, PackConversion<int, uint8_t>(aErrorCode),
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+#else
   nsresult rv = PackPDU(aResponseCode,
                         PackConversion<int, uint8_t>(aErrorCode), *pdu);
+#endif
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
@@ -344,35 +406,44 @@ BluetoothDaemonHandsfreeModule::AtRespon
 }
 
 nsresult
 BluetoothDaemonHandsfreeModule::ClccResponseCmd(
   int aIndex,
   BluetoothHandsfreeCallDirection aDir, BluetoothHandsfreeCallState aState,
   BluetoothHandsfreeCallMode aMode, BluetoothHandsfreeCallMptyType aMpty,
   const nsAString& aNumber, BluetoothHandsfreeCallAddressType aType,
-  BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aRemoteAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ConvertUTF16toUTF8 number(aNumber);
 
   nsAutoPtr<BluetoothDaemonPDU> pdu(
     new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CLCC_RESPONSE,
                            1 + // Call index
                            1 + // Call direction
                            1 + // Call state
                            1 + // Call mode
                            1 + // Call MPTY
                            1 + // Address type
-                           number.Length() + 1)); // Number string + \0
+                           number.Length() + 1 + // Number string + \0
+                           6)); // Address (BlueZ 5.25)
 
+#if ANDROID_VERSION >= 21
+  nsresult rv = PackPDU(
+    PackConversion<int, uint8_t>(aIndex),
+    aDir, aState, aMode, aMpty, aType,
+    PackCString0(number),
+    PackConversion<nsAString, BluetoothAddress>(aRemoteAddr), *pdu);
+#else
   nsresult rv = PackPDU(PackConversion<int, uint8_t>(aIndex),
                         aDir, aState, aMode, aMpty, aType,
                         PackCString0(number), *pdu);
+#endif
   if (NS_FAILED(rv)) {
     return rv;
   }
   rv = Send(pdu, aRes);
   if (NS_FAILED(rv)) {
     return rv;
   }
   unused << pdu.forget();
@@ -674,21 +745,23 @@ public:
 
     /* Read address */
     rv = UnpackPDU(
       pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
     if (NS_FAILED(rv)) {
       return rv;
     }
 
+#if ANDROID_VERSION < 21
     if (aArg1 == HFP_CONNECTION_STATE_CONNECTED) {
       sConnectedDeviceAddress = aArg2;
     } else if (aArg1 == HFP_CONNECTION_STATE_DISCONNECTED) {
       sConnectedDeviceAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
     }
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::ConnectionStateNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -755,18 +828,25 @@ public:
 
     /* Read state */
     nsresult rv = UnpackPDU(pdu, aArg1);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg2 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::VoiceRecognitionNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -784,18 +864,25 @@ public:
   AnswerCallInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1) const
   {
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg1 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::AnswerCallNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -813,18 +900,25 @@ public:
   HangupCallInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1) const
   {
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg1 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::HangupCallNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -857,18 +951,25 @@ public:
 
     /* Read volume */
     rv = UnpackPDU(pdu, UnpackConversion<uint8_t, int>(aArg2));
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg3));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg3 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::VolumeNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -887,25 +988,36 @@ public:
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1, nsString& aArg2) const
   {
     BluetoothDaemonPDU& pdu = GetPDU();
 
-    /* Read number */
-    nsresult rv = UnpackPDU(pdu, UnpackString0(aArg1));
+    nsresult rv;
+    /* Read address
+     * It's a little weird to parse aArg2(aBdAddr) before parsing
+     * aArg1(aNumber), but this order is defined in BlueZ 5.25 anyway.
+     */
+#if ANDROID_VERSION >= 21
+    rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
     if (NS_FAILED(rv)) {
       return rv;
     }
+#else
+    aArg2 = sConnectedDeviceAddress;
+#endif
 
-    /* Read address */
-    // TODO
-    aArg2 = sConnectedDeviceAddress;
+    /* Read number */
+    rv = UnpackPDU(pdu, UnpackString0(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::DialCallNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -931,18 +1043,25 @@ public:
 
     /* Read tone */
     nsresult rv = UnpackPDU(pdu, aArg1);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg2 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::DtmfNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -968,18 +1087,25 @@ public:
 
     /* Read state */
     nsresult rv = UnpackPDU(pdu, aArg1);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg2 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::NRECNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1005,18 +1131,25 @@ public:
 
     /* Read type */
     nsresult rv = UnpackPDU(pdu, aArg1);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg2 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::CallHoldNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1034,18 +1167,25 @@ public:
   CnumInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1) const
   {
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg1 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::CnumNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1063,18 +1203,25 @@ public:
   CindInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1) const
   {
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg1 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::CindNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1092,18 +1239,25 @@ public:
   CopsInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1) const
   {
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg1 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::CopsNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1121,18 +1275,25 @@ public:
   ClccInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1) const
   {
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg1 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::ClccNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1151,25 +1312,36 @@ public:
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsCString& aArg1, nsString& aArg2) const
   {
     BluetoothDaemonPDU& pdu = GetPDU();
 
-    /* Read string */
-    nsresult rv = UnpackPDU(pdu, UnpackCString0(aArg1));
+    nsresult rv;
+    /* Read address
+     * It's a little weird to parse aArg2(aBdAddr) before parsing
+     * aArg1(aAtString), but this order is defined in BlueZ 5.25 anyway.
+     */
+#if ANDROID_VERSION >= 21
+    rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg2));
     if (NS_FAILED(rv)) {
       return rv;
     }
+#else
+    aArg2 = sConnectedDeviceAddress;
+#endif
 
-    /* Read address */
-    // TODO
-    aArg2 = sConnectedDeviceAddress;
+    /* Read string */
+    rv = UnpackPDU(pdu, UnpackCString0(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::UnknownAtNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1187,18 +1359,25 @@ public:
   KeyPressedInitOp(BluetoothDaemonPDU& aPDU)
     : PDUInitOp(aPDU)
   { }
 
   nsresult
   operator () (nsString& aArg1) const
   {
     /* Read address */
-    // TODO
+#if ANDROID_VERSION >= 21
+    nsresult rv = UnpackPDU(
+      GetPDU(), UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+#else
     aArg1 = sConnectedDeviceAddress;
+#endif
     WarnAboutTrailingData();
     return NS_OK;
   }
 };
 
 void
 BluetoothDaemonHandsfreeModule::KeyPressedNtf(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
@@ -1401,38 +1580,38 @@ BluetoothDaemonHandsfreeInterface::Disco
 /* Voice Recognition */
 
 void
 BluetoothDaemonHandsfreeInterface::StartVoiceRecognition(
   const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
-  mModule->StartVoiceRecognitionCmd(aRes);
+  mModule->StartVoiceRecognitionCmd(aBdAddr, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::StopVoiceRecognition(
   const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
-  mModule->StopVoiceRecognitionCmd(aRes);
+  mModule->StopVoiceRecognitionCmd(aBdAddr, aRes);
 }
 
 /* Volume */
 
 void
 BluetoothDaemonHandsfreeInterface::VolumeControl(
   BluetoothHandsfreeVolumeType aType, int aVolume, const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
-  mModule->VolumeControlCmd(aType, aVolume, aRes);
+  mModule->VolumeControlCmd(aType, aVolume, aBdAddr, aRes);
 }
 
 /* Device status */
 
 void
 BluetoothDaemonHandsfreeInterface::DeviceStatusNotification(
   BluetoothHandsfreeNetworkState aNtkState,
   BluetoothHandsfreeServiceType aSvcType, int aSignal, int aBattChg,
@@ -1448,67 +1627,67 @@ BluetoothDaemonHandsfreeInterface::Devic
 
 void
 BluetoothDaemonHandsfreeInterface::CopsResponse(
   const char* aCops, const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
-  mModule->CopsResponseCmd(aCops, aRes);
+  mModule->CopsResponseCmd(aCops, aBdAddr, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::CindResponse(
   int aSvc, int aNumActive, int aNumHeld,
   BluetoothHandsfreeCallState aCallSetupState,
   int aSignal, int aRoam, int aBattChg,
   const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
   mModule->CindResponseCmd(aSvc, aNumActive, aNumHeld, aCallSetupState,
-                           aSignal, aRoam, aBattChg, aRes);
+                           aSignal, aRoam, aBattChg, aBdAddr, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::FormattedAtResponse(
   const char* aRsp, const nsAString& aBdAddr,
   BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
-  mModule->FormattedAtResponseCmd(aRsp, aRes);
+  mModule->FormattedAtResponseCmd(aRsp, aBdAddr, aRes);
 }
 
 void
 BluetoothDaemonHandsfreeInterface::AtResponse(
   BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
   const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
   MOZ_ASSERT(mModule);
 
-  mModule->AtResponseCmd(aResponseCode, aErrorCode, aRes);
+  mModule->AtResponseCmd(aResponseCode, aErrorCode, aBdAddr, 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);
+                           aType, aBdAddr, aRes);
 }
 
 /* Phone State */
 
 void
 BluetoothDaemonHandsfreeInterface::PhoneStateChange(
   int aNumActive, int aNumHeld,
   BluetoothHandsfreeCallState aCallSetupState,
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHandsfreeInterface.h
@@ -62,51 +62,56 @@ public:
                          BluetoothHandsfreeResultHandler* aRes);
   nsresult ConnectAudioCmd(const nsAString& aBdAddr,
                            BluetoothHandsfreeResultHandler* aRes);
   nsresult DisconnectAudioCmd(const nsAString& aBdAddr,
                               BluetoothHandsfreeResultHandler* aRes);
 
   /* Voice Recognition */
 
-  nsresult StartVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes);
-  nsresult StopVoiceRecognitionCmd(BluetoothHandsfreeResultHandler* aRes);
+  nsresult StartVoiceRecognitionCmd(const nsAString& aBdAddr,
+                                    BluetoothHandsfreeResultHandler* aRes);
+  nsresult StopVoiceRecognitionCmd(const nsAString& aBdAddr,
+                                   BluetoothHandsfreeResultHandler* aRes);
 
   /* Volume */
 
   nsresult VolumeControlCmd(BluetoothHandsfreeVolumeType aType, int aVolume,
+                            const nsAString& aBdAddr,
                             BluetoothHandsfreeResultHandler* aRes);
 
   /* Device status */
 
   nsresult DeviceStatusNotificationCmd(
     BluetoothHandsfreeNetworkState aNtkState,
     BluetoothHandsfreeServiceType aSvcType,
     int aSignal, int aBattChg,
     BluetoothHandsfreeResultHandler* aRes);
 
   /* Responses */
 
-  nsresult CopsResponseCmd(const char* aCops,
+  nsresult CopsResponseCmd(const char* aCops, const nsAString& aBdAddr,
                            BluetoothHandsfreeResultHandler* aRes);
   nsresult CindResponseCmd(int aSvc, int aNumActive, int aNumHeld,
                            BluetoothHandsfreeCallState aCallSetupState,
                            int aSignal, int aRoam, int aBattChg,
+                           const nsAString& aBdAddr,
                            BluetoothHandsfreeResultHandler* aRes);
-  nsresult FormattedAtResponseCmd(const char* aRsp,
+  nsresult FormattedAtResponseCmd(const char* aRsp, const nsAString& aBdAddr,
                                   BluetoothHandsfreeResultHandler* aRes);
   nsresult AtResponseCmd(BluetoothHandsfreeAtResponse aResponseCode,
-                         int aErrorCode,
+                         int aErrorCode, const nsAString& aBdAddr,
                          BluetoothHandsfreeResultHandler* aRes);
   nsresult ClccResponseCmd(int aIndex, BluetoothHandsfreeCallDirection aDir,
                            BluetoothHandsfreeCallState aState,
                            BluetoothHandsfreeCallMode aMode,
                            BluetoothHandsfreeCallMptyType aMpty,
                            const nsAString& aNumber,
                            BluetoothHandsfreeCallAddressType aType,
+                           const nsAString& aBdAddr,
                            BluetoothHandsfreeResultHandler* aRes);
 
   /* Phone State */
 
   nsresult PhoneStateChangeCmd(int aNumActive, int aNumHeld,
                                BluetoothHandsfreeCallState aCallSetupState,
                                const nsAString& aNumber,
                                BluetoothHandsfreeCallAddressType aType,
@@ -356,17 +361,24 @@ protected:
   void KeyPressedNtf(const BluetoothDaemonPDUHeader& aHeader,
                      BluetoothDaemonPDU& aPDU);
 
   void HandleNtf(const BluetoothDaemonPDUHeader& aHeader,
                  BluetoothDaemonPDU& aPDU,
                  void* aUserData);
 
   static BluetoothHandsfreeNotificationHandler* sNotificationHandler;
+#if ANDROID_VERSION < 21
+  /* |sConnectedDeviceAddress| stores Bluetooth device address of the
+   * connected device. Before BlueZ 5.25, we maintain this address by ourselves
+   * through ConnectionStateNtf(); after BlueZ 5.25, every callback carries
+   * this address directly so we don't have to keep it.
+   */
   static nsString sConnectedDeviceAddress;
+#endif
 };
 
 class BluetoothDaemonHandsfreeInterface MOZ_FINAL
   : public BluetoothHandsfreeInterface
 {
   class CleanupResultHandler;
   class InitResultHandler;
 
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h
@@ -616,16 +616,55 @@ PackPDU(const T1& aIn1, const T2& aIn2, 
   }
   rv = PackPDU(aIn6, aPDU);
   if (NS_FAILED(rv)) {
     return rv;
   }
   return PackPDU(aIn7, aPDU);
 }
 
+template <typename T1, typename T2, typename T3,
+          typename T4, typename T5, typename T6,
+          typename T7, typename T8>
+inline nsresult
+PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3,
+        const T4& aIn4, const T5& aIn5, const T6& aIn6,
+        const T7& aIn7, const T8& aIn8, BluetoothDaemonPDU& aPDU)
+{
+  nsresult rv = PackPDU(aIn1, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aIn2, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aIn3, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aIn4, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aIn5, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aIn6, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aIn7, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  return PackPDU(aIn8, aPDU);
+}
+
 //
 // Unpacking
 //
 
 inline nsresult
 UnpackPDU(BluetoothDaemonPDU& aPDU, int8_t& aOut)
 {
   return aPDU.Read(aOut);