Backed out changeset 868ace3fafba (bug 1153796)
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 15 Apr 2015 11:32:10 +0200
changeset 258171 f1cc9e12a4154a758366d211ef1d0fd57588983f
parent 258170 634d1577c6247c96fd454d3a6fcfa4224a05b5ba
child 258172 d0ee6524d4ce2512611650caa9a185db17a0fcf6
push id8007
push userraliiev@mozilla.com
push dateMon, 11 May 2015 19:23:16 +0000
treeherdermozilla-aurora@e2ce1aac996e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1153796
milestone40.0a1
backs out868ace3fafba41a961b95585c6bcc6206ba6996d
Backed out changeset 868ace3fafba (bug 1153796)
dom/bluetooth/BluetoothInterfaceHelpers.cpp
dom/bluetooth/BluetoothInterfaceHelpers.h
dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp
dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h
dom/bluetooth/bluetooth1/BluetoothInterfaceHelpers.cpp
dom/bluetooth/bluetooth1/BluetoothInterfaceHelpers.h
dom/bluetooth/bluetooth2/BluetoothInterfaceHelpers.h
dom/bluetooth/moz.build
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.cpp
@@ -992,16 +992,33 @@ Convert(const ConvertArray<Tin>& aIn, To
     nsresult rv = Convert(aIn.mData[i], aOut[i]);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
   return NS_OK;
 }
 
