Bug 1091575: Add core interfaces and Setup module for Bluetooth daemon (under bluetooth2/), r=btian
authorThomas Zimmermann <tdz@users.sourceforge.net>
Fri, 14 Nov 2014 10:04:33 +0100
changeset 215745 c91863c880df6a7032131012475e30269ab5d5e0
parent 215744 b7d22b4ba3cf8208ef0c9f2c3f99bed65ca6e029
child 215746 e4cfdcae2f80c160c941158e1cb4aac21ba300a3
push id27825
push userryanvm@gmail.com
push dateFri, 14 Nov 2014 22:14:56 +0000
treeherdermozilla-central@99892bdd512d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbtian
bugs1091575
milestone36.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 1091575: Add core interfaces and Setup module for Bluetooth daemon (under bluetooth2/), r=btian This patch adds the core interfaces and the Setup module for the Bluetooth Daemon. The Setup module implements commands for enabling and disabling Bluetooth profiles in the daemon.
dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp
dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h
dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp
dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h
dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.cpp
dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.h
dom/bluetooth2/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.cpp
@@ -0,0 +1,65 @@
+/* -*- 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 "BluetoothDaemonHelpers.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// Conversion
+//
+
+nsresult
+Convert(uint8_t aIn, BluetoothStatus& aOut)
+{
+  static const BluetoothStatus sStatus[] = {
+    CONVERT(0x00, STATUS_SUCCESS),
+    CONVERT(0x01, STATUS_FAIL),
+    CONVERT(0x02, STATUS_NOT_READY),
+    CONVERT(0x03, STATUS_NOMEM),
+    CONVERT(0x04, STATUS_BUSY),
+    CONVERT(0x05, STATUS_DONE),
+    CONVERT(0x06, STATUS_UNSUPPORTED),
+    CONVERT(0x07, STATUS_PARM_INVALID),
+    CONVERT(0x08, STATUS_UNHANDLED),
+    CONVERT(0x09, STATUS_AUTH_FAILURE),
+    CONVERT(0x0a, STATUS_RMT_DEV_DOWN)
+  };
+  if (NS_WARN_IF(aIn >= MOZ_ARRAY_LENGTH(sStatus))) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sStatus[aIn];
+  return NS_OK;
+}
+
+//
+// Packing
+//
+
+nsresult
+PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU)
+{
+  return PackPDU(aIn.mType, aIn.mLength,
+                 PackArray<uint8_t>(aIn.mValue.get(), aIn.mLength), aPDU);
+}
+
+nsresult
+PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU)
+{
+  return PackPDU(aIn.mService, aIn.mOpcode, aIn.mLength, aPDU);
+}
+
+//
+// Unpacking
+//
+
+nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut)
+{
+  return UnpackPDU(aPDU, UnpackConversion<uint8_t, BluetoothStatus>(aOut));
+}
+
+END_BLUETOOTH_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonHelpers.h
@@ -0,0 +1,376 @@
+/* -*- 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_bluedroid_bluetoothdaemonhelpers_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemonhelpers_h__
+
+#include "BluetoothCommon.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/ipc/BluetoothDaemonConnection.h"
+#include "nsThreadUtils.h"
+
+using namespace mozilla::ipc;
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+struct BluetoothConfigurationParameter {
+  uint8_t mType;
+  uint16_t mLength;
+  nsAutoArrayPtr<uint8_t> mValue;
+};
+
+struct BluetoothDaemonPDUHeader {
+  BluetoothDaemonPDUHeader()
+  : mService(0x00)
+  , mOpcode(0x00)
+  , mLength(0x00)
+  { }
+
+  BluetoothDaemonPDUHeader(uint8_t aService, uint8_t aOpcode, uint8_t aLength)
+  : mService(aService)
+  , mOpcode(aOpcode)
+  , mLength(aLength)
+  { }
+
+  uint8_t mService;
+  uint8_t mOpcode;
+  uint16_t mLength;
+};
+
+//
+// Conversion
+//
+// PDUs can only store primitive data types, such as integers or
+// strings. Gecko often uses more complex data types, such as
+// enumerators or structures. Conversion functions convert between
+// primitive data and internal Gecko's data types during a PDU's
+// packing and unpacking.
+//
+
+nsresult
+Convert(uint8_t aIn, BluetoothStatus& aOut);
+
+//
+// Packing
+//
+
+inline nsresult
+PackPDU(uint8_t aIn, BluetoothDaemonPDU& aPDU)
+{
+  return aPDU.Write(aIn);
+}
+
+inline nsresult
+PackPDU(uint16_t aIn, BluetoothDaemonPDU& aPDU)
+{
+  return aPDU.Write(aIn);
+}
+
+nsresult
+PackPDU(const BluetoothConfigurationParameter& aIn, BluetoothDaemonPDU& aPDU);
+
+nsresult
+PackPDU(const BluetoothDaemonPDUHeader& aIn, BluetoothDaemonPDU& aPDU);
+
+/* |PackArray| is a helper for packing arrays. Pass an instance
+ * of this structure as the first argument to |PackPDU| to pack
+ * an array. The array's maximum default length is 255 elements.
+ */
+template <typename T>
+struct PackArray
+{
+  PackArray(const T* aData, size_t aLength)
+  : mData(aData)
+  , mLength(aLength)
+  { }
+
+  const T* mData;
+  size_t mLength;
+};
+
+/* This implementation of |PackPDU| packs the length of an array
+ * and the elements of the array one-by-one.
+ */
+template<typename T>
+inline nsresult
+PackPDU(const PackArray<T>& aIn, BluetoothDaemonPDU& aPDU)
+{
+  for (size_t i = 0; i < aIn.mLength; ++i) {
+    nsresult rv = PackPDU(aIn.mData[i], aPDU);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+  }
+  return NS_OK;
+}
+
+template <typename T1, typename T2>
+inline nsresult
+PackPDU(const T1& aIn1, const T2& aIn2, BluetoothDaemonPDU& aPDU)
+{
+  nsresult rv = PackPDU(aIn1, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  return PackPDU(aIn2, aPDU);
+}
+
+template <typename T1, typename T2, typename T3>
+inline nsresult
+PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3,
+        BluetoothDaemonPDU& aPDU)
+{
+  nsresult rv = PackPDU(aIn1, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = PackPDU(aIn2, aPDU);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  return PackPDU(aIn3, aPDU);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+inline nsresult
+PackPDU(const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4,
+        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;
+  }
+  return PackPDU(aIn4, aPDU);
+}
+
+//
+// Unpacking
+//
+
+inline nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, uint8_t& aOut)
+{
+  return aPDU.Read(aOut);
+}
+
+inline nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, uint16_t& aOut)
+{
+  return aPDU.Read(aOut);
+}
+
+inline nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothDaemonPDUHeader& aOut)
+{
+  nsresult rv = UnpackPDU(aPDU, aOut.mService);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  rv = UnpackPDU(aPDU, aOut.mOpcode);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  return UnpackPDU(aPDU, aOut.mLength);
+}
+
+nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, BluetoothStatus& aOut);
+
+/* |UnpackConversion| is a helper for convering unpacked values. Pass
+ * an instance of this structure to |UnpackPDU| to read a value from
+ * the PDU in the input type and convert it to the output type.
+ */
+template<typename Tin, typename Tout>
+struct UnpackConversion {
+  UnpackConversion(Tout& aOut)
+  : mOut(aOut)
+  { }
+
+  Tout& mOut;
+};
+
+template<typename Tin, typename Tout>
+inline nsresult
+UnpackPDU(BluetoothDaemonPDU& aPDU, const UnpackConversion<Tin, Tout>& aOut)
+{
+  Tin in;
+  nsresult rv = UnpackPDU(aPDU, in);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+  return Convert(in, aOut.mOut);
+}
+
+//
+// Init operators
+//
+
+// |PDUInitOP| provides functionality for init operators that unpack PDUs.
+class PDUInitOp
+{
+protected:
+  PDUInitOp(BluetoothDaemonPDU& aPDU)
+  : mPDU(&aPDU)
+  { }
+
+  BluetoothDaemonPDU& GetPDU() const
+  {
+    return *mPDU; // cannot be nullptr
+  }
+
+  void WarnAboutTrailingData() const
+  {
+    size_t size = mPDU->GetSize();
+
+    if (MOZ_LIKELY(!size)) {
+      return;
+    }
+
+    uint8_t service, opcode;
+    uint16_t payloadSize;
+    mPDU->GetHeader(service, opcode, payloadSize);
+
+    BT_LOGR("Unpacked PDU of type (%x,%x) still contains %zu Bytes of data.",
+            service, opcode, size);
+  }
+
+private:
+  BluetoothDaemonPDU* mPDU; // Hold pointer to allow for constant instances
+};
+
+// |UnpackPDUInitOp| is a general-purpose init operator for all variants
+// of |BluetoothResultRunnable| and |BluetoothNotificationRunnable|. The
+// call operators of |UnpackPDUInitOp| unpack a PDU into the supplied
+// arguments.
+class UnpackPDUInitOp MOZ_FINAL : private PDUInitOp
+{
+public:
+  UnpackPDUInitOp(BluetoothDaemonPDU& aPDU)
+  : PDUInitOp(aPDU)
+  { }
+
+  nsresult operator () () const
+  {
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+
+  template<typename T1>
+  nsresult operator () (T1& aArg1) const
+  {
+    nsresult rv = UnpackPDU(GetPDU(), aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+
+  template<typename T1, typename T2>
+  nsresult operator () (T1& aArg1, T2& aArg2) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+
+  template<typename T1, typename T2, typename T3>
+  nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+
+  template<typename T1, typename T2, typename T3, typename T4>
+  nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg4);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+
+  template<typename T1, typename T2, typename T3, typename T4, typename T5>
+  nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3, T4& aArg4,
+                        T5& aArg5) const
+  {
+    BluetoothDaemonPDU& pdu = GetPDU();
+
+    nsresult rv = UnpackPDU(pdu, aArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg4);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = UnpackPDU(pdu, aArg5);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    WarnAboutTrailingData();
+    return NS_OK;
+  }
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.cpp
@@ -0,0 +1,813 @@
+/* -*- 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 "BluetoothDaemonInterface.h"
+#include "BluetoothDaemonHelpers.h"
+#include "BluetoothDaemonSetupInterface.h"
+#include "BluetoothInterfaceHelpers.h"
+#include "mozilla/unused.h"
+
+using namespace mozilla::ipc;
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// Protocol initialization and setup
+//
+
+class BluetoothDaemonSetupModule
+{
+public:
+  enum {
+    SERVICE_ID = 0x00
+  };
+
+  enum {
+    OPCODE_ERROR = 0x00,
+    OPCODE_REGISTER_MODULE = 0x01,
+    OPCODE_UNREGISTER_MODULE = 0x02,
+    OPCODE_CONFIGURATION = 0x03
+  };
+
+  virtual nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) = 0;
+
+  // Commands
+  //
+
+  nsresult RegisterModuleCmd(uint8_t aId, uint8_t aMode,
+                             BluetoothSetupResultHandler* aRes)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsAutoPtr<BluetoothDaemonPDU> pdu(
+      new BluetoothDaemonPDU(SERVICE_ID, OPCODE_REGISTER_MODULE, 0));
+
+    nsresult rv = PackPDU(aId, aMode, *pdu);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = Send(pdu, aRes);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    unused << pdu.forget();
+    return rv;
+  }
+
+  nsresult UnregisterModuleCmd(uint8_t aId,
+                               BluetoothSetupResultHandler* aRes)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsAutoPtr<BluetoothDaemonPDU> pdu(
+      new BluetoothDaemonPDU(SERVICE_ID, OPCODE_UNREGISTER_MODULE, 0));
+
+    nsresult rv = PackPDU(aId, *pdu);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = Send(pdu, aRes);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    unused << pdu.forget();
+    return rv;
+  }
+
+  nsresult ConfigurationCmd(const BluetoothConfigurationParameter* aParam,
+                            uint8_t aLen, BluetoothSetupResultHandler* aRes)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsAutoPtr<BluetoothDaemonPDU> pdu(
+      new BluetoothDaemonPDU(SERVICE_ID, OPCODE_CONFIGURATION, 0));
+
+    nsresult rv = PackPDU(
+      aLen, PackArray<BluetoothConfigurationParameter>(aParam, aLen), *pdu);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    rv = Send(pdu, aRes);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    unused << pdu.forget();
+    return rv;
+  }
+
+protected:
+
+  // Called to handle PDUs with Service field equal to 0x00, which
+  // contains internal operations for setup and configuration.
+  void HandleSvc(const BluetoothDaemonPDUHeader& aHeader,
+                 BluetoothDaemonPDU& aPDU, void* aUserData)
+  {
+    static void (BluetoothDaemonSetupModule::* const HandleRsp[])(
+      const BluetoothDaemonPDUHeader&,
+      BluetoothDaemonPDU&,
+      BluetoothSetupResultHandler*) = {
+      INIT_ARRAY_AT(OPCODE_ERROR,
+        &BluetoothDaemonSetupModule::ErrorRsp),
+      INIT_ARRAY_AT(OPCODE_REGISTER_MODULE,
+        &BluetoothDaemonSetupModule::RegisterModuleRsp),
+      INIT_ARRAY_AT(OPCODE_UNREGISTER_MODULE,
+        &BluetoothDaemonSetupModule::UnregisterModuleRsp),
+      INIT_ARRAY_AT(OPCODE_CONFIGURATION,
+        &BluetoothDaemonSetupModule::ConfigurationRsp)
+    };
+
+    if (NS_WARN_IF(aHeader.mOpcode >= MOZ_ARRAY_LENGTH(HandleRsp)) ||
+        NS_WARN_IF(!HandleRsp[aHeader.mOpcode])) {
+      return;
+    }
+
+    nsRefPtr<BluetoothSetupResultHandler> res =
+      already_AddRefed<BluetoothSetupResultHandler>(
+        static_cast<BluetoothSetupResultHandler*>(aUserData));
+
+    if (!res) {
+      return; // Return early if no result handler has been set
+    }
+
+    (this->*(HandleRsp[aHeader.mOpcode]))(aHeader, aPDU, res);
+  }
+
+  nsresult Send(BluetoothDaemonPDU* aPDU, BluetoothSetupResultHandler* aRes)
+  {
+    aRes->AddRef(); // Keep reference for response
+    return Send(aPDU, static_cast<void*>(aRes));
+  }
+
+private:
+
+  // Responses
+  //
+
+  typedef
+    BluetoothResultRunnable0<BluetoothSetupResultHandler, void>
+    ResultRunnable;
+
+  typedef
+    BluetoothResultRunnable1<BluetoothSetupResultHandler, void,
+                             BluetoothStatus, BluetoothStatus>
+    ErrorRunnable;
+
+  void
+  ErrorRsp(const BluetoothDaemonPDUHeader& aHeader,
+           BluetoothDaemonPDU& aPDU,
+           BluetoothSetupResultHandler* aRes)
+  {
+    ErrorRunnable::Dispatch(
+      aRes, &BluetoothSetupResultHandler::OnError, UnpackPDUInitOp(aPDU));
+  }
+
+  void
+  RegisterModuleRsp(const BluetoothDaemonPDUHeader& aHeader,
+                    BluetoothDaemonPDU& aPDU,
+                    BluetoothSetupResultHandler* aRes)
+  {
+    ResultRunnable::Dispatch(
+      aRes, &BluetoothSetupResultHandler::RegisterModule,
+      UnpackPDUInitOp(aPDU));
+  }
+
+  void
+  UnregisterModuleRsp(const BluetoothDaemonPDUHeader& aHeader,
+                      BluetoothDaemonPDU& aPDU,
+                      BluetoothSetupResultHandler* aRes)
+  {
+    ResultRunnable::Dispatch(
+      aRes, &BluetoothSetupResultHandler::UnregisterModule,
+      UnpackPDUInitOp(aPDU));
+  }
+
+  void
+  ConfigurationRsp(const BluetoothDaemonPDUHeader& aHeader,
+                   BluetoothDaemonPDU& aPDU,
+                   BluetoothSetupResultHandler* aRes)
+  {
+    ResultRunnable::Dispatch(
+      aRes, &BluetoothSetupResultHandler::Configuration,
+      UnpackPDUInitOp(aPDU));
+  }
+};
+
+//
+// Core module
+//
+
+static BluetoothNotificationHandler* sNotificationHandler;
+
+//
+// Protocol handling
+//
+
+class BluetoothDaemonProtocol MOZ_FINAL
+  : public BluetoothDaemonPDUConsumer
+  , public BluetoothDaemonSetupModule
+{
+public:
+  BluetoothDaemonProtocol(BluetoothDaemonConnection* aConnection);
+
+  // Outgoing PDUs
+  //
+
+  nsresult Send(BluetoothDaemonPDU* aPDU, void* aUserData) MOZ_OVERRIDE;
+
+  void StoreUserData(const BluetoothDaemonPDU& aPDU) MOZ_OVERRIDE;
+
+  // Incoming PUDs
+  //
+
+  void Handle(BluetoothDaemonPDU& aPDU) MOZ_OVERRIDE;
+
+  void* FetchUserData(const BluetoothDaemonPDUHeader& aHeader);
+
+private:
+  void HandleSetupSvc(const BluetoothDaemonPDUHeader& aHeader,
+                      BluetoothDaemonPDU& aPDU, void* aUserData);
+
+  BluetoothDaemonConnection* mConnection;
+  nsTArray<void*> mUserDataQ;
+};
+
+BluetoothDaemonProtocol::BluetoothDaemonProtocol(
+  BluetoothDaemonConnection* aConnection)
+  : mConnection(aConnection)
+{
+  MOZ_ASSERT(mConnection);
+}
+
+nsresult
+BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData)
+{
+  MOZ_ASSERT(aPDU);
+
+  aPDU->SetUserData(aUserData);
+  aPDU->UpdateHeader();
+  return mConnection->Send(aPDU); // Forward PDU to command channel
+}
+
+void
+BluetoothDaemonProtocol::HandleSetupSvc(
+  const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
+  void* aUserData)
+{
+  BluetoothDaemonSetupModule::HandleSvc(aHeader, aPDU, aUserData);
+}
+
+void
+BluetoothDaemonProtocol::Handle(BluetoothDaemonPDU& aPDU)
+{
+  static void (BluetoothDaemonProtocol::* const HandleSvc[])(
+    const BluetoothDaemonPDUHeader&, BluetoothDaemonPDU&, void*) = {
+    [0] = &BluetoothDaemonProtocol::HandleSetupSvc
+  };
+
+  BluetoothDaemonPDUHeader header;
+
+  if (NS_FAILED(UnpackPDU(aPDU, header)) ||
+      NS_WARN_IF(!(header.mService < MOZ_ARRAY_LENGTH(HandleSvc))) ||
+      NS_WARN_IF(!(HandleSvc[header.mService]))) {
+    return;
+  }
+
+  (this->*(HandleSvc[header.mService]))(header, aPDU, FetchUserData(header));
+}
+
+void
+BluetoothDaemonProtocol::StoreUserData(const BluetoothDaemonPDU& aPDU)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  mUserDataQ.AppendElement(aPDU.GetUserData());
+}
+
+void*
+BluetoothDaemonProtocol::FetchUserData(const BluetoothDaemonPDUHeader& aHeader)
+{
+  MOZ_ASSERT(!NS_IsMainThread());
+
+  if (aHeader.mOpcode & 0x80) {
+    return nullptr; // Ignore notifications
+  }
+
+  void* userData = mUserDataQ.ElementAt(0);
+  mUserDataQ.RemoveElementAt(0);
+
+  return userData;
+}
+
+//
+// Channels
+//
+
+class BluetoothDaemonChannel MOZ_FINAL : public BluetoothDaemonConnection
+{
+public:
+  BluetoothDaemonChannel(BluetoothDaemonInterface::Channel aChannel);
+
+  nsresult ConnectSocket(BluetoothDaemonInterface* aInterface,
+                         BluetoothDaemonPDUConsumer* aConsumer);
+
+  // Connection state
+  //
+
+  void OnConnectSuccess() MOZ_OVERRIDE;
+  void OnConnectError() MOZ_OVERRIDE;
+  void OnDisconnect() MOZ_OVERRIDE;
+
+private:
+  BluetoothDaemonInterface* mInterface;
+  BluetoothDaemonInterface::Channel mChannel;
+};
+
+BluetoothDaemonChannel::BluetoothDaemonChannel(
+  BluetoothDaemonInterface::Channel aChannel)
+: mInterface(nullptr)
+, mChannel(aChannel)
+{ }
+
+nsresult
+BluetoothDaemonChannel::ConnectSocket(BluetoothDaemonInterface* aInterface,
+                                      BluetoothDaemonPDUConsumer* aConsumer)
+{
+  MOZ_ASSERT(aInterface);
+
+  mInterface = aInterface;
+
+  return BluetoothDaemonConnection::ConnectSocket(aConsumer);
+}
+
+void
+BluetoothDaemonChannel::OnConnectSuccess()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mInterface);
+
+  mInterface->OnConnectSuccess(mChannel);
+}
+
+void
+BluetoothDaemonChannel::OnConnectError()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mInterface);
+
+  mInterface->OnConnectError(mChannel);
+  mInterface = nullptr;
+}
+
+void
+BluetoothDaemonChannel::OnDisconnect()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(mInterface);
+
+  mInterface->OnDisconnect(mChannel);
+  mInterface = nullptr;
+}
+
+//
+// Interface
+//
+
+/* returns the container structure of a variable; _t is the container's
+ * type, _v the name of the variable, and _m is _v's field within _t
+ */
+#define container(_t, _v, _m) \
+  ( (_t*)( ((const unsigned char*)(_v)) - offsetof(_t, _m) ) )
+
+BluetoothDaemonInterface*
+BluetoothDaemonInterface::GetInstance()
+{
+  static BluetoothDaemonInterface* sBluetoothInterface;
+
+  if (sBluetoothInterface) {
+    return sBluetoothInterface;
+  }
+
+  // Only create channel objects here. The connection will be
+  // established by |BluetoothDaemonInterface::Init|.
+
+  BluetoothDaemonChannel* cmdChannel =
+    new BluetoothDaemonChannel(BluetoothDaemonInterface::CMD_CHANNEL);
+
+  BluetoothDaemonChannel* ntfChannel =
+    new BluetoothDaemonChannel(BluetoothDaemonInterface::NTF_CHANNEL);
+
+  // Create a new interface object with the channels and a
+  // protocol handler.
+
+  sBluetoothInterface =
+    new BluetoothDaemonInterface(cmdChannel,
+                                 ntfChannel,
+                                 new BluetoothDaemonProtocol(cmdChannel));
+
+  return sBluetoothInterface;
+}
+
+BluetoothDaemonInterface::BluetoothDaemonInterface(
+  BluetoothDaemonChannel* aCmdChannel,
+  BluetoothDaemonChannel* aNtfChannel,
+  BluetoothDaemonProtocol* aProtocol)
+: mCmdChannel(aCmdChannel)
+, mNtfChannel(aNtfChannel)
+, mProtocol(aProtocol)
+{
+  MOZ_ASSERT(mCmdChannel);
+  MOZ_ASSERT(mNtfChannel);
+  MOZ_ASSERT(mProtocol);
+}
+
+BluetoothDaemonInterface::~BluetoothDaemonInterface()
+{ }
+
+class BluetoothDaemonInterface::InitResultHandler MOZ_FINAL
+  : public BluetoothSetupResultHandler
+{
+public:
+  InitResultHandler(BluetoothDaemonInterface* aInterface,
+                    BluetoothResultHandler* aRes)
+    : mInterface(aInterface)
+    , mRes(aRes)
+    , mRegisteredSocketModule(false)
+  {
+    MOZ_ASSERT(mInterface);
+  }
+
+  // We need to call methods from the |BluetoothResultHandler|. Since
+  // we're already on the main thread and returned from Init, we don't
+  // need to dispatch a new runnable.
+
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    // TODO: close channels
+
+    if (mRes) {
+      mRes->OnError(aStatus);
+    }
+  }
+
+  void RegisterModule() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mInterface->mProtocol);
+
+    if (!mRegisteredSocketModule) {
+      mRegisteredSocketModule = true;
+      // Init, step 4: Register Socket module
+      mInterface->mProtocol->RegisterModuleCmd(0x02, 0x00, this);
+    } else if (mRes) {
+      // Init, step 5: Signal success to caller
+      mRes->Init();
+    }
+  }
+
+private:
+  BluetoothDaemonInterface* mInterface;
+  nsRefPtr<BluetoothResultHandler> mRes;
+  bool mRegisteredSocketModule;
+};
+
+void
+BluetoothDaemonInterface::OnConnectSuccess(enum Channel aChannel)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
+
+  switch (aChannel) {
+    case CMD_CHANNEL:
+      // Init, step 2: Connect notification channel...
+      if (mNtfChannel->GetConnectionStatus() != SOCKET_CONNECTED) {
+        nsresult rv = mNtfChannel->ConnectSocket(this, mProtocol);
+        if (NS_FAILED(rv)) {
+          OnConnectError(NTF_CHANNEL);
+        }
+      } else {
+        // ...or go to step 3 if channel is already connected.
+        OnConnectSuccess(NTF_CHANNEL);
+      }
+      break;
+
+    case NTF_CHANNEL: {
+        nsRefPtr<BluetoothResultHandler> res = mResultHandlerQ.ElementAt(0);
+        mResultHandlerQ.RemoveElementAt(0);
+
+        // Init, step 3: Register Core module
+        nsresult rv = mProtocol->RegisterModuleCmd(
+          0x01, 0x00, new InitResultHandler(this, res));
+        if (NS_FAILED(rv) && res) {
+          DispatchError(res, STATUS_FAIL);
+        }
+      }
+      break;
+  }
+}
+
+void
+BluetoothDaemonInterface::OnConnectError(enum Channel aChannel)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
+
+  switch (aChannel) {
+    case NTF_CHANNEL:
+      // Close command channel
+      mCmdChannel->CloseSocket();
+      /* fall through for cleanup and error signalling */
+    case CMD_CHANNEL: {
+        // Signal error to caller
+        nsRefPtr<BluetoothResultHandler> res = mResultHandlerQ.ElementAt(0);
+        mResultHandlerQ.RemoveElementAt(0);
+
+        if (res) {
+          DispatchError(res, STATUS_FAIL);
+        }
+      }
+      break;
+  }
+}
+
+void
+BluetoothDaemonInterface::OnDisconnect(enum Channel aChannel)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(!mResultHandlerQ.IsEmpty());
+
+  switch (aChannel) {
+    case NTF_CHANNEL:
+      // Cleanup, step 4: Close command channel
+      mCmdChannel->CloseSocket();
+      break;
+    case CMD_CHANNEL: {
+        nsRefPtr<BluetoothResultHandler> res = mResultHandlerQ.ElementAt(0);
+        mResultHandlerQ.RemoveElementAt(0);
+
+        // Cleanup, step 5: Signal success to caller
+        if (res) {
+          res->Cleanup();
+        }
+      }
+      break;
+  }
+}
+
+void
+BluetoothDaemonInterface::Init(
+  BluetoothNotificationHandler* aNotificationHandler,
+  BluetoothResultHandler* aRes)
+{
+  sNotificationHandler = aNotificationHandler;
+
+  mResultHandlerQ.AppendElement(aRes);
+
+  // Init, step 1: Connect command channel...
+  if (mCmdChannel->GetConnectionStatus() != SOCKET_CONNECTED) {
+    nsresult rv = mCmdChannel->ConnectSocket(this, mProtocol);
+    if (NS_FAILED(rv)) {
+      OnConnectError(CMD_CHANNEL);
+    }
+  } else {
+    // ...or go to step 2 if channel is already connected.
+    OnConnectSuccess(CMD_CHANNEL);
+  }
+}
+
+class BluetoothDaemonInterface::CleanupResultHandler MOZ_FINAL
+  : public BluetoothSetupResultHandler
+{
+public:
+  CleanupResultHandler(BluetoothDaemonInterface* aInterface)
+    : mInterface(aInterface)
+    , mUnregisteredCoreModule(false)
+  {
+    MOZ_ASSERT(mInterface);
+  }
+
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
+  {
+    Proceed();
+  }
+
+  void UnregisterModule() MOZ_OVERRIDE
+  {
+    Proceed();
+  }
+
+private:
+  void Proceed()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(mInterface->mProtocol);
+
+    if (!mUnregisteredCoreModule) {
+      mUnregisteredCoreModule = true;
+      // Cleanup, step 2: Unregister Core module
+      mInterface->mProtocol->UnregisterModuleCmd(0x01, this);
+    } else {
+      // Cleanup, step 3: Close notification channel
+      mInterface->mNtfChannel->CloseSocket();
+    }
+  }
+
+  BluetoothDaemonInterface* mInterface;
+  bool mUnregisteredCoreModule;
+};
+
+void
+BluetoothDaemonInterface::Cleanup(BluetoothResultHandler* aRes)
+{
+  sNotificationHandler = nullptr;
+
+  mResultHandlerQ.AppendElement(aRes);
+
+  // Cleanup, step 1: Unregister Socket module
+  mProtocol->UnregisterModuleCmd(0x02, new CleanupResultHandler(this));
+}
+
+void
+BluetoothDaemonInterface::Enable(BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::Disable(BluetoothResultHandler* aRes)
+{
+}
+
+/* Adapter Properties */
+
+void
+BluetoothDaemonInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::GetAdapterProperty(const nsAString& aName,
+                                             BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::SetAdapterProperty(
+  const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes)
+{
+}
+
+/* Remote Device Properties */
+
+void
+BluetoothDaemonInterface::GetRemoteDeviceProperties(
+  const nsAString& aRemoteAddr, BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::GetRemoteDeviceProperty(
+  const nsAString& aRemoteAddr, const nsAString& aName,
+  BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::SetRemoteDeviceProperty(
+  const nsAString& aRemoteAddr, const BluetoothNamedValue& aProperty,
+  BluetoothResultHandler* aRes)
+{
+}
+
+/* Remote Services */
+
+void
+BluetoothDaemonInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr,
+                                                 const uint8_t aUuid[16],
+                                                 BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::GetRemoteServices(const nsAString& aRemoteAddr,
+                                            BluetoothResultHandler* aRes)
+{
+}
+
+/* Discovery */
+
+void
+BluetoothDaemonInterface::StartDiscovery(BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::CancelDiscovery(BluetoothResultHandler* aRes)
+{
+}
+
+/* Bonds */
+
+void
+BluetoothDaemonInterface::CreateBond(const nsAString& aBdAddr,
+                                     BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::RemoveBond(const nsAString& aBdAddr,
+                                     BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::CancelBond(const nsAString& aBdAddr,
+                                     BluetoothResultHandler* aRes)
+{
+}
+
+/* Authentication */
+
+void
+BluetoothDaemonInterface::PinReply(const nsAString& aBdAddr, bool aAccept,
+                                   const nsAString& aPinCode,
+                                   BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::SspReply(const nsAString& aBdAddr,
+                                   const nsAString& aVariant,
+                                   bool aAccept, uint32_t aPasskey,
+                                   BluetoothResultHandler* aRes)
+{
+}
+
+/* DUT Mode */
+
+void
+BluetoothDaemonInterface::DutModeConfigure(bool aEnable,
+                                           BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf,
+                                      uint8_t aLen,
+                                      BluetoothResultHandler* aRes)
+{
+}
+
+/* LE Mode */
+
+void
+BluetoothDaemonInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf,
+                                     uint8_t aLen,
+                                     BluetoothResultHandler* aRes)
+{
+}
+
+void
+BluetoothDaemonInterface::DispatchError(BluetoothResultHandler* aRes,
+                                        BluetoothStatus aStatus)
+{
+  BluetoothResultRunnable1<
+    BluetoothResultHandler, void, BluetoothStatus, BluetoothStatus>::Dispatch(
+    aRes, &BluetoothResultHandler::OnError,
+    ConstantInitOp1<BluetoothStatus>(aStatus));
+}
+
+BluetoothSocketInterface*
+BluetoothDaemonInterface::GetBluetoothSocketInterface()
+{
+  return nullptr;
+}
+
+BluetoothHandsfreeInterface*
+BluetoothDaemonInterface::GetBluetoothHandsfreeInterface()
+{
+  return nullptr;
+}
+
+BluetoothA2dpInterface*
+BluetoothDaemonInterface::GetBluetoothA2dpInterface()
+{
+  return nullptr;
+}
+
+BluetoothAvrcpInterface*
+BluetoothDaemonInterface::GetBluetoothAvrcpInterface()
+{
+  return nullptr;
+}
+
+BluetoothGattInterface*
+BluetoothDaemonInterface::GetBluetoothGattInterface()
+{
+  return nullptr;
+}
+
+END_BLUETOOTH_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonInterface.h
@@ -0,0 +1,130 @@
+/* -*- 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_bluedroid_bluetoothdaemoninterface_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemoninterface_h__
+
+#include "BluetoothInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothDaemonChannel;
+class BluetoothDaemonProtocol;
+
+class BluetoothDaemonInterface MOZ_FINAL : public BluetoothInterface
+{
+public:
+  class CleanupResultHandler;
+  class InitResultHandler;
+
+  friend class BluetoothDaemonChannel;
+  friend class CleanupResultHandler;
+  friend class InitResultHandler;
+
+  static BluetoothDaemonInterface* GetInstance();
+
+  void Init(BluetoothNotificationHandler* aNotificationHandler,
+            BluetoothResultHandler* aRes);
+  void Cleanup(BluetoothResultHandler* aRes);
+
+  void Enable(BluetoothResultHandler* aRes);
+  void Disable(BluetoothResultHandler* aRes);
+
+  /* Adapter Properties */
+
+  void GetAdapterProperties(BluetoothResultHandler* aRes);
+  void GetAdapterProperty(const nsAString& aName,
+                          BluetoothResultHandler* aRes);
+  void SetAdapterProperty(const BluetoothNamedValue& aProperty,
+                          BluetoothResultHandler* aRes);
+
+  /* Remote Device Properties */
+
+  void GetRemoteDeviceProperties(const nsAString& aRemoteAddr,
+                                 BluetoothResultHandler* aRes);
+  void GetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+                               const nsAString& aName,
+                               BluetoothResultHandler* aRes);
+  void SetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+                               const BluetoothNamedValue& aProperty,
+                               BluetoothResultHandler* aRes);
+
+  /* Remote Services */
+
+  void GetRemoteServiceRecord(const nsAString& aRemoteAddr,
+                              const uint8_t aUuid[16],
+                              BluetoothResultHandler* aRes);
+  void GetRemoteServices(const nsAString& aRemoteAddr,
+                         BluetoothResultHandler* aRes);
+
+  /* Discovery */
+
+  void StartDiscovery(BluetoothResultHandler* aRes);
+  void CancelDiscovery(BluetoothResultHandler* aRes);
+
+  /* Bonds */
+
+  void CreateBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
+  void RemoveBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
+  void CancelBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
+
+  /* Authentication */
+
+  void PinReply(const nsAString& aBdAddr, bool aAccept,
+                const nsAString& aPinCode,
+                BluetoothResultHandler* aRes);
+
+  void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
+                bool aAccept, uint32_t aPasskey,
+                BluetoothResultHandler* aRes);
+
+  /* DUT Mode */
+
+  void DutModeConfigure(bool aEnable, BluetoothResultHandler* aRes);
+  void DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+                   BluetoothResultHandler* aRes);
+
+  /* LE Mode */
+
+  void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+                  BluetoothResultHandler* aRes);
+
+  /* Profile Interfaces */
+
+  BluetoothSocketInterface* GetBluetoothSocketInterface() MOZ_OVERRIDE;
+  BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface() MOZ_OVERRIDE;
+  BluetoothA2dpInterface* GetBluetoothA2dpInterface() MOZ_OVERRIDE;
+  BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() MOZ_OVERRIDE;
+  BluetoothGattInterface* GetBluetoothGattInterface() MOZ_OVERRIDE;
+
+protected:
+  enum Channel {
+    CMD_CHANNEL,
+    NTF_CHANNEL
+  };
+
+  BluetoothDaemonInterface(BluetoothDaemonChannel* aCmdChannel,
+                           BluetoothDaemonChannel* aNtfChannel,
+                           BluetoothDaemonProtocol* aProtocol);
+  ~BluetoothDaemonInterface();
+
+  void OnConnectSuccess(enum Channel aChannel);
+  void OnConnectError(enum Channel aChannel);
+  void OnDisconnect(enum Channel aChannel);
+
+private:
+  void DispatchError(BluetoothResultHandler* aRes, BluetoothStatus aStatus);
+
+  nsAutoPtr<BluetoothDaemonChannel> mCmdChannel;
+  nsAutoPtr<BluetoothDaemonChannel> mNtfChannel;
+  nsAutoPtr<BluetoothDaemonProtocol> mProtocol;
+
+  nsTArray<nsRefPtr<BluetoothResultHandler> > mResultHandlerQ;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.cpp
@@ -0,0 +1,32 @@
+/* -*- 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 "BluetoothDaemonSetupInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+BluetoothSetupResultHandler::~BluetoothSetupResultHandler()
+{ }
+
+void
+BluetoothSetupResultHandler::OnError(BluetoothStatus aStatus)
+{
+  BT_WARNING("Received error code %d", (int)aStatus);
+}
+
+void
+BluetoothSetupResultHandler::RegisterModule()
+{ }
+
+void
+BluetoothSetupResultHandler::UnregisterModule()
+{ }
+
+void
+BluetoothSetupResultHandler::Configuration()
+{ }
+
+END_BLUETOOTH_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothDaemonSetupInterface.h
@@ -0,0 +1,29 @@
+/* -*- 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_bluedroid_bluetoothdaemonsetupinterface_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothdaemonsetupinterface_h__
+
+#include "BluetoothCommon.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothSetupResultHandler
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothSetupResultHandler)
+
+  virtual ~BluetoothSetupResultHandler();
+
+  virtual void OnError(BluetoothStatus aStatus);
+  virtual void RegisterModule();
+  virtual void UnregisterModule();
+  virtual void Configuration();
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
--- a/dom/bluetooth2/moz.build
+++ b/dom/bluetooth2/moz.build
@@ -46,16 +46,19 @@ if CONFIG['MOZ_B2G_BT']:
                 'bluez',
             ]
             DEFINES['MOZ_B2G_BT_BLUEZ'] = True
         elif CONFIG['MOZ_B2G_BT_BLUEDROID']:
             SOURCES += [
                 'bluedroid/BluetoothA2dpHALInterface.cpp',
                 'bluedroid/BluetoothA2dpManager.cpp',
                 'bluedroid/BluetoothAvrcpHALInterface.cpp',
+                'bluedroid/BluetoothDaemonHelpers.cpp',
+                'bluedroid/BluetoothDaemonInterface.cpp',
+                'bluedroid/BluetoothDaemonSetupInterface.cpp',
                 'bluedroid/BluetoothGattHALInterface.cpp',
                 'bluedroid/BluetoothGattManager.cpp',
                 'bluedroid/BluetoothHALHelpers.cpp',
                 'bluedroid/BluetoothHALInterface.cpp',
                 'bluedroid/BluetoothHandsfreeHALInterface.cpp',
                 'bluedroid/BluetoothOppManager.cpp',
                 'bluedroid/BluetoothServiceBluedroid.cpp',
                 'bluedroid/BluetoothSocket.cpp',