Bug 1095488: Add Bluetooth AVRCP module, r=shuang
authorThomas Zimmermann <tdz@users.sourceforge.net>
Wed, 07 Jan 2015 11:32:05 +0100
changeset 239173 68e1922b83f0ac9bb064d4f87677d4ef6371b5fa
parent 239172 6aa9be9df45007e8a40c5f6accf11302dc562e64
child 239174 e48fd6fe791f8a1d8a6997164cafea772d0c309a
push id7472
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 20:36:27 +0000
treeherdermozilla-aurora@300ca104f8fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshuang
bugs1095488
milestone37.0a1
Bug 1095488: Add Bluetooth AVRCP module, r=shuang
dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp
dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h
dom/bluetooth/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.cpp
@@ -0,0 +1,828 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BluetoothDaemonAvrcpInterface.h"
+#include "mozilla/unused.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// AVRCP module
+//
+
+BluetoothAvrcpNotificationHandler*
+  BluetoothDaemonAvrcpModule::sNotificationHandler;
+
+void
+BluetoothDaemonAvrcpModule::SetNotificationHandler(
+  BluetoothAvrcpNotificationHandler* aNotificationHandler)
+{
+  sNotificationHandler = aNotificationHandler;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::Send(BluetoothDaemonPDU* aPDU,
+                                 BluetoothAvrcpResultHandler* aRes)
+{
+  if (aRes) {
+    aRes->AddRef(); // Keep reference for response
+  }
+  return Send(aPDU, static_cast<void*>(aRes));
+}
+
+void
+BluetoothDaemonAvrcpModule::HandleSvc(const BluetoothDaemonPDUHeader& aHeader,
+                                      BluetoothDaemonPDU& aPDU, void* aUserData)
+{
+  static void (BluetoothDaemonAvrcpModule::* const HandleOp[])(
+    const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = {
+    INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::HandleRsp),
+    INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::HandleNtf),
+  };
+
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  unsigned int isNtf = !!(aHeader.mOpcode & 0x80);
+
+  (this->*(HandleOp[isNtf]))(aHeader, aPDU, aUserData);
+}
+
+// Commands
+//
+
+nsresult
+BluetoothDaemonAvrcpModule::GetPlayStatusRspCmd(
+  ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos,
+  BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAY_STATUS_RSP,
+                           1 + // Play status
+                           4 + // Duration
+                           4)); // Position
+
+  nsresult rv = PackPDU(aPlayStatus, aSongLen, aSongPos, *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspCmd(
+  int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
+  BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_ATTR_RSP,
+                           1 + // # Attributes
+                           aNumAttr)); // Player attributes
+
+  nsresult rv = PackPDU(
+    PackConversion<int, uint8_t>(aNumAttr),
+    PackArray<BluetoothAvrcpPlayerAttribute>(aPAttrs, aNumAttr), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::ListPlayerAppValueRspCmd(
+  int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_LIST_PLAYER_APP_VALUE_RSP,
+                           1 + // # Values
+                           aNumVal)); // Player values
+
+  nsresult rv = PackPDU(PackConversion<int, uint8_t>(aNumVal),
+                        PackArray<uint8_t>(aPVals, aNumVal), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::GetPlayerAppValueRspCmd(
+  uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues,
+  BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_RSP,
+                           1 + // # Pairs
+                           2 * aNumAttrs)); // Attribute-value pairs
+  nsresult rv = PackPDU(
+    aNumAttrs,
+    BluetoothAvrcpAttributeValuePairs(aIds, aValues, aNumAttrs), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspCmd(
+  int aNumAttr, const uint8_t* aIds, const char** aTexts,
+  BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP,
+                           0)); // Dynamically allocated
+  nsresult rv = PackPDU(
+    PackConversion<int, uint8_t>(aNumAttr),
+    BluetoothAvrcpAttributeTextPairs(aIds, aTexts, aNumAttr), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspCmd(
+  int aNumVal, const uint8_t* aIds, const char** aTexts,
+  BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP,
+                           0)); // Dynamically allocated
+  nsresult rv = PackPDU(
+    PackConversion<int, uint8_t>(aNumVal),
+    BluetoothAvrcpAttributeTextPairs(aIds, aTexts, aNumVal), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::GetElementAttrRspCmd(
+  uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttr,
+  BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_GET_ELEMENT_ATTR_RSP,
+                           0)); // Dynamically allocated
+  nsresult rv = PackPDU(
+    aNumAttr,
+    PackArray<BluetoothAvrcpElementAttribute>(aAttr, aNumAttr), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::SetPlayerAppValueRspCmd(
+  BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_PLAYER_APP_VALUE_RSP,
+                           1)); // Status code
+
+  nsresult rv = PackPDU(aRspStatus, *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::RegisterNotificationRspCmd(
+  BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
+  const BluetoothAvrcpNotificationParam& aParam,
+  BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_REGISTER_NOTIFICATION_RSP,
+                           1 + // Event
+                           1 + // Type
+                           1 + // Data length
+                           256)); // Maximum data length
+
+  nsresult rv = PackPDU(aEvent, aType,
+                        BluetoothAvrcpEventParamPair(aEvent, aParam), *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+nsresult
+BluetoothDaemonAvrcpModule::SetVolumeCmd(uint8_t aVolume,
+                                         BluetoothAvrcpResultHandler* aRes)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsAutoPtr<BluetoothDaemonPDU> pdu(
+    new BluetoothDaemonPDU(SERVICE_ID, OPCODE_SET_VOLUME,
+                           1)); // Volume
+
+  nsresult rv = PackPDU(aVolume, *pdu);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = Send(pdu, aRes);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  unused << pdu.forget();
+  return NS_OK;
+}
+
+// Responses
+//
+
+void
+BluetoothDaemonAvrcpModule::ErrorRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ErrorRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::OnError, UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::GetPlayStatusRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::ListPlayerAppValueRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::GetPlayerAppValueRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::GetElementAttrRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::SetPlayerAppValueRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::RegisterNotificationRspRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::SetVolumeRsp(
+  const BluetoothDaemonPDUHeader& aHeader,
+  BluetoothDaemonPDU& aPDU, BluetoothAvrcpResultHandler* aRes)
+{
+  ResultRunnable::Dispatch(
+    aRes, &BluetoothAvrcpResultHandler::SetVolume,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::HandleRsp(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
+  void* aUserData)
+{
+  static void (BluetoothDaemonAvrcpModule::* const HandleRsp[])(
+    const BluetoothDaemonPDUHeader&,
+    BluetoothDaemonPDU&,
+    BluetoothAvrcpResultHandler*) = {
+    INIT_ARRAY_AT(OPCODE_ERROR,
+      &BluetoothDaemonAvrcpModule::ErrorRsp),
+    INIT_ARRAY_AT(OPCODE_GET_PLAY_STATUS_RSP,
+      &BluetoothDaemonAvrcpModule::GetPlayStatusRspRsp),
+    INIT_ARRAY_AT(OPCODE_LIST_PLAYER_APP_ATTR_RSP,
+      &BluetoothDaemonAvrcpModule::ListPlayerAppAttrRspRsp),
+    INIT_ARRAY_AT(OPCODE_LIST_PLAYER_APP_VALUE_RSP,
+      &BluetoothDaemonAvrcpModule::ListPlayerAppValueRspRsp),
+    INIT_ARRAY_AT(OPCODE_GET_PLAYER_APP_VALUE_RSP,
+      &BluetoothDaemonAvrcpModule::GetPlayerAppValueRspRsp),
+    INIT_ARRAY_AT(OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP,
+      &BluetoothDaemonAvrcpModule::GetPlayerAppAttrTextRspRsp),
+    INIT_ARRAY_AT(OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP,
+      &BluetoothDaemonAvrcpModule::GetPlayerAppValueTextRspRsp),
+    INIT_ARRAY_AT(OPCODE_GET_ELEMENT_ATTR_RSP,
+      &BluetoothDaemonAvrcpModule::GetElementAttrRspRsp),
+    INIT_ARRAY_AT(OPCODE_SET_PLAYER_APP_VALUE_RSP,
+      &BluetoothDaemonAvrcpModule::SetPlayerAppValueRspRsp),
+    INIT_ARRAY_AT(OPCODE_REGISTER_NOTIFICATION_RSP,
+      &BluetoothDaemonAvrcpModule::RegisterNotificationRspRsp),
+    INIT_ARRAY_AT(OPCODE_SET_VOLUME,
+      &BluetoothDaemonAvrcpModule::SetVolumeRsp)
+  };
+
+  MOZ_ASSERT(!NS_IsMainThread()); // I/O thread
+
+  if (NS_WARN_IF(!(aHeader.mOpcode < MOZ_ARRAY_LENGTH(HandleRsp))) ||
+      NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) {
+    return;
+  }
+
+  nsRefPtr<BluetoothAvrcpResultHandler> res =
+    already_AddRefed<BluetoothAvrcpResultHandler>(
+      static_cast<BluetoothAvrcpResultHandler*>(aUserData));
+
+  if (!res) {
+    return; // Return early if no result handler has been set for response
+  }
+
+  (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
+}
+
+// Notifications
+//
+
+// Returns the current notification handler to a notification runnable
+class BluetoothDaemonAvrcpModule::NotificationHandlerWrapper MOZ_FINAL
+{
+public:
+  typedef BluetoothAvrcpNotificationHandler ObjectType;
+
+  static ObjectType* GetInstance()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    return sNotificationHandler;
+  }
+};
+
+// Init operator class for RemoteFeatureNotification
+class BluetoothDaemonAvrcpModule::RemoteFeatureInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  RemoteFeatureInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (nsString& aArg1, unsigned long& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read address */
+    nsresult rv = UnpackPDU(
+      pdu, UnpackConversion<BluetoothAddress, nsAString>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read feature */
+    rv = UnpackPDU(
+      pdu,
+      UnpackConversion<BluetoothAvrcpRemoteFeature, unsigned long>(aArg2));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
+void
+BluetoothDaemonAvrcpModule::RemoteFeatureNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  RemoteFeatureNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::RemoteFeatureNotification,
+    RemoteFeatureInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::GetPlayStatusNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  GetPlayStatusNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::GetPlayStatusNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  ListPlayerAppAttrNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::ListPlayerAppValuesNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  ListPlayerAppValuesNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+// Init operator class for GetPlayerAppValueNotification
+class BluetoothDaemonAvrcpModule::GetPlayerAppValueInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  GetPlayerAppValueInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (uint8_t& aArg1,
+               nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read number of attributes */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read attributes */
+    rv = UnpackPDU(
+      pdu, UnpackArray<BluetoothAvrcpPlayerAttribute>(aArg2, aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
+void
+BluetoothDaemonAvrcpModule::GetPlayerAppValueNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  GetPlayerAppValueNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification,
+    GetPlayerAppValueInitOp(aPDU));
+}
+
+// Init operator class for GetPlayerAppAttrsTextNotification
+class BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  GetPlayerAppAttrsTextInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (uint8_t& aArg1,
+               nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read number of attributes */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read attributes */
+    rv = UnpackPDU(
+      pdu, UnpackArray<BluetoothAvrcpPlayerAttribute>(aArg2, aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
+void
+BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  GetPlayerAppAttrsTextNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification,
+    GetPlayerAppAttrsTextInitOp(aPDU));
+}
+
+// Init operator class for GetPlayerAppValuesTextNotification
+class BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  GetPlayerAppValuesTextInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (uint8_t& aArg1, uint8_t& aArg2,
+               nsAutoArrayPtr<uint8_t>& aArg3) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read attribute */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read number of values */
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read values */
+    rv = UnpackPDU(pdu, UnpackArray<uint8_t>(aArg3, aArg2));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
+void
+BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  GetPlayerAppValuesTextNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification,
+    GetPlayerAppValuesTextInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::SetPlayerAppValueNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  SetPlayerAppValueNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+// Init operator class for GetElementAttrNotification
+class BluetoothDaemonAvrcpModule::GetElementAttrInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  GetElementAttrInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (uint8_t& aArg1,
+               nsAutoArrayPtr<BluetoothAvrcpMediaAttribute>& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    /* Read number of attributes */
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+
+    /* Read attributes */
+    rv = UnpackPDU(
+      pdu, UnpackArray<BluetoothAvrcpMediaAttribute>(aArg2, aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
+void
+BluetoothDaemonAvrcpModule::GetElementAttrNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  GetElementAttrNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::GetElementAttrNotification,
+    GetElementAttrInitOp(aPDU));
+}
+
+void
+BluetoothDaemonAvrcpModule::RegisterNotificationNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  RegisterNotificationNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::RegisterNotificationNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+#if ANDROID_VERSION >= 19
+void
+BluetoothDaemonAvrcpModule::VolumeChangeNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  VolumeChangeNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::VolumeChangeNotification,
+    UnpackPDUInitOp(aPDU));
+}
+
+// Init operator class for PassthroughCmdNotification
+class BluetoothDaemonAvrcpModule::PassthroughCmdInitOp MOZ_FINAL
+  : private PDUInitOp
+{
+public:
+  PassthroughCmdInitOp(BluetoothDaemonPDU& aPDU)
+    : PDUInitOp(aPDU)
+  { }
+
+  nsresult
+  operator () (int& aArg1, int& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, UnpackConversion<uint8_t, int>(aArg1));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, UnpackConversion<uint8_t, int>(aArg2));
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
+void
+BluetoothDaemonAvrcpModule::PassthroughCmdNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU)
+{
+  PassthroughCmdNotification::Dispatch(
+    &BluetoothAvrcpNotificationHandler::PassthroughCmdNotification,
+    PassthroughCmdInitOp(aPDU));
+}
+#endif
+
+void
+BluetoothDaemonAvrcpModule::HandleNtf(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
+  void* aUserData)
+{
+  static void (BluetoothDaemonAvrcpModule::* const HandleNtf[])(
+    const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&) = {
+#if ANDROID_VERSION >= 19
+    INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::RemoteFeatureNtf),
+    INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::GetPlayStatusNtf),
+    INIT_ARRAY_AT(2, &BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf),
+    INIT_ARRAY_AT(3, &BluetoothDaemonAvrcpModule::ListPlayerAppValuesNtf),
+    INIT_ARRAY_AT(4, &BluetoothDaemonAvrcpModule::GetPlayerAppValueNtf),
+    INIT_ARRAY_AT(5, &BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextNtf),
+    INIT_ARRAY_AT(6, &BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf),
+    INIT_ARRAY_AT(7, &BluetoothDaemonAvrcpModule::SetPlayerAppValueNtf),
+    INIT_ARRAY_AT(8, &BluetoothDaemonAvrcpModule::GetElementAttrNtf),
+    INIT_ARRAY_AT(9, &BluetoothDaemonAvrcpModule::RegisterNotificationNtf),
+    INIT_ARRAY_AT(10, &BluetoothDaemonAvrcpModule::VolumeChangeNtf),
+    INIT_ARRAY_AT(11, &BluetoothDaemonAvrcpModule::PassthroughCmdNtf)
+#else
+    INIT_ARRAY_AT(0, &BluetoothDaemonAvrcpModule::GetPlayStatusNtf),
+    INIT_ARRAY_AT(1, &BluetoothDaemonAvrcpModule::ListPlayerAppAttrNtf),
+    INIT_ARRAY_AT(2, &BluetoothDaemonAvrcpModule::ListPlayerAppValuesNtf),
+    INIT_ARRAY_AT(3, &BluetoothDaemonAvrcpModule::GetPlayerAppValueNtf),
+    INIT_ARRAY_AT(4, &BluetoothDaemonAvrcpModule::GetPlayerAppAttrsTextNtf),
+    INIT_ARRAY_AT(5, &BluetoothDaemonAvrcpModule::GetPlayerAppValuesTextNtf),
+    INIT_ARRAY_AT(6, &BluetoothDaemonAvrcpModule::SetPlayerAppValueNtf),
+    INIT_ARRAY_AT(7, &BluetoothDaemonAvrcpModule::GetElementAttrNtf),
+    INIT_ARRAY_AT(8, &BluetoothDaemonAvrcpModule::RegisterNotificationNtf)
+#endif
+  };
+
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  uint8_t index = aHeader.mOpcode - 0x81;
+
+  if (NS_WARN_IF(!(index < MOZ_ARRAY_LENGTH(HandleNtf))) ||
+      NS_WARN_IF(!HandleNtf[index])) {
+    return;
+  }
+
+  (this->*(HandleNtf[index]))(aHeader, aPDU);
+}
+
+END_BLUETOOTH_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonAvrcpInterface.h
@@ -0,0 +1,292 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_bluetooth_bluetoothdaemonavrcpinterface_h
+#define mozilla_dom_bluetooth_bluetoothdaemonavrcpinterface_h
+
+#include "BluetoothDaemonHelpers.h"
+#include "BluetoothInterface.h"
+#include "BluetoothInterfaceHelpers.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothSetupResultHandler;
+
+class BluetoothDaemonAvrcpModule
+{
+public:
+  enum {
+    SERVICE_ID = 0x08
+  };
+
+  enum {
+    OPCODE_ERROR = 0x00,
+    OPCODE_GET_PLAY_STATUS_RSP = 0x01,
+    OPCODE_LIST_PLAYER_APP_ATTR_RSP = 0x02,
+    OPCODE_LIST_PLAYER_APP_VALUE_RSP = 0x03,
+    OPCODE_GET_PLAYER_APP_VALUE_RSP = 0x04,
+    OPCODE_GET_PLAYER_APP_ATTR_TEXT_RSP = 0x05,
+    OPCODE_GET_PLAYER_APP_VALUE_TEXT_RSP = 0x06,
+    OPCODE_GET_ELEMENT_ATTR_RSP = 0x07,
+    OPCODE_SET_PLAYER_APP_VALUE_RSP = 0x08,
+    OPCODE_REGISTER_NOTIFICATION_RSP = 0x09,
+    OPCODE_SET_VOLUME = 0x0a,
+#if ANDROID_VERSION >= 19
+    OPCODE_REMOTE_FEATURES_NTF = 0x81,
+    OPCODE_GET_PLAY_STATUS_NTF = 0x82,
+    OPCODE_LIST_PLAYER_APP_ATTR_NTF = 0x83,
+    OPCODE_LIST_PLAYER_APP_VALUES_NTF = 0x84,
+    OPCODE_GET_PLAYER_APP_VALUE_NTF = 0x85,
+    OPCODE_GET_PLAYER_APP_ATTRS_TEXT_NTF = 0x86,
+    OPCODE_GET_PLAYER_APP_VALUES_TEXT_NTF = 0x87,
+    OPCODE_SET_PLAYER_APP_VALUE_NTF = 0x88,
+    OPCODE_GET_ELEMENT_ATTR_NTF = 0x89,
+    OPCODE_REGISTER_NOTIFICATION_NTF = 0x8a,
+    OPCODE_VOLUME_CHANGE_NTF = 0x8b,
+    OPCODE_PASSTHROUGH_CMD_NTF = 0x8c
+#else /* defined by BlueZ 5.14 */
+    OPCODE_GET_PLAY_STATUS_NTF = 0x81,
+    OPCODE_LIST_PLAYER_APP_ATTR_NTF = 0x82,
+    OPCODE_LIST_PLAYER_APP_VALUES_NTF = 0x83,
+    OPCODE_GET_PLAYER_APP_VALUE_NTF = 0x84,
+    OPCODE_GET_PLAYER_APP_ATTRS_TEXT_NTF = 0x85,
+    OPCODE_GET_PLAYER_APP_VALUES_TEXT_NTF = 0x86,
+    OPCODE_SET_PLAYER_APP_VALUE_NTF = 0x87,
+    OPCODE_GET_ELEMENT_ATTR_NTF = 0x88,
+    OPCODE_REGISTER_NOTIFICATION_NTF = 0x89
+#endif
+  };
+
+  virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0;
+
+  virtual nsresult RegisterModule(uint8_t aId, uint8_t aMode,
+                                  BluetoothSetupResultHandler* aRes) = 0;
+
+  virtual nsresult UnregisterModule(uint8_t aId,
+                                    BluetoothSetupResultHandler* aRes) = 0;
+
+  void SetNotificationHandler(
+    BluetoothAvrcpNotificationHandler* aNotificationHandler);
+
+  //
+  // Commands
+  //
+
+  nsresult GetPlayStatusRspCmd(
+    ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos,
+    BluetoothAvrcpResultHandler* aRes);
+
+  nsresult ListPlayerAppAttrRspCmd(
+    int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
+    BluetoothAvrcpResultHandler* aRes);
+
+  nsresult ListPlayerAppValueRspCmd(
+    int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes);
+
+  nsresult GetPlayerAppValueRspCmd(
+    uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues,
+    BluetoothAvrcpResultHandler* aRes);
+
+  nsresult GetPlayerAppAttrTextRspCmd(
+    int aNumAttr, const uint8_t* aIds, const char** aTexts,
+    BluetoothAvrcpResultHandler* aRes);
+
+  nsresult GetPlayerAppValueTextRspCmd(
+    int aNumVal, const uint8_t* aIds, const char** aTexts,
+    BluetoothAvrcpResultHandler* aRes);
+
+  nsresult GetElementAttrRspCmd(
+    uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttr,
+    BluetoothAvrcpResultHandler* aRes);
+
+  nsresult SetPlayerAppValueRspCmd(
+    BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes);
+
+  nsresult RegisterNotificationRspCmd(
+    BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
+    const BluetoothAvrcpNotificationParam& aParam,
+    BluetoothAvrcpResultHandler* aRes);
+
+  nsresult SetVolumeCmd(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
+
+protected:
+  nsresult Send(BluetoothDaemonPDU* aPDU,
+                BluetoothAvrcpResultHandler* aRes);
+
+  void HandleSvc(const BluetoothDaemonPDUHeader& aHeader,
+                 BluetoothDaemonPDU& aPDU, void* aUserData);
+
+  //
+  // Responses
+  //
+
+  typedef BluetoothResultRunnable0<BluetoothAvrcpResultHandler, void>
+    ResultRunnable;
+
+  typedef BluetoothResultRunnable1<BluetoothAvrcpResultHandler, void,
+                                   BluetoothStatus, BluetoothStatus>
+    ErrorRunnable;
+
+  void ErrorRsp(const BluetoothDaemonPDUHeader& aHeader,
+                BluetoothDaemonPDU& aPDU,
+                BluetoothAvrcpResultHandler* aRes);
+
+  void GetPlayStatusRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                           BluetoothDaemonPDU& aPDU,
+                           BluetoothAvrcpResultHandler* aRes);
+
+  void ListPlayerAppAttrRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                               BluetoothDaemonPDU& aPDU,
+                               BluetoothAvrcpResultHandler* aRes);
+
+  void ListPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                                BluetoothDaemonPDU& aPDU,
+                                BluetoothAvrcpResultHandler* aRes);
+
+  void GetPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                               BluetoothDaemonPDU& aPDU,
+                               BluetoothAvrcpResultHandler* aRes);
+
+  void GetPlayerAppAttrTextRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                                  BluetoothDaemonPDU& aPDU,
+                                  BluetoothAvrcpResultHandler* aRes);
+
+  void GetPlayerAppValueTextRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                                   BluetoothDaemonPDU& aPDU,
+                                   BluetoothAvrcpResultHandler* aRes);
+
+  void GetElementAttrRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                            BluetoothDaemonPDU& aPDU,
+                            BluetoothAvrcpResultHandler* aRes);
+
+  void SetPlayerAppValueRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                               BluetoothDaemonPDU& aPDU,
+                               BluetoothAvrcpResultHandler* aRes);
+
+  void RegisterNotificationRspRsp(const BluetoothDaemonPDUHeader& aHeader,
+                                  BluetoothDaemonPDU& aPDU,
+                                  BluetoothAvrcpResultHandler* aRes);
+
+  void SetVolumeRsp(const BluetoothDaemonPDUHeader& aHeader,
+                    BluetoothDaemonPDU& aPDU,
+                    BluetoothAvrcpResultHandler* aRes);
+
+  void HandleRsp(const BluetoothDaemonPDUHeader& aHeader,
+                 BluetoothDaemonPDU& aPDU,
+                 void* aUserData);
+
+  //
+  // Notifications
+  //
+
+  class NotificationHandlerWrapper;
+
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+                                         nsString, unsigned long,
+                                         const nsAString&>
+    RemoteFeatureNotification;
+
+  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+    GetPlayStatusNotification;
+
+  typedef BluetoothNotificationRunnable0<NotificationHandlerWrapper, void>
+    ListPlayerAppAttrNotification;
+
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+                                         BluetoothAvrcpPlayerAttribute>
+    ListPlayerAppValuesNotification;
+
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
+    uint8_t, const BluetoothAvrcpPlayerAttribute*>
+    GetPlayerAppValueNotification;
+
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
+    uint8_t, const BluetoothAvrcpPlayerAttribute*>
+    GetPlayerAppAttrsTextNotification;
+
+  typedef BluetoothNotificationRunnable3<NotificationHandlerWrapper, void,
+                                         uint8_t, uint8_t,
+                                         nsAutoArrayPtr<uint8_t>, uint8_t,
+                                         uint8_t, const uint8_t*>
+    GetPlayerAppValuesTextNotification;
+
+  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+                                         BluetoothAvrcpPlayerSettings,
+                                         const BluetoothAvrcpPlayerSettings&>
+    SetPlayerAppValueNotification;
+
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+    uint8_t, nsAutoArrayPtr<BluetoothAvrcpMediaAttribute>,
+    uint8_t, const BluetoothAvrcpMediaAttribute*>
+    GetElementAttrNotification;
+
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+                                         BluetoothAvrcpEvent, uint32_t>
+    RegisterNotificationNotification;
+
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+                                         uint8_t, uint8_t>
+    VolumeChangeNotification;
+
+  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
+                                         int, int>
+    PassthroughCmdNotification;
+
+  class GetElementAttrInitOp;
+  class GetPlayerAppAttrsTextInitOp;
+  class GetPlayerAppValueInitOp;
+  class GetPlayerAppValuesTextInitOp;
+  class PassthroughCmdInitOp;
+  class RemoteFeatureInitOp;
+
+  void RemoteFeatureNtf(const BluetoothDaemonPDUHeader& aHeader,
+                        BluetoothDaemonPDU& aPDU);
+
+  void GetPlayStatusNtf(const BluetoothDaemonPDUHeader& aHeader,
+                        BluetoothDaemonPDU& aPDU);
+
+  void ListPlayerAppAttrNtf(const BluetoothDaemonPDUHeader& aHeader,
+                            BluetoothDaemonPDU& aPDU);
+
+  void ListPlayerAppValuesNtf(const BluetoothDaemonPDUHeader& aHeader,
+                              BluetoothDaemonPDU& aPDU);
+
+  void GetPlayerAppValueNtf(const BluetoothDaemonPDUHeader& aHeader,
+                            BluetoothDaemonPDU& aPDU);
+
+  void GetPlayerAppAttrsTextNtf(const BluetoothDaemonPDUHeader& aHeader,
+                                BluetoothDaemonPDU& aPDU);
+
+  void GetPlayerAppValuesTextNtf(const BluetoothDaemonPDUHeader& aHeader,
+                                 BluetoothDaemonPDU& aPDU);
+
+  void SetPlayerAppValueNtf(const BluetoothDaemonPDUHeader& aHeader,
+                            BluetoothDaemonPDU& aPDU);
+
+  void GetElementAttrNtf(const BluetoothDaemonPDUHeader& aHeader,
+                         BluetoothDaemonPDU& aPDU);
+
+  void RegisterNotificationNtf(const BluetoothDaemonPDUHeader& aHeader,
+                               BluetoothDaemonPDU& aPDU);
+
+  void VolumeChangeNtf(const BluetoothDaemonPDUHeader& aHeader,
+                       BluetoothDaemonPDU& aPDU);
+
+  void PassthroughCmdNtf(const BluetoothDaemonPDUHeader& aHeader,
+                         BluetoothDaemonPDU& aPDU);
+
+  void HandleNtf(const BluetoothDaemonPDUHeader& aHeader,
+                 BluetoothDaemonPDU& aPDU,
+                 void* aUserData);
+
+  static BluetoothAvrcpNotificationHandler* sNotificationHandler;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -44,16 +44,17 @@ if CONFIG['MOZ_B2G_BT']:
             ]
             DEFINES['MOZ_B2G_BT_BLUEZ'] = True
         elif CONFIG['MOZ_B2G_BT_BLUEDROID']:
             SOURCES += [
                 'bluedroid/BluetoothA2dpHALInterface.cpp',
                 'bluedroid/BluetoothA2dpManager.cpp',
                 'bluedroid/BluetoothAvrcpHALInterface.cpp',
                 'bluedroid/BluetoothDaemonA2dpInterface.cpp',
+                'bluedroid/BluetoothDaemonAvrcpInterface.cpp',
                 'bluedroid/BluetoothDaemonHandsfreeInterface.cpp',
                 'bluedroid/BluetoothDaemonHelpers.cpp',
                 'bluedroid/BluetoothDaemonInterface.cpp',
                 'bluedroid/BluetoothDaemonSetupInterface.cpp',
                 'bluedroid/BluetoothDaemonSocketInterface.cpp',
                 'bluedroid/BluetoothHALHelpers.cpp',
                 'bluedroid/BluetoothHALInterface.cpp',
                 'bluedroid/BluetoothHandsfreeHALInterface.cpp',