+#ifdef MOZ_B2G_BT_API_V2
+nsresult
+Convert(nsresult aIn, BluetoothStatus& aOut)
+{
+  if (NS_SUCCEEDED(aIn)) {
+    aOut = STATUS_SUCCESS;
+  } else if (aIn == NS_ERROR_OUT_OF_MEMORY) {
+    aOut = STATUS_NOMEM;
+  } else {
+    aOut = STATUS_FAIL;
+  }
+  return NS_OK;
+}
+#else
+// Missing in bluetooth1
+#endif
+
 //
 // Packing
 //
 
 nsresult
 PackPDU(bool aIn, BluetoothDaemonPDU& aPDU)
 {
   return PackPDU(PackConversion<bool, uint8_t>(aIn), aPDU);
--- a/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonHelpers.h
@@ -325,16 +325,23 @@ nsresult
 Convert(BluetoothSocketType aIn, uint8_t& aOut);
 
 nsresult
 Convert(BluetoothSspVariant aIn, uint8_t& aOut);
 
 nsresult
 Convert(ControlPlayStatus aIn, uint8_t& aOut);
 
+#ifdef MOZ_B2G_BT_API_V2
+nsresult
+Convert(nsresult aIn, BluetoothStatus& aOut);
+#else
+// Missing in bluetooth1
+#endif
+
 //
 // Packing
 //
 
 // introduce link errors on non-handled data types
 template <typename T>
 nsresult
 PackPDU(T aIn, BluetoothDaemonPDU& aPDU);
rename from dom/bluetooth/BluetoothInterfaceHelpers.cpp
rename to dom/bluetooth/bluetooth1/BluetoothInterfaceHelpers.cpp
rename from dom/bluetooth/BluetoothInterfaceHelpers.h
rename to dom/bluetooth/bluetooth1/BluetoothInterfaceHelpers.h
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth/bluetooth2/BluetoothInterfaceHelpers.h
@@ -0,0 +1,759 @@
+/* -*- 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_bluetoothinterfacehelpers_h
+#define mozilla_dom_bluetooth_bluetoothinterfacehelpers_h
+
+#include "BluetoothCommon.h"
+#include "nsThreadUtils.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// Result handling
+//
+// The classes of type |BluetoothResultRunnable[0..3]| transfer
+// a result handler from the I/O thread to the main thread for
+// execution. Call the methods |Create| and |Dispatch| to create or
+// create-and-dispatch a result runnable.
+//
+// You need to specify the called method. The |Create| and |Dispatch|
+// methods of |BluetoothResultRunnable[1..3]| receive an extra argument
+// for initializing the result's arguments. During creation, the result
+// runnable calls the supplied class's call operator with the result's
+// argument. This is where initialization and conversion from backend-
+// specific types is performed.
+//
+
+template <typename Obj, typename Res>
+class BluetoothResultRunnable0 : public nsRunnable
+{
+public:
+  typedef BluetoothResultRunnable0<Obj, Res> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aObj, aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Obj* aObj, Res (Obj::*aMethod)(), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
+    if (!runnable) {
+      BT_LOGR("BluetoothResultRunnable0::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_LOGR("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    ((*mObj).*mMethod)();
+    return NS_OK;
+  }
+
+private:
+  BluetoothResultRunnable0(Obj* aObj, Res (Obj::*aMethod)())
+  : mObj(aObj)
+  , mMethod(aMethod)
+  {
+    MOZ_ASSERT(mObj);
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    return aInitOp();
+  }
+
+  nsRefPtr<Obj> mObj;
+  void (Obj::*mMethod)();
+};
+
+template <typename Obj, typename Res, typename Tin1, typename Arg1>
+class BluetoothResultRunnable1 : public nsRunnable
+{
+public:
+  typedef BluetoothResultRunnable1<Obj, Res, Tin1, Arg1> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aObj, aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
+    if (!runnable) {
+      BT_LOGR("BluetoothResultRunnable1::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_LOGR("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    ((*mObj).*mMethod)(mArg1);
+    return NS_OK;
+  }
+
+private:
+  BluetoothResultRunnable1(Obj* aObj, Res (Obj::*aMethod)(Arg1))
+  : mObj(aObj)
+  , mMethod(aMethod)
+  {
+    MOZ_ASSERT(mObj);
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    return aInitOp(mArg1);
+  }
+
+  nsRefPtr<Obj> mObj;
+  Res (Obj::*mMethod)(Arg1);
+  Tin1 mArg1;
+};
+
+template <typename Obj, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Arg1, typename Arg2, typename Arg3>
+class BluetoothResultRunnable3 : public nsRunnable
+{
+public:
+  typedef BluetoothResultRunnable3<Obj, Res,
+                                   Tin1, Tin2, Tin3,
+                                   Arg1, Arg2, Arg3> SelfType;
+
+  template<typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
+         const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aObj, aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename InitOp>
+  static void
+  Dispatch(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aObj, aMethod, aInitOp);
+    if (!runnable) {
+      BT_LOGR("BluetoothResultRunnable3::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    ((*mObj).*mMethod)(mArg1, mArg2, mArg3);
+    return NS_OK;
+  }
+
+private:
+  BluetoothResultRunnable3(Obj* aObj, Res (Obj::*aMethod)(Arg1, Arg2, Arg3))
+  : mObj(aObj)
+  , mMethod(aMethod)
+  {
+    MOZ_ASSERT(mObj);
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    return aInitOp(mArg1, mArg2, mArg3);
+  }
+
+  nsRefPtr<Obj> mObj;
+  Res (Obj::*mMethod)(Arg1, Arg2, Arg3);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+};
+
+//
+// Notification handling
+//
+// The classes of type |BluetoothNotificationRunnable[0..5]| transfer
+// a notification from the I/O thread to a notification handler on the
+// main thread. Call the methods |Create| and |Dispatch| to create or
+// create-and-dispatch a notification runnable.
+//
+// Like with result runnables, you need to specify the called method.
+// And like with result runnables, the |Create| and |Dispatch| methods
+// of |BluetoothNotificationRunnable[1..5]| receive an extra argument
+// for initializing the notification's arguments. During creation, the
+// notification runnable calls the class's call operator with the
+// notification's argument. This is where initialization and conversion
+// from backend-specific types is performed.
+//
+
+template <typename ObjectWrapper, typename Res>
+class BluetoothNotificationRunnable0 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationRunnable0<ObjectWrapper, Res> SelfType;
+
+  template<typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      BT_WARNING("BluetoothNotificationRunnable0::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      BT_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)();
+    }
+    return NS_OK;
+  }
+
+private:
+  BluetoothNotificationRunnable0(Res (ObjectType::*aMethod)())
+  : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    return aInitOp();
+  }
+
+  Res (ObjectType::*mMethod)();
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Arg1=Tin1>
+class BluetoothNotificationRunnable1 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationRunnable1<ObjectWrapper, Res,
+                                         Tin1, Arg1> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+
+    if (!runnable) {
+      BT_WARNING("BluetoothNotificationRunnable1::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      BT_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1);
+    }
+    return NS_OK;
+  }
+
+private:
+  BluetoothNotificationRunnable1(Res (ObjectType::*aMethod)(Arg1))
+  : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1);
+  Tin1 mArg1;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2,
+          typename Arg1=Tin1, typename Arg2=Tin2>
+class BluetoothNotificationRunnable2 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationRunnable2<ObjectWrapper, Res,
+                                         Tin1, Tin2,
+                                         Arg1, Arg2> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      BT_WARNING("BluetoothNotificationRunnable2::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      BT_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2);
+    }
+    return NS_OK;
+  }
+
+private:
+  BluetoothNotificationRunnable2(
+    Res (ObjectType::*aMethod)(Arg1, Arg2))
+  : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2);
+  Tin1 mArg1;
+  Tin2 mArg2;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3>
+class BluetoothNotificationRunnable3 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationRunnable3<ObjectWrapper, Res,
+                                             Tin1, Tin2, Tin3,
+                                             Arg1, Arg2, Arg3> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType>
+  Create(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3), const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      BT_WARNING("BluetoothNotificationRunnable3::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      BT_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3);
+    }
+    return NS_OK;
+  }
+
+private:
+  BluetoothNotificationRunnable3(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3))
+  : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3, typename Tin4,
+          typename Arg1=Tin1, typename Arg2=Tin2,
+          typename Arg3=Tin3, typename Arg4=Tin4>
+class BluetoothNotificationRunnable4 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationRunnable4<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Arg1, Arg2, Arg3, Arg4> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+    const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      BT_WARNING("BluetoothNotificationRunnable4::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      BT_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4);
+    }
+    return NS_OK;
+  }
+
+private:
+  BluetoothNotificationRunnable4(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4))
+  : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+  Tin4 mArg4;
+};
+
+template <typename ObjectWrapper, typename Res,
+          typename Tin1, typename Tin2, typename Tin3,
+          typename Tin4, typename Tin5,
+          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3,
+          typename Arg4=Tin4, typename Arg5=Tin5>
+class BluetoothNotificationRunnable5 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationRunnable5<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Tin5, Arg1, Arg2, Arg3, Arg4, Arg5> SelfType;
+
+  template <typename InitOp>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+    const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+    if (NS_FAILED(runnable->Init(aInitOp))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template <typename InitOp>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+           const InitOp& aInitOp)
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod, aInitOp);
+    if (!runnable) {
+      BT_WARNING("BluetoothNotificationRunnable5::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() override
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+    if (!obj) {
+      BT_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)(mArg1, mArg2, mArg3, mArg4, mArg5);
+    }
+    return NS_OK;
+  }
+
+private:
+  BluetoothNotificationRunnable5(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5))
+  : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  template<typename InitOp>
+  nsresult
+  Init(const InitOp& aInitOp)
+  {
+    nsresult rv = aInitOp(mArg1, mArg2, mArg3, mArg4, mArg5);
+    if (NS_FAILED(rv)) {
+      return rv;
+    }
+    return NS_OK;
+  }
+
+  Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3, Arg4, Arg5);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+  Tin4 mArg4;
+  Tin5 mArg5;
+};
+
+//
+// Init operators
+//
+// Below are general-purpose init operators for Bluetooth. The classes
+// of type |ConstantInitOp[1..3]| initialize results or notifications
+// with constant values.
+//
+
+template <typename T1>
+class ConstantInitOp1 final
+{
+public:
+  ConstantInitOp1(const T1& aArg1)
+  : mArg1(aArg1)
+  { }
+
+  nsresult operator () (T1& aArg1) const
+  {
+    aArg1 = mArg1;
+
+    return NS_OK;
+  }
+
+private:
+  const T1& mArg1;
+};
+
+template <typename T1, typename T2>
+class ConstantInitOp2 final
+{
+public:
+  ConstantInitOp2(const T1& aArg1, const T2& aArg2)
+  : mArg1(aArg1)
+  , mArg2(aArg2)
+  { }
+
+  nsresult operator () (T1& aArg1, T2& aArg2) const
+  {
+    aArg1 = mArg1;
+    aArg2 = mArg2;
+
+    return NS_OK;
+  }
+
+private:
+  const T1& mArg1;
+  const T2& mArg2;
+};
+
+template <typename T1, typename T2, typename T3>
+class ConstantInitOp3 final
+{
+public:
+  ConstantInitOp3(const T1& aArg1, const T2& aArg2, const T3& aArg3)
+  : mArg1(aArg1)
+  , mArg2(aArg2)
+  , mArg3(aArg3)
+  { }
+
+  nsresult operator () (T1& aArg1, T2& aArg2, T3& aArg3) const
+  {
+    aArg1 = mArg1;
+    aArg2 = mArg2;
+    aArg3 = mArg3;
+
+    return NS_OK;
+  }
+
+private:
+  const T1& mArg1;
+  const T2& mArg2;
+  const T3& mArg3;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
--- a/dom/bluetooth/moz.build
+++ b/dom/bluetooth/moz.build
@@ -6,18 +6,17 @@
 
 if CONFIG['MOZ_B2G_BT']:
 
     #
     # Generic code
     #
 
     SOURCES += [
-        'BluetoothInterface.cpp',
-        'BluetoothInterfaceHelpers.cpp'
+        'BluetoothInterface.cpp'
     ]
 
     if CONFIG['MOZ_B2G_BT_API_V2']:
         SOURCES += [
             'bluetooth2/BluetoothAdapter.cpp',
             'bluetooth2/BluetoothClassOfDevice.cpp',
             'bluetooth2/BluetoothDevice.cpp',
             'bluetooth2/BluetoothDiscoveryHandle.cpp',
@@ -48,16 +47,17 @@ if CONFIG['MOZ_B2G_BT']:
             'bluetooth2/ipc',
         ]
         DEFINES['MOZ_B2G_BT_API_V2'] = True
     else:
         SOURCES += [
             'bluetooth1/BluetoothAdapter.cpp',
             'bluetooth1/BluetoothDevice.cpp',
             'bluetooth1/BluetoothHidManager.cpp',
+            'bluetooth1/BluetoothInterfaceHelpers.cpp',
             'bluetooth1/BluetoothManager.cpp',
             'bluetooth1/BluetoothProfileController.cpp',
             'bluetooth1/BluetoothPropertyContainer.cpp',
             'bluetooth1/BluetoothReplyRunnable.cpp',
             'bluetooth1/BluetoothService.cpp',
             'bluetooth1/BluetoothUtils.cpp',
             'bluetooth1/BluetoothUuid.cpp',
             'bluetooth1/ipc/BluetoothChild.cpp',