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 248819 fc0b50dc40fe0e54ed26a515c7c4cec9e9eef0bd
parent 248818 24505b76d6ad652d7822cb49bf846cd631bcc7b2
child 248820 bf12689b10f8a449d90196b1ea5bbcc9bd198709
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbtian
bugs1102703
milestone37.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1102703: (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);