diff --git a/CLOBBER b/CLOBBER
index d4cdfaff33de..9220f8255f4d 100644
--- a/CLOBBER
+++ b/CLOBBER
@@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
-Merge day clobber
\ No newline at end of file
+Bug 1061489: Updated moz.build requires CLOBBER
diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml
index d773de2ffd6b..7f436d10e014 100644
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml
index 6163a8f3a311..c6a8cb1953d2 100644
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml
index b863e1fa4119..5fb8555c43d7 100644
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml
index 9b746f7ca91d..9a55cd46ab14 100644
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml
index 6163a8f3a311..c6a8cb1953d2 100644
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml
index c2c39ba45626..4be1ac7764d2 100644
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml
index 4eed4efd9a55..f55bedfb21d1 100644
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json
index 9580cde62437..7ca4c78c0363 100644
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -4,6 +4,6 @@
"remote": "",
"branch": ""
},
- "revision": "d39431f7b119e5cac505e63375ba929ac72eb681",
+ "revision": "62c1693326443d61bfa405d41d95d05281053cfa",
"repo_path": "/integration/gaia-central"
}
diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml
index 92d706d507c6..362a0a4c7332 100644
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml
index a5c2006a8959..83fbeeaf7271 100644
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml
index 6412839d65ff..78dd1c530bd5 100644
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml
index 64791cc1eda9..82cb97e650aa 100644
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -17,7 +17,7 @@
-
+
diff --git a/dom/bluetooth/BluetoothInterface.cpp b/dom/bluetooth/BluetoothInterface.cpp
new file mode 100644
index 000000000000..6dccf5fb4f54
--- /dev/null
+++ b/dom/bluetooth/BluetoothInterface.cpp
@@ -0,0 +1,109 @@
+/* -*- 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 "BluetoothInterface.h"
+#ifdef MOZ_B2G_BT_BLUEDROID
+#include "BluetoothHALInterface.h"
+#endif
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// Socket Interface
+//
+
+BluetoothSocketInterface::~BluetoothSocketInterface()
+{ }
+
+//
+// Handsfree Interface
+//
+
+// Notification handling
+//
+
+BluetoothHandsfreeNotificationHandler::
+ ~BluetoothHandsfreeNotificationHandler()
+{ }
+
+// Interface
+//
+
+BluetoothHandsfreeInterface::BluetoothHandsfreeInterface()
+{ }
+
+BluetoothHandsfreeInterface::~BluetoothHandsfreeInterface()
+{ }
+
+//
+// Bluetooth Advanced Audio Interface
+//
+
+// Notification handling
+//
+
+BluetoothA2dpNotificationHandler::~BluetoothA2dpNotificationHandler()
+{ }
+
+// Interface
+//
+
+BluetoothA2dpInterface::BluetoothA2dpInterface()
+{ }
+
+BluetoothA2dpInterface::~BluetoothA2dpInterface()
+{ }
+
+//
+// Bluetooth AVRCP Interface
+//
+
+// Notification handling
+//
+
+BluetoothAvrcpNotificationHandler::~BluetoothAvrcpNotificationHandler()
+{ }
+
+// Interface
+//
+
+BluetoothAvrcpInterface::BluetoothAvrcpInterface()
+{ }
+
+BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
+{ }
+
+// Notification handling
+//
+
+BluetoothNotificationHandler::~BluetoothNotificationHandler()
+{ }
+
+// Interface
+//
+
+BluetoothInterface*
+BluetoothInterface::GetInstance()
+{
+ /* Here's where we decide which implementation to use. Currently
+ * there is only Bluedroid, but others are possible. Having multiple
+ * interfaces built-in and selecting the correct one at runtime could
+ * also be an option.
+ */
+#ifdef MOZ_B2G_BT_BLUEDROID
+ return BluetoothHALInterface::GetInstance();
+#else
+ return nullptr;
+#endif
+}
+
+BluetoothInterface::BluetoothInterface()
+{ }
+
+BluetoothInterface::~BluetoothInterface()
+{ }
+
+END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.h b/dom/bluetooth/BluetoothInterface.h
similarity index 53%
rename from dom/bluetooth/bluedroid/BluetoothInterface.h
rename to dom/bluetooth/BluetoothInterface.h
index 6acfc20a2f8d..29b8138a5e7e 100644
--- a/dom/bluetooth/bluedroid/BluetoothInterface.h
+++ b/dom/bluetooth/BluetoothInterface.h
@@ -4,23 +4,14 @@
* 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_bluetoothinterface_h__
-#define mozilla_dom_bluetooth_bluedroid_bluetoothinterface_h__
+#ifndef mozilla_dom_bluetooth_bluetoothinterface_h__
+#define mozilla_dom_bluetooth_bluetoothinterface_h__
-#include
-#include
-#include
-#include
-#if ANDROID_VERSION >= 18
-#include
-#endif
#include "BluetoothCommon.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h"
BEGIN_BLUETOOTH_NAMESPACE
-class BluetoothInterface;
-
//
// Socket Interface
//
@@ -47,30 +38,24 @@ public:
class BluetoothSocketInterface
{
public:
- friend class BluetoothInterface;
-
// Init and Cleanup is handled by BluetoothInterface
- void Listen(BluetoothSocketType aType,
- const nsAString& aServiceName,
- const uint8_t aServiceUuid[16],
- int aChannel, bool aEncrypt, bool aAuth,
- BluetoothSocketResultHandler* aRes);
+ virtual void Listen(BluetoothSocketType aType,
+ const nsAString& aServiceName,
+ const uint8_t aServiceUuid[16],
+ int aChannel, bool aEncrypt, bool aAuth,
+ BluetoothSocketResultHandler* aRes) = 0;
- void Connect(const nsAString& aBdAddr,
- BluetoothSocketType aType,
- const uint8_t aUuid[16],
- int aChannel, bool aEncrypt, bool aAuth,
- BluetoothSocketResultHandler* aRes);
+ virtual void Connect(const nsAString& aBdAddr,
+ BluetoothSocketType aType,
+ const uint8_t aUuid[16],
+ int aChannel, bool aEncrypt, bool aAuth,
+ BluetoothSocketResultHandler* aRes) = 0;
- void Accept(int aFd, BluetoothSocketResultHandler* aRes);
+ virtual void Accept(int aFd, BluetoothSocketResultHandler* aRes) = 0;
protected:
- BluetoothSocketInterface(const btsock_interface_t* aInterface);
- ~BluetoothSocketInterface();
-
-private:
- const btsock_interface_t* mInterface;
+ virtual ~BluetoothSocketInterface();
};
//
@@ -191,74 +176,70 @@ public:
class BluetoothHandsfreeInterface
{
public:
- friend class BluetoothInterface;
-
- void Init(BluetoothHandsfreeNotificationHandler* aNotificationHandler,
- BluetoothHandsfreeResultHandler* aRes);
- void Cleanup(BluetoothHandsfreeResultHandler* aRes);
+ virtual void Init(
+ BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void Cleanup(BluetoothHandsfreeResultHandler* aRes) = 0;
/* Connect / Disconnect */
- void Connect(const nsAString& aBdAddr,
- BluetoothHandsfreeResultHandler* aRes);
- void Disconnect(const nsAString& aBdAddr,
- BluetoothHandsfreeResultHandler* aRes);
- void ConnectAudio(const nsAString& aBdAddr,
- BluetoothHandsfreeResultHandler* aRes);
- void DisconnectAudio(const nsAString& aBdAddr,
- BluetoothHandsfreeResultHandler* aRes);
+ virtual void Connect(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void Disconnect(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void ConnectAudio(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void DisconnectAudio(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
/* Voice Recognition */
- void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
- void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
+ virtual void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes) = 0;
/* Volume */
- void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
- BluetoothHandsfreeResultHandler* aRes);
+ virtual void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
/* Device status */
- void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
- BluetoothHandsfreeServiceType aSvcType,
- int aSignal, int aBattChg,
- BluetoothHandsfreeResultHandler* aRes);
+ virtual void DeviceStatusNotification(
+ BluetoothHandsfreeNetworkState aNtkState,
+ BluetoothHandsfreeServiceType aSvcType,
+ int aSignal, int aBattChg, BluetoothHandsfreeResultHandler* aRes) = 0;
/* Responses */
- void CopsResponse(const char* aCops,
- BluetoothHandsfreeResultHandler* aRes);
- void CindResponse(int aSvc, int aNumActive, int aNumHeld,
- BluetoothHandsfreeCallState aCallSetupState, int aSignal,
- int aRoam, int aBattChg,
- BluetoothHandsfreeResultHandler* aRes);
- void FormattedAtResponse(const char* aRsp,
- BluetoothHandsfreeResultHandler* aRes);
- void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
- BluetoothHandsfreeResultHandler* aRes);
- void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
- BluetoothHandsfreeCallState aState,
- BluetoothHandsfreeCallMode aMode,
- BluetoothHandsfreeCallMptyType aMpty,
- const nsAString& aNumber,
- BluetoothHandsfreeCallAddressType aType,
- BluetoothHandsfreeResultHandler* aRes);
+ virtual void CopsResponse(const char* aCops,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void CindResponse(int aSvc, int aNumActive, int aNumHeld,
+ BluetoothHandsfreeCallState aCallSetupState,
+ int aSignal, int aRoam, int aBattChg,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void FormattedAtResponse(const char* aRsp,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
+ virtual void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
+ BluetoothHandsfreeCallState aState,
+ BluetoothHandsfreeCallMode aMode,
+ BluetoothHandsfreeCallMptyType aMpty,
+ const nsAString& aNumber,
+ BluetoothHandsfreeCallAddressType aType,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
/* Phone State */
- void PhoneStateChange(int aNumActive, int aNumHeld,
- BluetoothHandsfreeCallState aCallSetupState,
- const nsAString& aNumber,
- BluetoothHandsfreeCallAddressType aType,
- BluetoothHandsfreeResultHandler* aRes);
+ virtual void PhoneStateChange(int aNumActive, int aNumHeld,
+ BluetoothHandsfreeCallState aCallSetupState,
+ const nsAString& aNumber,
+ BluetoothHandsfreeCallAddressType aType,
+ BluetoothHandsfreeResultHandler* aRes) = 0;
protected:
- BluetoothHandsfreeInterface(const bthf_interface_t* aInterface);
- ~BluetoothHandsfreeInterface();
-
-private:
- const bthf_interface_t* mInterface;
+ BluetoothHandsfreeInterface();
+ virtual ~BluetoothHandsfreeInterface();
};
//
@@ -306,23 +287,18 @@ public:
class BluetoothA2dpInterface
{
public:
- friend class BluetoothInterface;
+ virtual void Init(BluetoothA2dpNotificationHandler* aNotificationHandler,
+ BluetoothA2dpResultHandler* aRes) = 0;
+ virtual void Cleanup(BluetoothA2dpResultHandler* aRes) = 0;
- void Init(BluetoothA2dpNotificationHandler* aNotificationHandler,
- BluetoothA2dpResultHandler* aRes);
- void Cleanup(BluetoothA2dpResultHandler* aRes);
-
- void Connect(const nsAString& aBdAddr,
- BluetoothA2dpResultHandler* aRes);
- void Disconnect(const nsAString& aBdAddr,
- BluetoothA2dpResultHandler* aRes);
+ virtual void Connect(const nsAString& aBdAddr,
+ BluetoothA2dpResultHandler* aRes) = 0;
+ virtual void Disconnect(const nsAString& aBdAddr,
+ BluetoothA2dpResultHandler* aRes) = 0;
protected:
- BluetoothA2dpInterface(const btav_interface_t* aInterface);
- ~BluetoothA2dpInterface();
-
-private:
- const btav_interface_t* mInterface;
+ BluetoothA2dpInterface();
+ virtual ~BluetoothA2dpInterface();
};
//
@@ -428,61 +404,50 @@ public:
class BluetoothAvrcpInterface
{
public:
- friend class BluetoothInterface;
+ virtual void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler,
+ BluetoothAvrcpResultHandler* aRes) = 0;
+ virtual void Cleanup(BluetoothAvrcpResultHandler* aRes) = 0;
- void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler,
- BluetoothAvrcpResultHandler* aRes);
- void Cleanup(BluetoothAvrcpResultHandler* aRes);
+ virtual void GetPlayStatusRsp(ControlPlayStatus aPlayStatus,
+ uint32_t aSongLen, uint32_t aSongPos,
+ BluetoothAvrcpResultHandler* aRes) = 0;
- void GetPlayStatusRsp(ControlPlayStatus aPlayStatus,
- uint32_t aSongLen, uint32_t aSongPos,
- BluetoothAvrcpResultHandler* aRes);
-
- void ListPlayerAppAttrRsp(int aNumAttr,
- const BluetoothAvrcpPlayerAttribute* aPAttrs,
- BluetoothAvrcpResultHandler* aRes);
- void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals,
- BluetoothAvrcpResultHandler* aRes);
+ virtual void ListPlayerAppAttrRsp(
+ int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
+ BluetoothAvrcpResultHandler* aRes) = 0;
+ virtual void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals,
+ BluetoothAvrcpResultHandler* aRes) = 0;
/* TODO: redesign this interface once we actually use it */
- void GetPlayerAppValueRsp(uint8_t aNumAttrs,
- const uint8_t* aIds, const uint8_t* aValues,
- BluetoothAvrcpResultHandler* aRes);
+ virtual void GetPlayerAppValueRsp(uint8_t aNumAttrs, const uint8_t* aIds,
+ const uint8_t* aValues,
+ BluetoothAvrcpResultHandler* aRes) = 0;
/* TODO: redesign this interface once we actually use it */
- void GetPlayerAppAttrTextRsp(int aNumAttr,
- const uint8_t* aIds, const char** aTexts,
- BluetoothAvrcpResultHandler* aRes);
+ virtual void GetPlayerAppAttrTextRsp(int aNumAttr, const uint8_t* aIds,
+ const char** aTexts,
+ BluetoothAvrcpResultHandler* aRes) = 0;
/* TODO: redesign this interface once we actually use it */
- void GetPlayerAppValueTextRsp(int aNumVal,
- const uint8_t* aIds, const char** aTexts,
- BluetoothAvrcpResultHandler* aRes);
+ virtual void GetPlayerAppValueTextRsp(int aNumVal, const uint8_t* aIds,
+ const char** aTexts,
+ BluetoothAvrcpResultHandler* aRes) = 0;
- void GetElementAttrRsp(uint8_t aNumAttr,
- const BluetoothAvrcpElementAttribute* aAttr,
- BluetoothAvrcpResultHandler* aRes);
+ virtual void GetElementAttrRsp(uint8_t aNumAttr,
+ const BluetoothAvrcpElementAttribute* aAttr,
+ BluetoothAvrcpResultHandler* aRes) = 0;
- void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus,
- BluetoothAvrcpResultHandler* aRes);
+ virtual void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus,
+ BluetoothAvrcpResultHandler* aRes) = 0;
- void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent,
- BluetoothAvrcpNotification aType,
- const BluetoothAvrcpNotificationParam& aParam,
- BluetoothAvrcpResultHandler* aRes);
+ virtual void RegisterNotificationRsp(
+ BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
+ const BluetoothAvrcpNotificationParam& aParam,
+ BluetoothAvrcpResultHandler* aRes) = 0;
- void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
+ virtual void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes) = 0;
protected:
- BluetoothAvrcpInterface(
-#if ANDROID_VERSION >= 18
- const btrc_interface_t* aInterface
-#endif
- );
- ~BluetoothAvrcpInterface();
-
-private:
-#if ANDROID_VERSION >= 18
- const btrc_interface_t* mInterface;
-#endif
+ BluetoothAvrcpInterface();
+ virtual ~BluetoothAvrcpInterface();
};
//
@@ -582,92 +547,86 @@ class BluetoothInterface
public:
static BluetoothInterface* GetInstance();
- void Init(BluetoothNotificationHandler* aNotificationHandler,
- BluetoothResultHandler* aRes);
- void Cleanup(BluetoothResultHandler* aRes);
-
- void Enable(BluetoothResultHandler* aRes);
- void Disable(BluetoothResultHandler* aRes);
+ virtual void Init(BluetoothNotificationHandler* aNotificationHandler,
+ BluetoothResultHandler* aRes) = 0;
+ virtual void Cleanup(BluetoothResultHandler* aRes) = 0;
+ virtual void Enable(BluetoothResultHandler* aRes) = 0;
+ virtual void Disable(BluetoothResultHandler* aRes) = 0;
/* Adapter Properties */
- void GetAdapterProperties(BluetoothResultHandler* aRes);
- void GetAdapterProperty(const nsAString& aName,
- BluetoothResultHandler* aRes);
- void SetAdapterProperty(const BluetoothNamedValue& aProperty,
- BluetoothResultHandler* aRes);
+ virtual void GetAdapterProperties(BluetoothResultHandler* aRes) = 0;
+ virtual void GetAdapterProperty(const nsAString& aName,
+ BluetoothResultHandler* aRes) = 0;
+ virtual void SetAdapterProperty(const BluetoothNamedValue& aProperty,
+ BluetoothResultHandler* aRes) = 0;
/* 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);
+ virtual void GetRemoteDeviceProperties(const nsAString& aRemoteAddr,
+ BluetoothResultHandler* aRes) = 0;
+ virtual void GetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+ const nsAString& aName,
+ BluetoothResultHandler* aRes) = 0;
+ virtual void SetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+ const BluetoothNamedValue& aProperty,
+ BluetoothResultHandler* aRes) = 0;
/* Remote Services */
- void GetRemoteServiceRecord(const nsAString& aRemoteAddr,
- const uint8_t aUuid[16],
- BluetoothResultHandler* aRes);
- void GetRemoteServices(const nsAString& aRemoteAddr,
- BluetoothResultHandler* aRes);
+ virtual void GetRemoteServiceRecord(const nsAString& aRemoteAddr,
+ const uint8_t aUuid[16],
+ BluetoothResultHandler* aRes) = 0;
+ virtual void GetRemoteServices(const nsAString& aRemoteAddr,
+ BluetoothResultHandler* aRes) = 0;
/* Discovery */
- void StartDiscovery(BluetoothResultHandler* aRes);
- void CancelDiscovery(BluetoothResultHandler* aRes);
+ virtual void StartDiscovery(BluetoothResultHandler* aRes) = 0;
+ virtual void CancelDiscovery(BluetoothResultHandler* aRes) = 0;
/* Bonds */
- void CreateBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
- void RemoveBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
- void CancelBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
+ virtual void CreateBond(const nsAString& aBdAddr,
+ BluetoothResultHandler* aRes) = 0;
+ virtual void RemoveBond(const nsAString& aBdAddr,
+ BluetoothResultHandler* aRes) = 0;
+ virtual void CancelBond(const nsAString& aBdAddr,
+ BluetoothResultHandler* aRes) = 0;
/* Authentication */
- void PinReply(const nsAString& aBdAddr, bool aAccept,
- const nsAString& aPinCode,
- BluetoothResultHandler* aRes);
+ virtual void PinReply(const nsAString& aBdAddr, bool aAccept,
+ const nsAString& aPinCode,
+ BluetoothResultHandler* aRes) = 0;
- void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
- bool aAccept, uint32_t aPasskey,
- BluetoothResultHandler* aRes);
+ virtual void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
+ bool aAccept, uint32_t aPasskey,
+ BluetoothResultHandler* aRes) = 0;
/* DUT Mode */
- void DutModeConfigure(bool aEnable, BluetoothResultHandler* aRes);
- void DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
- BluetoothResultHandler* aRes);
+ virtual void DutModeConfigure(bool aEnable,
+ BluetoothResultHandler* aRes) = 0;
+ virtual void DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+ BluetoothResultHandler* aRes) = 0;
/* LE Mode */
- void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
- BluetoothResultHandler* aRes);
+ virtual void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+ BluetoothResultHandler* aRes) = 0;
/* Profile Interfaces */
- BluetoothSocketInterface* GetBluetoothSocketInterface();
- BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface();
- BluetoothA2dpInterface* GetBluetoothA2dpInterface();
- BluetoothAvrcpInterface* GetBluetoothAvrcpInterface();
+ virtual BluetoothSocketInterface* GetBluetoothSocketInterface() = 0;
+ virtual BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface() = 0;
+ virtual BluetoothA2dpInterface* GetBluetoothA2dpInterface() = 0;
+ virtual BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() = 0;
protected:
- BluetoothInterface(const bt_interface_t* aInterface);
- ~BluetoothInterface();
-
-private:
- template
- T* CreateProfileInterface();
-
- template
- T* GetProfileInterface();
-
- const bt_interface_t* mInterface;
+ BluetoothInterface();
+ virtual ~BluetoothInterface();
};
END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.cpp
new file mode 100644
index 000000000000..5bd82e7c893e
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.cpp
@@ -0,0 +1,184 @@
+/* -*- 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 "BluetoothA2dpHALInterface.h"
+#include "BluetoothHALHelpers.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+typedef
+ BluetoothHALInterfaceRunnable0
+ BluetoothA2dpHALResultRunnable;
+
+typedef
+ BluetoothHALInterfaceRunnable1
+ BluetoothA2dpHALErrorRunnable;
+
+static nsresult
+DispatchBluetoothA2dpHALResult(
+ BluetoothA2dpResultHandler* aRes,
+ void (BluetoothA2dpResultHandler::*aMethod)(),
+ BluetoothStatus aStatus)
+{
+ MOZ_ASSERT(aRes);
+
+ nsRunnable* runnable;
+
+ if (aStatus == STATUS_SUCCESS) {
+ runnable = new BluetoothA2dpHALResultRunnable(aRes, aMethod);
+ } else {
+ runnable = new BluetoothA2dpHALErrorRunnable(aRes,
+ &BluetoothA2dpResultHandler::OnError, aStatus);
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ return rv;
+}
+
+// Notification handling
+//
+
+static BluetoothA2dpNotificationHandler* sA2dpNotificationHandler;
+
+struct BluetoothA2dpHALCallback
+{
+ class A2dpNotificationHandlerWrapper
+ {
+ public:
+ typedef BluetoothA2dpNotificationHandler ObjectType;
+
+ static ObjectType* GetInstance()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ return sA2dpNotificationHandler;
+ }
+ };
+
+ // Notifications
+
+ typedef BluetoothNotificationHALRunnable2<
+ A2dpNotificationHandlerWrapper, void,
+ BluetoothA2dpConnectionState, nsString,
+ BluetoothA2dpConnectionState, const nsAString&>
+ ConnectionStateNotification;
+
+ typedef BluetoothNotificationHALRunnable2<
+ A2dpNotificationHandlerWrapper, void,
+ BluetoothA2dpAudioState, nsString,
+ BluetoothA2dpAudioState, const nsAString&>
+ AudioStateNotification;
+
+ // Bluedroid A2DP callbacks
+
+ static void
+ ConnectionState(btav_connection_state_t aState, bt_bdaddr_t* aBdAddr)
+ {
+ ConnectionStateNotification::Dispatch(
+ &BluetoothA2dpNotificationHandler::ConnectionStateNotification,
+ aState, aBdAddr);
+ }
+
+ static void
+ AudioState(btav_audio_state_t aState, bt_bdaddr_t* aBdAddr)
+ {
+ AudioStateNotification::Dispatch(
+ &BluetoothA2dpNotificationHandler::AudioStateNotification,
+ aState, aBdAddr);
+ }
+};
+
+// Interface
+//
+
+BluetoothA2dpHALInterface::BluetoothA2dpHALInterface(
+ const btav_interface_t* aInterface)
+: mInterface(aInterface)
+{
+ MOZ_ASSERT(mInterface);
+}
+
+BluetoothA2dpHALInterface::~BluetoothA2dpHALInterface()
+{ }
+
+void
+BluetoothA2dpHALInterface::Init(
+ BluetoothA2dpNotificationHandler* aNotificationHandler,
+ BluetoothA2dpResultHandler* aRes)
+{
+ static btav_callbacks_t sCallbacks = {
+ sizeof(sCallbacks),
+ BluetoothA2dpHALCallback::ConnectionState,
+ BluetoothA2dpHALCallback::AudioState
+ };
+
+ sA2dpNotificationHandler = aNotificationHandler;
+
+ bt_status_t status = mInterface->init(&sCallbacks);
+
+ if (aRes) {
+ DispatchBluetoothA2dpHALResult(aRes,
+ &BluetoothA2dpResultHandler::Init,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothA2dpHALInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
+{
+ mInterface->cleanup();
+
+ if (aRes) {
+ DispatchBluetoothA2dpHALResult(aRes,
+ &BluetoothA2dpResultHandler::Cleanup,
+ STATUS_SUCCESS);
+ }
+}
+
+void
+BluetoothA2dpHALInterface::Connect(const nsAString& aBdAddr,
+ BluetoothA2dpResultHandler* aRes)
+{
+ bt_status_t status;
+ bt_bdaddr_t bdAddr;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->connect(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothA2dpHALResult(
+ aRes, &BluetoothA2dpResultHandler::Connect,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothA2dpHALInterface::Disconnect(const nsAString& aBdAddr,
+ BluetoothA2dpResultHandler* aRes)
+{
+ bt_status_t status;
+ bt_bdaddr_t bdAddr;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->disconnect(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothA2dpHALResult(
+ aRes, &BluetoothA2dpResultHandler::Disconnect,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.h b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.h
new file mode 100644
index 000000000000..84b1108bf3fa
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpHALInterface.h
@@ -0,0 +1,44 @@
+/* -*- 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_bluetootha2dphalinterface_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetootha2dphalinterface_h__
+
+#include
+#include
+#include "BluetoothCommon.h"
+#include "BluetoothInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothHALInterface;
+
+class BluetoothA2dpHALInterface MOZ_FINAL
+ : public BluetoothA2dpInterface
+{
+public:
+ friend class BluetoothHALInterface;
+
+ void Init(BluetoothA2dpNotificationHandler* aNotificationHandler,
+ BluetoothA2dpResultHandler* aRes);
+ void Cleanup(BluetoothA2dpResultHandler* aRes);
+
+ void Connect(const nsAString& aBdAddr,
+ BluetoothA2dpResultHandler* aRes);
+ void Disconnect(const nsAString& aBdAddr,
+ BluetoothA2dpResultHandler* aRes);
+
+protected:
+ BluetoothA2dpHALInterface(const btav_interface_t* aInterface);
+ ~BluetoothA2dpHALInterface();
+
+private:
+ const btav_interface_t* mInterface;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
diff --git a/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.cpp
new file mode 100644
index 000000000000..3b9f1e8bae9d
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.cpp
@@ -0,0 +1,593 @@
+/* -*- 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 "BluetoothAvrcpHALInterface.h"
+#include "BluetoothHALHelpers.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+typedef
+ BluetoothHALInterfaceRunnable0
+ BluetoothAvrcpHALResultRunnable;
+
+typedef
+ BluetoothHALInterfaceRunnable1
+ BluetoothAvrcpHALErrorRunnable;
+
+static nsresult
+DispatchBluetoothAvrcpHALResult(
+ BluetoothAvrcpResultHandler* aRes,
+ void (BluetoothAvrcpResultHandler::*aMethod)(),
+ BluetoothStatus aStatus)
+{
+ MOZ_ASSERT(aRes);
+
+ nsRunnable* runnable;
+
+ if (aStatus == STATUS_SUCCESS) {
+ runnable = new BluetoothAvrcpHALResultRunnable(aRes, aMethod);
+ } else {
+ runnable = new BluetoothAvrcpHALErrorRunnable(aRes,
+ &BluetoothAvrcpResultHandler::OnError, aStatus);
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ return rv;
+}
+
+// Notification handling
+//
+
+static BluetoothAvrcpNotificationHandler* sAvrcpNotificationHandler;
+
+struct BluetoothAvrcpCallback
+{
+ class AvrcpNotificationHandlerWrapper
+ {
+ public:
+ typedef BluetoothAvrcpNotificationHandler ObjectType;
+
+ static ObjectType* GetInstance()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ return sAvrcpNotificationHandler;
+ }
+ };
+
+ // Notifications
+
+ typedef BluetoothNotificationHALRunnable0
+ GetPlayStatusNotification;
+
+ typedef BluetoothNotificationHALRunnable0
+ ListPlayerAppAttrNotification;
+
+ typedef BluetoothNotificationHALRunnable1
+ ListPlayerAppValuesNotification;
+
+ typedef BluetoothNotificationHALRunnable2,
+ uint8_t, const BluetoothAvrcpPlayerAttribute*>
+ GetPlayerAppValueNotification;
+
+ typedef BluetoothNotificationHALRunnable2,
+ uint8_t, const BluetoothAvrcpPlayerAttribute*>
+ GetPlayerAppAttrsTextNotification;
+
+ typedef BluetoothNotificationHALRunnable3,
+ uint8_t, uint8_t, const uint8_t*>
+ GetPlayerAppValuesTextNotification;
+
+ typedef BluetoothNotificationHALRunnable1
+ SetPlayerAppValueNotification;
+
+ typedef BluetoothNotificationHALRunnable2,
+ uint8_t, const BluetoothAvrcpMediaAttribute*>
+ GetElementAttrNotification;
+
+ typedef BluetoothNotificationHALRunnable2
+ RegisterNotificationNotification;
+
+ typedef BluetoothNotificationHALRunnable2
+ RemoteFeatureNotification;
+
+ typedef BluetoothNotificationHALRunnable2
+ VolumeChangeNotification;
+
+ typedef BluetoothNotificationHALRunnable2
+ PassthroughCmdNotification;
+
+ // Bluedroid AVRCP callbacks
+
+#if ANDROID_VERSION >= 18
+ static void
+ GetPlayStatus()
+ {
+ GetPlayStatusNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::GetPlayStatusNotification);
+ }
+
+ static void
+ ListPlayerAppAttr()
+ {
+ ListPlayerAppAttrNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::ListPlayerAppAttrNotification);
+ }
+
+ static void
+ ListPlayerAppValues(btrc_player_attr_t aAttrId)
+ {
+ ListPlayerAppValuesNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::ListPlayerAppValuesNotification,
+ aAttrId);
+ }
+
+ static void
+ GetPlayerAppValue(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs)
+ {
+ GetPlayerAppValueNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::GetPlayerAppValueNotification,
+ aNumAttrs, ConvertArray(aAttrs, aNumAttrs));
+ }
+
+ static void
+ GetPlayerAppAttrsText(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs)
+ {
+ GetPlayerAppAttrsTextNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification,
+ aNumAttrs, ConvertArray(aAttrs, aNumAttrs));
+ }
+
+ static void
+ GetPlayerAppValuesText(uint8_t aAttrId, uint8_t aNumVals, uint8_t* aVals)
+ {
+ GetPlayerAppValuesTextNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification,
+ aAttrId, aNumVals, ConvertArray(aVals, aNumVals));
+ }
+
+ static void
+ SetPlayerAppValue(btrc_player_settings_t* aVals)
+ {
+ SetPlayerAppValueNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::SetPlayerAppValueNotification,
+ *aVals);
+ }
+
+ static void
+ GetElementAttr(uint8_t aNumAttrs, btrc_media_attr_t* aAttrs)
+ {
+ GetElementAttrNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::GetElementAttrNotification,
+ aNumAttrs, ConvertArray(aAttrs, aNumAttrs));
+ }
+
+ static void
+ RegisterNotification(btrc_event_id_t aEvent, uint32_t aParam)
+ {
+ RegisterNotificationNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::RegisterNotificationNotification,
+ aEvent, aParam);
+ }
+#endif // ANDROID_VERSION >= 18
+
+#if ANDROID_VERSION >= 19
+ static void
+ RemoteFeature(bt_bdaddr_t* aBdAddr, btrc_remote_features_t aFeatures)
+ {
+ RemoteFeatureNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::RemoteFeatureNotification,
+ aBdAddr, aFeatures);
+ }
+
+ static void
+ VolumeChange(uint8_t aVolume, uint8_t aCType)
+ {
+ VolumeChangeNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::VolumeChangeNotification,
+ aVolume, aCType);
+ }
+
+ static void
+ PassthroughCmd(int aId, int aKeyState)
+ {
+ PassthroughCmdNotification::Dispatch(
+ &BluetoothAvrcpNotificationHandler::PassthroughCmdNotification,
+ aId, aKeyState);
+ }
+#endif // ANDROID_VERSION >= 19
+};
+
+// Interface
+//
+
+BluetoothAvrcpHALInterface::BluetoothAvrcpHALInterface(
+#if ANDROID_VERSION >= 18
+ const btrc_interface_t* aInterface
+#endif
+ )
+#if ANDROID_VERSION >= 18
+: mInterface(aInterface)
+#endif
+{
+#if ANDROID_VERSION >= 18
+ MOZ_ASSERT(mInterface);
+#endif
+}
+
+BluetoothAvrcpHALInterface::~BluetoothAvrcpHALInterface()
+{ }
+
+void
+BluetoothAvrcpHALInterface::Init(
+ BluetoothAvrcpNotificationHandler* aNotificationHandler,
+ BluetoothAvrcpResultHandler* aRes)
+{
+#if ANDROID_VERSION >= 18
+ static btrc_callbacks_t sCallbacks = {
+ sizeof(sCallbacks),
+#if ANDROID_VERSION >= 19
+ BluetoothAvrcpCallback::RemoteFeature,
+#endif
+ BluetoothAvrcpCallback::GetPlayStatus,
+ BluetoothAvrcpCallback::ListPlayerAppAttr,
+ BluetoothAvrcpCallback::ListPlayerAppValues,
+ BluetoothAvrcpCallback::GetPlayerAppValue,
+ BluetoothAvrcpCallback::GetPlayerAppAttrsText,
+ BluetoothAvrcpCallback::GetPlayerAppValuesText,
+ BluetoothAvrcpCallback::SetPlayerAppValue,
+ BluetoothAvrcpCallback::GetElementAttr,
+ BluetoothAvrcpCallback::RegisterNotification
+#if ANDROID_VERSION >= 19
+ ,
+ BluetoothAvrcpCallback::VolumeChange,
+ BluetoothAvrcpCallback::PassthroughCmd
+#endif
+ };
+#endif // ANDROID_VERSION >= 18
+
+ sAvrcpNotificationHandler = aNotificationHandler;
+
+#if ANDROID_VERSION >= 18
+ bt_status_t status = mInterface->init(&sCallbacks);
+#else
+ bt_status_t status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(aRes, &BluetoothAvrcpResultHandler::Init,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
+{
+#if ANDROID_VERSION >= 18
+ mInterface->cleanup();
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(aRes,
+ &BluetoothAvrcpResultHandler::Cleanup, STATUS_SUCCESS);
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::GetPlayStatusRsp(
+ ControlPlayStatus aPlayStatus, uint32_t aSongLen, uint32_t aSongPos,
+ BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ btrc_play_status_t playStatus = BTRC_PLAYSTATE_STOPPED;
+
+ if (!(NS_FAILED(Convert(aPlayStatus, playStatus)))) {
+ status = mInterface->get_play_status_rsp(playStatus, aSongLen, aSongPos);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::ListPlayerAppAttrRsp(
+ int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
+ BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ ConvertArray pAttrsArray(aPAttrs, aNumAttr);
+ nsAutoArrayPtr pAttrs;
+
+ if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) {
+ status = mInterface->list_player_app_attr_rsp(aNumAttr, pAttrs);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::ListPlayerAppValueRsp(
+ int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes)
+{
+#if ANDROID_VERSION >= 18
+ bt_status_t status = mInterface->list_player_app_value_rsp(aNumVal, aPVals);
+#else
+ bt_status_t status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::GetPlayerAppValueRsp(
+ uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues,
+ BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ btrc_player_settings_t pVals;
+
+ /* FIXME: you need to implement the missing conversion functions */
+ NS_NOTREACHED("Conversion function missing");
+
+ if (false /* TODO: we don't support any player app values currently */) {
+ status = mInterface->get_player_app_value_rsp(&pVals);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::GetPlayerAppAttrTextRsp(
+ int aNumAttr, const uint8_t* aIds, const char** aTexts,
+ BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ btrc_player_setting_text_t* aPAttrs;
+
+ /* FIXME: you need to implement the missing conversion functions */
+ NS_NOTREACHED("Conversion function missing");
+
+ if (false /* TODO: we don't support any attributes currently */) {
+ status = mInterface->get_player_app_attr_text_rsp(aNumAttr, aPAttrs);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::GetPlayerAppValueTextRsp(
+ int aNumVal, const uint8_t* aIds, const char** aTexts,
+ BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ btrc_player_setting_text_t* pVals;
+
+ /* FIXME: you need to implement the missing conversion functions */
+ NS_NOTREACHED("Conversion function missing");
+
+ if (false /* TODO: we don't support any values currently */) {
+ status = mInterface->get_player_app_value_text_rsp(aNumVal, pVals);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::GetElementAttrRsp(
+ uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttrs,
+ BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ ConvertArray pAttrsArray(aAttrs, aNumAttr);
+ nsAutoArrayPtr pAttrs;
+
+ if (NS_SUCCEEDED(Convert(pAttrsArray, pAttrs))) {
+ status = mInterface->get_element_attr_rsp(aNumAttr, pAttrs);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::SetPlayerAppValueRsp(
+ BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ btrc_status_t rspStatus = BTRC_STS_BAD_CMD; // silences compiler warning
+
+ if (NS_SUCCEEDED(Convert(aRspStatus, rspStatus))) {
+ status = mInterface->set_player_app_value_rsp(rspStatus);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::RegisterNotificationRsp(
+ BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
+ const BluetoothAvrcpNotificationParam& aParam,
+ BluetoothAvrcpResultHandler* aRes)
+{
+ bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+ nsresult rv;
+ btrc_event_id_t event = { };
+ btrc_notification_type_t type = BTRC_NOTIFICATION_TYPE_INTERIM;
+ btrc_register_notification_t param;
+
+ switch (aEvent) {
+ case AVRCP_EVENT_PLAY_STATUS_CHANGED:
+ rv = Convert(aParam.mPlayStatus, param.play_status);
+ break;
+ case AVRCP_EVENT_TRACK_CHANGE:
+ MOZ_ASSERT(sizeof(aParam.mTrack) == sizeof(param.track));
+ memcpy(param.track, aParam.mTrack, sizeof(param.track));
+ rv = NS_OK;
+ break;
+ case AVRCP_EVENT_TRACK_REACHED_END:
+ NS_NOTREACHED("Unknown conversion");
+ rv = NS_ERROR_ILLEGAL_VALUE;
+ break;
+ case AVRCP_EVENT_TRACK_REACHED_START:
+ NS_NOTREACHED("Unknown conversion");
+ rv = NS_ERROR_ILLEGAL_VALUE;
+ break;
+ case AVRCP_EVENT_PLAY_POS_CHANGED:
+ param.song_pos = aParam.mSongPos;
+ rv = NS_OK;
+ break;
+ case AVRCP_EVENT_APP_SETTINGS_CHANGED:
+ NS_NOTREACHED("Unknown conversion");
+ rv = NS_ERROR_ILLEGAL_VALUE;
+ break;
+ default:
+ NS_NOTREACHED("Unknown conversion");
+ rv = NS_ERROR_ILLEGAL_VALUE;
+ break;
+ }
+
+ if (NS_SUCCEEDED(rv) &&
+ NS_SUCCEEDED(Convert(aEvent, event)) &&
+ NS_SUCCEEDED(Convert(aType, type))) {
+ status = mInterface->register_notification_rsp(event, type, ¶m);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+#else
+ status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothAvrcpHALInterface::SetVolume(uint8_t aVolume,
+ BluetoothAvrcpResultHandler* aRes)
+{
+#if ANDROID_VERSION >= 19
+ bt_status_t status = mInterface->set_volume(aVolume);
+#else
+ bt_status_t status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothAvrcpHALResult(
+ aRes, &BluetoothAvrcpResultHandler::SetVolume,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.h b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.h
new file mode 100644
index 000000000000..8dcd54fc6bc5
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothAvrcpHALInterface.h
@@ -0,0 +1,84 @@
+/* -*- 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_bluetoothavrcphalinterface_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothavrcphalinterface_h__
+
+#include
+#if ANDROID_VERSION >= 18
+#include
+#endif
+#include "BluetoothCommon.h"
+#include "BluetoothInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothHALInterface;
+
+class BluetoothAvrcpHALInterface MOZ_FINAL
+ : public BluetoothAvrcpInterface
+{
+public:
+ friend class BluetoothHALInterface;
+
+ void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler,
+ BluetoothAvrcpResultHandler* aRes);
+ void Cleanup(BluetoothAvrcpResultHandler* aRes);
+
+ void GetPlayStatusRsp(ControlPlayStatus aPlayStatus,
+ uint32_t aSongLen, uint32_t aSongPos,
+ BluetoothAvrcpResultHandler* aRes);
+
+ void ListPlayerAppAttrRsp(int aNumAttr,
+ const BluetoothAvrcpPlayerAttribute* aPAttrs,
+ BluetoothAvrcpResultHandler* aRes);
+ void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals,
+ BluetoothAvrcpResultHandler* aRes);
+
+ /* TODO: redesign this interface once we actually use it */
+ void GetPlayerAppValueRsp(uint8_t aNumAttrs,
+ const uint8_t* aIds, const uint8_t* aValues,
+ BluetoothAvrcpResultHandler* aRes);
+ /* TODO: redesign this interface once we actually use it */
+ void GetPlayerAppAttrTextRsp(int aNumAttr,
+ const uint8_t* aIds, const char** aTexts,
+ BluetoothAvrcpResultHandler* aRes);
+ /* TODO: redesign this interface once we actually use it */
+ void GetPlayerAppValueTextRsp(int aNumVal,
+ const uint8_t* aIds, const char** aTexts,
+ BluetoothAvrcpResultHandler* aRes);
+
+ void GetElementAttrRsp(uint8_t aNumAttr,
+ const BluetoothAvrcpElementAttribute* aAttr,
+ BluetoothAvrcpResultHandler* aRes);
+
+ void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus,
+ BluetoothAvrcpResultHandler* aRes);
+
+ void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent,
+ BluetoothAvrcpNotification aType,
+ const BluetoothAvrcpNotificationParam& aParam,
+ BluetoothAvrcpResultHandler* aRes);
+
+ void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
+
+protected:
+ BluetoothAvrcpHALInterface(
+#if ANDROID_VERSION >= 18
+ const btrc_interface_t* aInterface
+#endif
+ );
+ ~BluetoothAvrcpHALInterface();
+
+private:
+#if ANDROID_VERSION >= 18
+ const btrc_interface_t* mInterface;
+#endif
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp
new file mode 100644
index 000000000000..f0163b26084d
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.cpp
@@ -0,0 +1,298 @@
+/* -*- 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 "BluetoothHALHelpers.h"
+
+#define MAX_UUID_SIZE 16
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// Conversion
+//
+
+nsresult
+Convert(const nsAString& aIn, bt_property_type_t& aOut)
+{
+ if (aIn.EqualsLiteral("Name")) {
+ aOut = BT_PROPERTY_BDNAME;
+ } else if (aIn.EqualsLiteral("Discoverable")) {
+ aOut = BT_PROPERTY_ADAPTER_SCAN_MODE;
+ } else if (aIn.EqualsLiteral("DiscoverableTimeout")) {
+ aOut = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
+ } else {
+ BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aIn).get());
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ return NS_OK;
+}
+
+nsresult
+Convert(ConvertNamedValue& aIn, bt_property_t& aOut)
+{
+ nsresult rv = Convert(aIn.mNamedValue.name(), aOut.type);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (aIn.mNamedValue.value().type() == BluetoothValue::Tuint32_t) {
+ // Set discoverable timeout
+ aOut.val =
+ reinterpret_cast(aIn.mNamedValue.value().get_uint32_t());
+ } else if (aIn.mNamedValue.value().type() == BluetoothValue::TnsString) {
+ // Set name
+ aIn.mStringValue =
+ NS_ConvertUTF16toUTF8(aIn.mNamedValue.value().get_nsString());
+ aOut.val =
+ const_cast(static_cast(aIn.mStringValue.get()));
+ aOut.len = strlen(static_cast(aOut.val));
+ } else if (aIn.mNamedValue.value().type() == BluetoothValue::Tbool) {
+ // Set scan mode
+ rv = Convert(aIn.mNamedValue.value().get_bool(), aIn.mScanMode);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ aOut.val = &aIn.mScanMode;
+ aOut.len = sizeof(aIn.mScanMode);
+ } else {
+ BT_LOGR("Invalid property value type");
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const nsAString& aIn, bt_bdaddr_t& aOut)
+{
+ NS_ConvertUTF16toUTF8 bdAddressUTF8(aIn);
+ const char* str = bdAddressUTF8.get();
+
+ for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aOut.address); ++i, ++str) {
+ aOut.address[i] =
+ static_cast(strtoul(str, const_cast(&str), 16));
+ }
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const nsAString& aIn, bt_ssp_variant_t& aOut)
+{
+ if (aIn.EqualsLiteral("PasskeyConfirmation")) {
+ aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION;
+ } else if (aIn.EqualsLiteral("PasskeyEntry")) {
+ aOut = BT_SSP_VARIANT_PASSKEY_ENTRY;
+ } else if (aIn.EqualsLiteral("Consent")) {
+ aOut = BT_SSP_VARIANT_CONSENT;
+ } else if (aIn.EqualsLiteral("PasskeyNotification")) {
+ aOut = BT_SSP_VARIANT_PASSKEY_NOTIFICATION;
+ } else {
+ BT_LOGR("Invalid SSP variant name: %s", NS_ConvertUTF16toUTF8(aIn).get());
+ aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ return NS_OK;
+}
+
+nsresult
+Convert(const uint8_t aIn[16], bt_uuid_t& aOut)
+{
+ if (sizeof(aOut.uu) != 16) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ memcpy(aOut.uu, aIn, sizeof(aOut.uu));
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut)
+{
+ if (sizeof(aIn.uu) != sizeof(aOut.mUuid)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ memcpy(aOut.mUuid, aIn.uu, sizeof(aOut.mUuid));
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const nsAString& aIn, bt_pin_code_t& aOut)
+{
+ if (aIn.Length() > MOZ_ARRAY_LENGTH(aOut.pin)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+
+ NS_ConvertUTF16toUTF8 pinCodeUTF8(aIn);
+ const char* str = pinCodeUTF8.get();
+
+ nsAString::size_type i;
+
+ // Fill pin into aOut
+ for (i = 0; i < aIn.Length(); ++i, ++str) {
+ aOut.pin[i] = static_cast(*str);
+ }
+
+ // Clear remaining bytes in aOut
+ size_t ntrailing =
+ (MOZ_ARRAY_LENGTH(aOut.pin) - aIn.Length()) * sizeof(aOut.pin[0]);
+ memset(aOut.pin + aIn.Length(), 0, ntrailing);
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const bt_bdaddr_t& aIn, nsAString& aOut)
+{
+ char str[BLUETOOTH_ADDRESS_LENGTH + 1];
+
+ int res = snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
+ static_cast(aIn.address[0]),
+ static_cast(aIn.address[1]),
+ static_cast(aIn.address[2]),
+ static_cast(aIn.address[3]),
+ static_cast(aIn.address[4]),
+ static_cast(aIn.address[5]));
+ if (res < 0) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ } else if ((size_t)res >= sizeof(str)) {
+ return NS_ERROR_OUT_OF_MEMORY; /* string buffer too small */
+ }
+
+ aOut = NS_ConvertUTF8toUTF16(str);
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut)
+{
+ nsresult rv = Convert(aIn.uuid, aOut.mUuid);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ aOut.mChannel = aIn.channel;
+
+ MOZ_ASSERT(sizeof(aIn.name) == sizeof(aOut.mName));
+ memcpy(aOut.mName, aIn.name, sizeof(aOut.mName));
+
+ return NS_OK;
+}
+
+#if ANDROID_VERSION >= 18
+nsresult
+Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut)
+{
+ const NS_ConvertUTF16toUTF8 value(aIn.mValue);
+ size_t len = std::min(strlen(value.get()), sizeof(aOut.text) - 1);
+
+ memcpy(aOut.text, value.get(), len);
+ aOut.text[len] = '\0';
+ aOut.attr_id = aIn.mId;
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut)
+{
+ aOut.mNumAttr = aIn.num_attr;
+ memcpy(aOut.mIds, aIn.attr_ids, aIn.num_attr);
+ memcpy(aOut.mValues, aIn.attr_values, aIn.num_attr);
+
+ return NS_OK;
+}
+#endif // ANDROID_VERSION >= 18
+
+nsresult
+Convert(const bt_property_t& aIn, BluetoothProperty& aOut)
+{
+ /* type conversion */
+
+ nsresult rv = Convert(aIn.type, aOut.mType);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ /* value conversion */
+
+ switch (aOut.mType) {
+ case PROPERTY_BDNAME:
+ /* fall through */
+ case PROPERTY_REMOTE_FRIENDLY_NAME:
+ {
+ // We construct an nsCString here because bdname
+ // returned from Bluedroid is not 0-terminated.
+ aOut.mString = NS_ConvertUTF8toUTF16(
+ nsCString(static_cast(aIn.val), aIn.len));
+ }
+ break;
+ case PROPERTY_BDADDR:
+ rv = Convert(*static_cast(aIn.val), aOut.mString);
+ break;
+ case PROPERTY_UUIDS:
+ {
+ size_t numUuids = aIn.len / MAX_UUID_SIZE;
+ ConvertArray array(
+ static_cast(aIn.val), numUuids);
+ aOut.mUuidArray.SetLength(numUuids);
+ rv = Convert(array, aOut.mUuidArray);
+ }
+ break;
+ case PROPERTY_CLASS_OF_DEVICE:
+ /* fall through */
+ case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
+ aOut.mUint32 = *static_cast(aIn.val);
+ break;
+ case PROPERTY_TYPE_OF_DEVICE:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mDeviceType);
+ break;
+ case PROPERTY_SERVICE_RECORD:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mServiceRecord);
+ break;
+ case PROPERTY_ADAPTER_SCAN_MODE:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mScanMode);
+ break;
+ case PROPERTY_ADAPTER_BONDED_DEVICES:
+ {
+ size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES;
+ ConvertArray array(
+ static_cast(aIn.val), numAddresses);
+ aOut.mStringArray.SetLength(numAddresses);
+ rv = Convert(array, aOut.mStringArray);
+ }
+ break;
+ case PROPERTY_REMOTE_RSSI:
+ aOut.mInt32 = *static_cast(aIn.val);
+ break;
+#if ANDROID_VERSION >= 18
+ case PROPERTY_REMOTE_VERSION_INFO:
+ rv = Convert(*static_cast(aIn.val),
+ aOut.mRemoteInfo);
+ break;
+#endif
+ case PROPERTY_REMOTE_DEVICE_TIMESTAMP:
+ /* nothing to do */
+ break;
+ default:
+ /* mismatch with type conversion */
+ NS_NOTREACHED("Unhandled property type");
+ break;
+ }
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+}
+
+END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothHALHelpers.h b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h
new file mode 100644
index 000000000000..a3db9504fa5b
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothHALHelpers.h
@@ -0,0 +1,1439 @@
+/* -*- 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_bluetoothhalhelpers_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothhalhelpers_h__
+
+#include
+#include
+#include
+#include
+#if ANDROID_VERSION >= 18
+#include
+#endif
+#include "BluetoothCommon.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/dom/bluetooth/BluetoothTypes.h"
+#include "nsThreadUtils.h"
+
+#if MOZ_IS_GCC && MOZ_GCC_VERSION_AT_LEAST(4, 7, 0)
+/* use designated array initializers if supported */
+#define CONVERT(in_, out_) \
+ [in_] = out_
+#else
+/* otherwise init array element by position */
+#define CONVERT(in_, out_) \
+ out_
+#endif
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// Conversion
+//
+
+inline nsresult
+Convert(bt_status_t aIn, BluetoothStatus& aOut)
+{
+ static const BluetoothStatus sStatus[] = {
+ CONVERT(BT_STATUS_SUCCESS, STATUS_SUCCESS),
+ CONVERT(BT_STATUS_FAIL, STATUS_FAIL),
+ CONVERT(BT_STATUS_NOT_READY, STATUS_NOT_READY),
+ CONVERT(BT_STATUS_NOMEM, STATUS_NOMEM),
+ CONVERT(BT_STATUS_BUSY, STATUS_BUSY),
+ CONVERT(BT_STATUS_DONE, STATUS_DONE),
+ CONVERT(BT_STATUS_UNSUPPORTED, STATUS_UNSUPPORTED),
+ CONVERT(BT_STATUS_PARM_INVALID, STATUS_PARM_INVALID),
+ CONVERT(BT_STATUS_UNHANDLED, STATUS_UNHANDLED),
+ CONVERT(BT_STATUS_AUTH_FAILURE, STATUS_AUTH_FAILURE),
+ CONVERT(BT_STATUS_RMT_DEV_DOWN, STATUS_RMT_DEV_DOWN)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sStatus[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(int aIn, BluetoothStatus& aOut)
+{
+ return Convert(static_cast(aIn), aOut);
+}
+
+nsresult
+Convert(const nsAString& aIn, bt_property_type_t& aOut);
+
+inline nsresult
+Convert(bool aIn, bt_scan_mode_t& aOut)
+{
+ static const bt_scan_mode_t sScanMode[] = {
+ CONVERT(false, BT_SCAN_MODE_CONNECTABLE),
+ CONVERT(true, BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sScanMode[aIn];
+ return NS_OK;
+}
+
+
+inline nsresult
+Convert(bt_scan_mode_t aIn, BluetoothScanMode& aOut)
+{
+ static const BluetoothScanMode sScanMode[] = {
+ CONVERT(BT_SCAN_MODE_NONE, SCAN_MODE_NONE),
+ CONVERT(BT_SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE),
+ CONVERT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE,
+ SCAN_MODE_CONNECTABLE_DISCOVERABLE)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sScanMode[aIn];
+ return NS_OK;
+}
+
+struct ConvertNamedValue
+{
+ ConvertNamedValue(const BluetoothNamedValue& aNamedValue)
+ : mNamedValue(aNamedValue)
+ { }
+
+ const BluetoothNamedValue& mNamedValue;
+
+ // temporary fields
+ nsCString mStringValue;
+ bt_scan_mode_t mScanMode;
+};
+
+nsresult
+Convert(ConvertNamedValue& aIn, bt_property_t& aOut);
+
+nsresult
+Convert(const nsAString& aIn, bt_bdaddr_t& aOut);
+
+nsresult
+Convert(const nsAString& aIn, bt_ssp_variant_t& aOut);
+
+inline nsresult
+Convert(const bt_ssp_variant_t& aIn, nsAString& aOut)
+{
+ static const char * const sSspVariant[] = {
+ CONVERT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION, "PasskeyConfirmation"),
+ CONVERT(BT_SSP_VARIANT_PASSKEY_ENTRY, "PasskeyEntry"),
+ CONVERT(BT_SSP_VARIANT_CONSENT, "Consent"),
+ CONVERT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION, "PasskeyNotification")
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = NS_ConvertUTF8toUTF16(sSspVariant[aIn]);
+ return NS_OK;
+}
+
+inline nsresult
+Convert(const bool& aIn, uint8_t& aOut)
+{
+ // casting converts true/false to either 1 or 0
+ aOut = static_cast(aIn);
+ return NS_OK;
+}
+
+nsresult
+Convert(const uint8_t aIn[16], bt_uuid_t& aOut);
+
+nsresult
+Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut);
+
+nsresult
+Convert(const nsAString& aIn, bt_pin_code_t& aOut);
+
+nsresult
+Convert(const bt_bdaddr_t& aIn, nsAString& aOut);
+
+inline nsresult
+Convert(const bt_bdaddr_t* aIn, nsAString& aOut)
+{
+ if (!aIn) {
+ aOut.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
+ return NS_OK;
+ }
+ return Convert(*aIn, aOut);
+}
+
+inline nsresult
+Convert(bt_state_t aIn, bool& aOut)
+{
+ static const bool sState[] = {
+ CONVERT(BT_STATE_OFF, false),
+ CONVERT(BT_STATE_ON, true)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bt_property_type_t aIn, BluetoothPropertyType& aOut)
+{
+ static const BluetoothPropertyType sPropertyType[] = {
+ CONVERT(0, static_cast(0)), // invalid, required by gcc
+ CONVERT(BT_PROPERTY_BDNAME, PROPERTY_BDNAME),
+ CONVERT(BT_PROPERTY_BDADDR, PROPERTY_BDADDR),
+ CONVERT(BT_PROPERTY_UUIDS, PROPERTY_UUIDS),
+ CONVERT(BT_PROPERTY_CLASS_OF_DEVICE, PROPERTY_CLASS_OF_DEVICE),
+ CONVERT(BT_PROPERTY_TYPE_OF_DEVICE, PROPERTY_TYPE_OF_DEVICE),
+ CONVERT(BT_PROPERTY_SERVICE_RECORD, PROPERTY_SERVICE_RECORD),
+ CONVERT(BT_PROPERTY_ADAPTER_SCAN_MODE, PROPERTY_ADAPTER_SCAN_MODE),
+ CONVERT(BT_PROPERTY_ADAPTER_BONDED_DEVICES,
+ PROPERTY_ADAPTER_BONDED_DEVICES),
+ CONVERT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
+ PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
+ CONVERT(BT_PROPERTY_REMOTE_FRIENDLY_NAME, PROPERTY_REMOTE_FRIENDLY_NAME),
+ CONVERT(BT_PROPERTY_REMOTE_RSSI, PROPERTY_REMOTE_RSSI),
+ CONVERT(BT_PROPERTY_REMOTE_VERSION_INFO,PROPERTY_REMOTE_VERSION_INFO)
+ };
+ if (aIn == BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP) {
+ /* This case is handled separately to not populate
+ * |sPropertyType| with empty entries. */
+ aOut = PROPERTY_REMOTE_DEVICE_TIMESTAMP;
+ return NS_OK;
+ }
+ if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPropertyType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sPropertyType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bt_discovery_state_t aIn, bool& aOut)
+{
+ static const bool sDiscoveryState[] = {
+ CONVERT(BT_DISCOVERY_STOPPED, false),
+ CONVERT(BT_DISCOVERY_STARTED, true)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sDiscoveryState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sDiscoveryState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(const char* aIn, nsACString& aOut)
+{
+ aOut.Assign(aIn);
+
+ return NS_OK;
+}
+
+inline nsresult
+Convert(const char* aIn, nsAString& aOut)
+{
+ aOut = NS_ConvertUTF8toUTF16(aIn);
+
+ return NS_OK;
+}
+
+inline nsresult
+Convert(const bt_bdname_t& aIn, nsAString& aOut)
+{
+ return Convert(reinterpret_cast(aIn.name), aOut);
+}
+
+inline nsresult
+Convert(const bt_bdname_t* aIn, nsAString& aOut)
+{
+ if (!aIn) {
+ aOut.Truncate();
+ return NS_OK;
+ }
+ return Convert(*aIn, aOut);
+}
+
+inline nsresult
+Convert(bt_bond_state_t aIn, BluetoothBondState& aOut)
+{
+ static const BluetoothBondState sBondState[] = {
+ CONVERT(BT_BOND_STATE_NONE, BOND_STATE_NONE),
+ CONVERT(BT_BOND_STATE_BONDING, BOND_STATE_BONDING),
+ CONVERT(BT_BOND_STATE_BONDED, BOND_STATE_BONDED)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sBondState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sBondState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bt_acl_state_t aIn, bool& aOut)
+{
+ static const bool sAclState[] = {
+ CONVERT(BT_ACL_STATE_CONNECTED, true),
+ CONVERT(BT_ACL_STATE_DISCONNECTED, false)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sAclState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sAclState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bt_device_type_t aIn, BluetoothDeviceType& aOut)
+{
+ static const BluetoothDeviceType sDeviceType[] = {
+ CONVERT(0, static_cast(0)), // invalid, required by gcc
+ CONVERT(BT_DEVICE_DEVTYPE_BREDR, DEVICE_TYPE_BREDR),
+ CONVERT(BT_DEVICE_DEVTYPE_BLE, DEVICE_TYPE_BLE),
+ CONVERT(BT_DEVICE_DEVTYPE_DUAL, DEVICE_TYPE_DUAL)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sDeviceType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sDeviceType[aIn];
+ return NS_OK;
+}
+
+nsresult
+Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut);
+
+inline nsresult
+Convert(BluetoothSocketType aIn, btsock_type_t& aOut)
+{
+ // FIXME: Array member [0] is currently invalid, but required
+ // by gcc. Start values in |BluetoothSocketType| at index
+ // 0 to fix this problem.
+ static const btsock_type_t sSocketType[] = {
+ CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
+ CONVERT(BluetoothSocketType::RFCOMM, BTSOCK_RFCOMM),
+ CONVERT(BluetoothSocketType::SCO, BTSOCK_SCO),
+ CONVERT(BluetoothSocketType::L2CAP, BTSOCK_L2CAP),
+ // EL2CAP is not supported by Bluedroid
+ };
+ if (aIn == BluetoothSocketType::EL2CAP ||
+ aIn >= MOZ_ARRAY_LENGTH(sSocketType) || !sSocketType[aIn]) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sSocketType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeAtResponse aIn, bthf_at_response_t& aOut)
+{
+ static const bthf_at_response_t sAtResponse[] = {
+ CONVERT(HFP_AT_RESPONSE_ERROR, BTHF_AT_RESPONSE_ERROR),
+ CONVERT(HFP_AT_RESPONSE_OK, BTHF_AT_RESPONSE_OK)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sAtResponse)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sAtResponse[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeCallAddressType aIn, bthf_call_addrtype_t& aOut)
+{
+ static const bthf_call_addrtype_t sCallAddressType[] = {
+ CONVERT(HFP_CALL_ADDRESS_TYPE_UNKNOWN, BTHF_CALL_ADDRTYPE_UNKNOWN),
+ CONVERT(HFP_CALL_ADDRESS_TYPE_INTERNATIONAL,
+ BTHF_CALL_ADDRTYPE_INTERNATIONAL)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sCallAddressType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sCallAddressType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeCallDirection aIn, bthf_call_direction_t& aOut)
+{
+ static const bthf_call_direction_t sCallDirection[] = {
+ CONVERT(HFP_CALL_DIRECTION_OUTGOING, BTHF_CALL_DIRECTION_OUTGOING),
+ CONVERT(HFP_CALL_DIRECTION_INCOMING, BTHF_CALL_DIRECTION_INCOMING)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sCallDirection)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sCallDirection[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeCallMode aIn, bthf_call_mode_t& aOut)
+{
+ static const bthf_call_mode_t sCallMode[] = {
+ CONVERT(HFP_CALL_MODE_VOICE, BTHF_CALL_TYPE_VOICE),
+ CONVERT(HFP_CALL_MODE_DATA, BTHF_CALL_TYPE_DATA),
+ CONVERT(HFP_CALL_MODE_FAX, BTHF_CALL_TYPE_FAX)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sCallMode)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sCallMode[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeCallMptyType aIn, bthf_call_mpty_type_t& aOut)
+{
+ static const bthf_call_mpty_type_t sCallMptyType[] = {
+ CONVERT(HFP_CALL_MPTY_TYPE_SINGLE, BTHF_CALL_MPTY_TYPE_SINGLE),
+ CONVERT(HFP_CALL_MPTY_TYPE_MULTI, BTHF_CALL_MPTY_TYPE_MULTI)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sCallMptyType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sCallMptyType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeCallState aIn, bthf_call_state_t& aOut)
+{
+ static const bthf_call_state_t sCallState[] = {
+ CONVERT(HFP_CALL_STATE_ACTIVE, BTHF_CALL_STATE_ACTIVE),
+ CONVERT(HFP_CALL_STATE_HELD, BTHF_CALL_STATE_HELD),
+ CONVERT(HFP_CALL_STATE_DIALING, BTHF_CALL_STATE_DIALING),
+ CONVERT(HFP_CALL_STATE_ALERTING, BTHF_CALL_STATE_ALERTING),
+ CONVERT(HFP_CALL_STATE_INCOMING, BTHF_CALL_STATE_INCOMING),
+ CONVERT(HFP_CALL_STATE_WAITING, BTHF_CALL_STATE_WAITING),
+ CONVERT(HFP_CALL_STATE_IDLE, BTHF_CALL_STATE_IDLE)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sCallState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sCallState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeNetworkState aIn, bthf_network_state_t& aOut)
+{
+ static const bthf_network_state_t sNetworkState[] = {
+ CONVERT(HFP_NETWORK_STATE_NOT_AVAILABLE, BTHF_NETWORK_STATE_NOT_AVAILABLE),
+ CONVERT(HFP_NETWORK_STATE_AVAILABLE, BTHF_NETWORK_STATE_AVAILABLE)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sNetworkState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sNetworkState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeServiceType aIn, bthf_service_type_t& aOut)
+{
+ static const bthf_service_type_t sServiceType[] = {
+ CONVERT(HFP_SERVICE_TYPE_HOME, BTHF_SERVICE_TYPE_HOME),
+ CONVERT(HFP_SERVICE_TYPE_ROAMING, BTHF_SERVICE_TYPE_ROAMING)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sServiceType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sServiceType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(BluetoothHandsfreeVolumeType aIn, bthf_volume_type_t& aOut)
+{
+ static const bthf_volume_type_t sVolumeType[] = {
+ CONVERT(HFP_VOLUME_TYPE_SPEAKER, BTHF_VOLUME_TYPE_SPK),
+ CONVERT(HFP_VOLUME_TYPE_MICROPHONE, BTHF_VOLUME_TYPE_MIC)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sVolumeType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bthf_audio_state_t aIn, BluetoothHandsfreeAudioState& aOut)
+{
+ static const BluetoothHandsfreeAudioState sAudioState[] = {
+ CONVERT(BTHF_AUDIO_STATE_DISCONNECTED, HFP_AUDIO_STATE_DISCONNECTED),
+ CONVERT(BTHF_AUDIO_STATE_CONNECTING, HFP_AUDIO_STATE_CONNECTING),
+ CONVERT(BTHF_AUDIO_STATE_CONNECTED, HFP_AUDIO_STATE_CONNECTED),
+ CONVERT(BTHF_AUDIO_STATE_DISCONNECTING, HFP_AUDIO_STATE_DISCONNECTING)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sAudioState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bthf_chld_type_t aIn, BluetoothHandsfreeCallHoldType& aOut)
+{
+ static const BluetoothHandsfreeCallHoldType sCallHoldType[] = {
+ CONVERT(BTHF_CHLD_TYPE_RELEASEHELD, HFP_CALL_HOLD_RELEASEHELD),
+ CONVERT(BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD,
+ HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD),
+ CONVERT(BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD,
+ HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD),
+ CONVERT(BTHF_CHLD_TYPE_ADDHELDTOCONF, HFP_CALL_HOLD_ADDHELDTOCONF)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sCallHoldType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sCallHoldType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bthf_connection_state_t aIn, BluetoothHandsfreeConnectionState& aOut)
+{
+ static const BluetoothHandsfreeConnectionState sConnectionState[] = {
+ CONVERT(BTHF_CONNECTION_STATE_DISCONNECTED,
+ HFP_CONNECTION_STATE_DISCONNECTED),
+ CONVERT(BTHF_CONNECTION_STATE_CONNECTING, HFP_CONNECTION_STATE_CONNECTING),
+ CONVERT(BTHF_CONNECTION_STATE_CONNECTED, HFP_CONNECTION_STATE_CONNECTED),
+ CONVERT(BTHF_CONNECTION_STATE_SLC_CONNECTED,
+ HFP_CONNECTION_STATE_SLC_CONNECTED),
+ CONVERT(BTHF_CONNECTION_STATE_DISCONNECTING,
+ HFP_CONNECTION_STATE_DISCONNECTING)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sConnectionState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bthf_nrec_t aIn, BluetoothHandsfreeNRECState& aOut)
+{
+ static const BluetoothHandsfreeNRECState sNRECState[] = {
+ CONVERT(BTHF_NREC_STOP, HFP_NREC_STOPPED),
+ CONVERT(BTHF_NREC_START, HFP_NREC_STARTED)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sNRECState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sNRECState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bthf_vr_state_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut)
+{
+ static const BluetoothHandsfreeVoiceRecognitionState
+ sVoiceRecognitionState[] = {
+ CONVERT(BTHF_VR_STATE_STOPPED, HFP_VOICE_RECOGNITION_STOPPED),
+ CONVERT(BTHF_VR_STATE_STARTED, HFP_VOICE_RECOGNITION_STARTED)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sVoiceRecognitionState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sVoiceRecognitionState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(bthf_volume_type_t aIn, BluetoothHandsfreeVolumeType& aOut)
+{
+ static const BluetoothHandsfreeVolumeType sVolumeType[] = {
+ CONVERT(BTHF_VOLUME_TYPE_SPK, HFP_VOLUME_TYPE_SPEAKER),
+ CONVERT(BTHF_VOLUME_TYPE_MIC, HFP_VOLUME_TYPE_MICROPHONE)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sVolumeType[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(btav_connection_state_t aIn, BluetoothA2dpConnectionState& aOut)
+{
+ static const BluetoothA2dpConnectionState sConnectionState[] = {
+ CONVERT(BTAV_CONNECTION_STATE_DISCONNECTED,
+ A2DP_CONNECTION_STATE_DISCONNECTED),
+ CONVERT(BTAV_CONNECTION_STATE_CONNECTING,
+ A2DP_CONNECTION_STATE_CONNECTING),
+ CONVERT(BTAV_CONNECTION_STATE_CONNECTED,
+ A2DP_CONNECTION_STATE_CONNECTED),
+ CONVERT(BTAV_CONNECTION_STATE_DISCONNECTING,
+ A2DP_CONNECTION_STATE_DISCONNECTING),
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sConnectionState[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(btav_audio_state_t aIn, BluetoothA2dpAudioState& aOut)
+{
+ static const BluetoothA2dpAudioState sAudioState[] = {
+ CONVERT(BTAV_AUDIO_STATE_REMOTE_SUSPEND, A2DP_AUDIO_STATE_REMOTE_SUSPEND),
+ CONVERT(BTAV_AUDIO_STATE_STOPPED, A2DP_AUDIO_STATE_STOPPED),
+ CONVERT(BTAV_AUDIO_STATE_STARTED, A2DP_AUDIO_STATE_STARTED),
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sAudioState[aIn];
+ return NS_OK;
+}
+
+#if ANDROID_VERSION >= 18
+inline nsresult
+Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut)
+{
+ aOut.mVerMajor = aIn.version;
+ aOut.mVerMinor = aIn.sub_ver;
+ aOut.mManufacturer = aIn.manufacturer;
+
+ return NS_OK;
+}
+
+inline nsresult
+Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut)
+{
+ static const btrc_play_status_t sPlayStatus[] = {
+ CONVERT(PLAYSTATUS_STOPPED, BTRC_PLAYSTATE_STOPPED),
+ CONVERT(PLAYSTATUS_PLAYING, BTRC_PLAYSTATE_PLAYING),
+ CONVERT(PLAYSTATUS_PAUSED, BTRC_PLAYSTATE_PAUSED),
+ CONVERT(PLAYSTATUS_FWD_SEEK, BTRC_PLAYSTATE_FWD_SEEK),
+ CONVERT(PLAYSTATUS_REV_SEEK, BTRC_PLAYSTATE_REV_SEEK)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sPlayStatus)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sPlayStatus[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(enum BluetoothAvrcpPlayerAttribute aIn, btrc_player_attr_t& aOut)
+{
+ static const btrc_player_attr_t sPlayerAttr[] = {
+ CONVERT(AVRCP_PLAYER_ATTRIBUTE_EQUALIZER, BTRC_PLAYER_ATTR_EQUALIZER),
+ CONVERT(AVRCP_PLAYER_ATTRIBUTE_REPEAT, BTRC_PLAYER_ATTR_REPEAT),
+ CONVERT(AVRCP_PLAYER_ATTRIBUTE_SHUFFLE, BTRC_PLAYER_ATTR_SHUFFLE),
+ CONVERT(AVRCP_PLAYER_ATTRIBUTE_SCAN, BTRC_PLAYER_ATTR_SCAN)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sPlayerAttr[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(btrc_player_attr_t aIn, enum BluetoothAvrcpPlayerAttribute& aOut)
+{
+ static const BluetoothAvrcpPlayerAttribute sPlayerAttr[] = {
+ CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
+ CONVERT(BTRC_PLAYER_ATTR_EQUALIZER, AVRCP_PLAYER_ATTRIBUTE_EQUALIZER),
+ CONVERT(BTRC_PLAYER_ATTR_REPEAT, AVRCP_PLAYER_ATTRIBUTE_REPEAT),
+ CONVERT(BTRC_PLAYER_ATTR_SHUFFLE, AVRCP_PLAYER_ATTRIBUTE_SHUFFLE),
+ CONVERT(BTRC_PLAYER_ATTR_SCAN, AVRCP_PLAYER_ATTRIBUTE_SCAN)
+ };
+ if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sPlayerAttr[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(enum BluetoothAvrcpStatus aIn, btrc_status_t& aOut)
+{
+ static const btrc_status_t sStatus[] = {
+ CONVERT(AVRCP_STATUS_BAD_COMMAND, BTRC_STS_BAD_CMD),
+ CONVERT(AVRCP_STATUS_BAD_PARAMETER, BTRC_STS_BAD_PARAM),
+ CONVERT(AVRCP_STATUS_NOT_FOUND, BTRC_STS_NOT_FOUND),
+ CONVERT(AVRCP_STATUS_INTERNAL_ERROR, BTRC_STS_INTERNAL_ERR),
+ CONVERT(AVRCP_STATUS_SUCCESS, BTRC_STS_NO_ERROR)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sStatus[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(enum BluetoothAvrcpEvent aIn, btrc_event_id_t& aOut)
+{
+ static const btrc_event_id_t sEventId[] = {
+ CONVERT(AVRCP_EVENT_PLAY_STATUS_CHANGED, BTRC_EVT_PLAY_STATUS_CHANGED),
+ CONVERT(AVRCP_EVENT_TRACK_CHANGE, BTRC_EVT_TRACK_CHANGE),
+ CONVERT(AVRCP_EVENT_TRACK_REACHED_END, BTRC_EVT_TRACK_REACHED_END),
+ CONVERT(AVRCP_EVENT_TRACK_REACHED_START, BTRC_EVT_TRACK_REACHED_START),
+ CONVERT(AVRCP_EVENT_PLAY_POS_CHANGED, BTRC_EVT_PLAY_POS_CHANGED),
+ CONVERT(AVRCP_EVENT_APP_SETTINGS_CHANGED, BTRC_EVT_APP_SETTINGS_CHANGED)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sEventId)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sEventId[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(btrc_event_id_t aIn, enum BluetoothAvrcpEvent& aOut)
+{
+ static const BluetoothAvrcpEvent sEventId[] = {
+ CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
+ CONVERT(BTRC_EVT_PLAY_STATUS_CHANGED, AVRCP_EVENT_PLAY_STATUS_CHANGED),
+ CONVERT(BTRC_EVT_TRACK_CHANGE, AVRCP_EVENT_TRACK_CHANGE),
+ CONVERT(BTRC_EVT_TRACK_REACHED_END, AVRCP_EVENT_TRACK_REACHED_END),
+ CONVERT(BTRC_EVT_TRACK_REACHED_START, AVRCP_EVENT_TRACK_REACHED_START),
+ CONVERT(BTRC_EVT_PLAY_POS_CHANGED, AVRCP_EVENT_PLAY_POS_CHANGED),
+ CONVERT(6, static_cast(0)), // invalid, [6] required by gcc
+ CONVERT(7, static_cast(0)), // invalid, [7] required by gcc
+ CONVERT(BTRC_EVT_APP_SETTINGS_CHANGED, AVRCP_EVENT_APP_SETTINGS_CHANGED)
+ };
+ if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sEventId[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(btrc_media_attr_t aIn, enum BluetoothAvrcpMediaAttribute& aOut)
+{
+ static const BluetoothAvrcpMediaAttribute sEventId[] = {
+ CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
+ CONVERT(BTRC_MEDIA_ATTR_TITLE, AVRCP_MEDIA_ATTRIBUTE_TITLE),
+ CONVERT(BTRC_MEDIA_ATTR_ARTIST, AVRCP_MEDIA_ATTRIBUTE_ARTIST),
+ CONVERT(BTRC_MEDIA_ATTR_ALBUM, AVRCP_MEDIA_ATTRIBUTE_ALBUM),
+ CONVERT(BTRC_MEDIA_ATTR_TRACK_NUM, AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM),
+ CONVERT(BTRC_MEDIA_ATTR_NUM_TRACKS, AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS),
+ CONVERT(BTRC_MEDIA_ATTR_GENRE, AVRCP_MEDIA_ATTRIBUTE_GENRE),
+ CONVERT(BTRC_MEDIA_ATTR_PLAYING_TIME, AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME)
+ };
+ if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sEventId[aIn];
+ return NS_OK;
+}
+
+inline nsresult
+Convert(enum BluetoothAvrcpNotification aIn, btrc_notification_type_t& aOut)
+{
+ static const btrc_notification_type_t sNotificationType[] = {
+ CONVERT(AVRCP_NTF_INTERIM, BTRC_NOTIFICATION_TYPE_INTERIM),
+ CONVERT(AVRCP_NTF_CHANGED, BTRC_NOTIFICATION_TYPE_CHANGED)
+ };
+ if (aIn >= MOZ_ARRAY_LENGTH(sNotificationType)) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ aOut = sNotificationType[aIn];
+ return NS_OK;
+}
+
+nsresult
+Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut);
+
+nsresult
+Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut);
+#endif // ANDROID_VERSION >= 18
+
+#if ANDROID_VERSION >= 19
+inline nsresult
+Convert(btrc_remote_features_t aIn, unsigned long& aOut)
+{
+ /* The input type's name is misleading. The converted value is
+ * actually a bitmask.
+ */
+ aOut = static_cast(aIn);
+ return NS_OK;
+}
+#endif // ANDROID_VERSION >= 19
+
+/* |ConvertArray| is a helper for converting arrays. Pass an
+ * instance of this structure as the first argument to |Convert|
+ * to convert an array. The output type has to support the array
+ * subscript operator.
+ */
+template
+struct ConvertArray
+{
+ ConvertArray(const T* aData, unsigned long aLength)
+ : mData(aData)
+ , mLength(aLength)
+ { }
+
+ const T* mData;
+ unsigned long mLength;
+};
+
+/* This implementation of |Convert| converts the elements of an
+ * array one-by-one. The result data structures must have enough
+ * memory allocated.
+ */
+template
+inline nsresult
+Convert(const ConvertArray& aIn, Tout& aOut)
+{
+ for (unsigned long i = 0; i < aIn.mLength; ++i) {
+ nsresult rv = Convert(aIn.mData[i], aOut[i]);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ return NS_OK;
+}
+
+/* This implementation of |Convert| is a helper that automatically
+ * allocates enough memory to hold the conversion results. The
+ * actual conversion is performed by the array-conversion helper
+ * above.
+ */
+template
+inline nsresult
+Convert(const ConvertArray& aIn, nsAutoArrayPtr& aOut)
+{
+ aOut = new Tout[aIn.mLength];
+ Tout* out = aOut.get();
+
+ return Convert(aIn, out);
+}
+
+/* |ConvertDefault| is a helper function to return the result of a
+ * conversion or a default value if the conversion fails.
+ */
+template
+inline Tout
+ConvertDefault(const Tin& aIn, const Tout& aDefault)
+{
+ Tout out = aDefault; // assignment silences compiler warning
+ if (NS_FAILED(Convert(aIn, out))) {
+ return aDefault;
+ }
+ return out;
+}
+
+/* This implementation of |Convert| is a helper for copying the
+ * input value into the output value. It handles all cases that
+ * need no conversion.
+ */
+template
+inline nsresult
+Convert(const T& aIn, T& aOut)
+{
+ aOut = aIn;
+
+ return NS_OK;
+}
+
+nsresult
+Convert(const bt_property_t& aIn, BluetoothProperty& aOut);
+
+//
+// Result handling
+//
+
+template
+class BluetoothHALInterfaceRunnable0 : public nsRunnable
+{
+public:
+ BluetoothHALInterfaceRunnable0(Obj* aObj, Res (Obj::*aMethod)())
+ : mObj(aObj)
+ , mMethod(aMethod)
+ {
+ MOZ_ASSERT(mObj);
+ MOZ_ASSERT(mMethod);
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ ((*mObj).*mMethod)();
+ return NS_OK;
+ }
+
+private:
+ nsRefPtr mObj;
+ void (Obj::*mMethod)();
+};
+
+template
+class BluetoothHALInterfaceRunnable1 : public nsRunnable
+{
+public:
+ BluetoothHALInterfaceRunnable1(Obj* aObj, Res (Obj::*aMethod)(Arg1),
+ const Arg1& aArg1)
+ : mObj(aObj)
+ , mMethod(aMethod)
+ , mArg1(aArg1)
+ {
+ MOZ_ASSERT(mObj);
+ MOZ_ASSERT(mMethod);
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ ((*mObj).*mMethod)(mArg1);
+ return NS_OK;
+ }
+
+private:
+ nsRefPtr mObj;
+ Res (Obj::*mMethod)(Arg1);
+ Tin1 mArg1;
+};
+
+template
+class BluetoothHALInterfaceRunnable3 : public nsRunnable
+{
+public:
+ BluetoothHALInterfaceRunnable3(Obj* aObj,
+ Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
+ const Arg1& aArg1, const Arg2& aArg2,
+ const Arg3& aArg3)
+ : mObj(aObj)
+ , mMethod(aMethod)
+ , mArg1(aArg1)
+ , mArg2(aArg2)
+ , mArg3(aArg3)
+ {
+ MOZ_ASSERT(mObj);
+ MOZ_ASSERT(mMethod);
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ ((*mObj).*mMethod)(mArg1, mArg2, mArg3);
+ return NS_OK;
+ }
+
+private:
+ nsRefPtr mObj;
+ Res (Obj::*mMethod)(Arg1, Arg2, Arg3);
+ Tin1 mArg1;
+ Tin2 mArg2;
+ Tin3 mArg3;
+};
+
+//
+// Notification handling
+//
+
+template
+class BluetoothNotificationHALRunnable0 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationHALRunnable0 SelfType;
+
+ static already_AddRefed Create(Res (ObjectType::*aMethod)())
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ return runnable.forget();
+ }
+
+ static void
+ Dispatch(Res (ObjectType::*aMethod)())
+ {
+ nsRefPtr runnable = Create(aMethod);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationHALRunnable0::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_OVERRIDE
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ ObjectType* obj = ObjectWrapper::GetInstance();
+
+ if (!obj) {
+ BT_WARNING("Notification handler not initialized");
+ } else {
+ ((*obj).*mMethod)();
+ }
+ return NS_OK;
+ }
+
+private:
+ BluetoothNotificationHALRunnable0(Res (ObjectType::*aMethod)())
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ Res (ObjectType::*mMethod)();
+};
+
+template
+class BluetoothNotificationHALRunnable1 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationHALRunnable1 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationHALRunnable1::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_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:
+ BluetoothNotificationHALRunnable1(Res (ObjectType::*aMethod)(Arg1))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1);
+ Tin1 mArg1;
+};
+
+template
+class BluetoothNotificationHALRunnable2 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationHALRunnable2 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2), const T1& aIn1, const T2& aIn2)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2),
+ const T1& aIn1, const T2& aIn2)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1, aIn2);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationHALRunnable2::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_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:
+ BluetoothNotificationHALRunnable2(
+ Res (ObjectType::*aMethod)(Arg1, Arg2))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1, Arg2);
+ Tin1 mArg1;
+ Tin2 mArg2;
+};
+
+template
+class BluetoothNotificationHALRunnable3 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationHALRunnable3 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationHALRunnable3::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_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:
+ BluetoothNotificationHALRunnable3(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn3, mArg3);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ return NS_OK;
+ }
+
+ Res (ObjectType::*mMethod)(Arg1, Arg2, Arg3);
+ Tin1 mArg1;
+ Tin2 mArg2;
+ Tin3 mArg3;
+};
+
+template
+class BluetoothNotificationHALRunnable4 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationHALRunnable4 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
+ {
+ nsRefPtr runnable = Create(aMethod, aIn1, aIn2, aIn3, aIn4);
+
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationHALRunnable4::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_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:
+ BluetoothNotificationHALRunnable4(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2,
+ const T3& aIn3, const T4& aIn4)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn3, mArg3);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn4, 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
+class BluetoothNotificationHALRunnable5 : public nsRunnable
+{
+public:
+ typedef typename ObjectWrapper::ObjectType ObjectType;
+ typedef BluetoothNotificationHALRunnable5 SelfType;
+
+ template
+ static already_AddRefed Create(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3,
+ const T4& aIn4, const T5& aIn5)
+ {
+ nsRefPtr runnable(new SelfType(aMethod));
+
+ if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5))) {
+ return nullptr;
+ }
+ return runnable.forget();
+ }
+
+ template
+ static void
+ Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5),
+ const T1& aIn1, const T2& aIn2, const T3& aIn3,
+ const T4& aIn4, const T5& aIn5)
+ {
+ nsRefPtr runnable = Create(aMethod,
+ aIn1, aIn2, aIn3, aIn4, aIn5);
+ if (!runnable) {
+ BT_WARNING("BluetoothNotificationHALRunnable5::Create failed");
+ return;
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ }
+
+ NS_METHOD
+ Run() MOZ_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:
+ BluetoothNotificationHALRunnable5(
+ Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4, Arg5))
+ : mMethod(aMethod)
+ {
+ MOZ_ASSERT(mMethod);
+ }
+
+ template
+ nsresult
+ ConvertAndSet(const T1& aIn1, const T2& aIn2, const T3& aIn3,
+ const T4& aIn4, const T5& aIn5)
+ {
+ nsresult rv = Convert(aIn1, mArg1);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn2, mArg2);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn3, mArg3);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn4, mArg4);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ rv = Convert(aIn5, 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;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
diff --git a/dom/bluetooth/bluedroid/BluetoothHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothHALInterface.cpp
new file mode 100644
index 000000000000..e7527181e2e7
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothHALInterface.cpp
@@ -0,0 +1,913 @@
+/* -*- 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 "BluetoothHALInterface.h"
+#include "BluetoothHALHelpers.h"
+#include "BluetoothA2dpHALInterface.h"
+#include "BluetoothAvrcpHALInterface.h"
+#include "BluetoothHandsfreeHALInterface.h"
+#include "BluetoothSocketHALInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+template
+struct interface_traits
+{ };
+
+template<>
+struct interface_traits
+{
+ typedef const btsock_interface_t const_interface_type;
+
+ static const char* profile_id()
+ {
+ return BT_PROFILE_SOCKETS_ID;
+ }
+};
+
+template<>
+struct interface_traits
+{
+ typedef const bthf_interface_t const_interface_type;
+
+ static const char* profile_id()
+ {
+ return BT_PROFILE_HANDSFREE_ID;
+ }
+};
+
+template<>
+struct interface_traits
+{
+ typedef const btav_interface_t const_interface_type;
+
+ static const char* profile_id()
+ {
+ return BT_PROFILE_ADVANCED_AUDIO_ID;
+ }
+};
+
+#if ANDROID_VERSION >= 18
+template<>
+struct interface_traits
+{
+ typedef const btrc_interface_t const_interface_type;
+
+ static const char* profile_id()
+ {
+ return BT_PROFILE_AV_RC_ID;
+ }
+};
+#endif
+
+typedef
+ BluetoothHALInterfaceRunnable0
+ BluetoothHALResultRunnable;
+
+typedef
+ BluetoothHALInterfaceRunnable1
+ BluetoothHALErrorRunnable;
+
+static nsresult
+DispatchBluetoothHALResult(BluetoothResultHandler* aRes,
+ void (BluetoothResultHandler::*aMethod)(),
+ BluetoothStatus aStatus)
+{
+ MOZ_ASSERT(aRes);
+
+ nsRunnable* runnable;
+
+ if (aStatus == STATUS_SUCCESS) {
+ runnable = new BluetoothHALResultRunnable(aRes, aMethod);
+ } else {
+ runnable = new BluetoothHALErrorRunnable(
+ aRes, &BluetoothResultHandler::OnError, aStatus);
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ return rv;
+}
+
+// Notification handling
+//
+
+static BluetoothNotificationHandler* sNotificationHandler;
+
+struct BluetoothCallback
+{
+ class NotificationHandlerWrapper
+ {
+ public:
+ typedef BluetoothNotificationHandler ObjectType;
+
+ static ObjectType* GetInstance()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ return sNotificationHandler;
+ }
+ };
+
+ // Notifications
+
+ typedef BluetoothNotificationHALRunnable1
+ AdapterStateChangedNotification;
+
+ typedef BluetoothNotificationHALRunnable3,
+ BluetoothStatus, int,
+ const BluetoothProperty*>
+ AdapterPropertiesNotification;
+
+ typedef BluetoothNotificationHALRunnable4,
+ BluetoothStatus, const nsAString&,
+ int, const BluetoothProperty*>
+ RemoteDevicePropertiesNotification;
+
+ typedef BluetoothNotificationHALRunnable2,
+ int, const BluetoothProperty*>
+ DeviceFoundNotification;
+
+ typedef BluetoothNotificationHALRunnable1
+ DiscoveryStateChangedNotification;
+
+ typedef BluetoothNotificationHALRunnable3
+ PinRequestNotification;
+
+ typedef BluetoothNotificationHALRunnable5
+ SspRequestNotification;
+
+ typedef BluetoothNotificationHALRunnable3
+ BondStateChangedNotification;
+
+ typedef BluetoothNotificationHALRunnable3
+ AclStateChangedNotification;
+
+ typedef BluetoothNotificationHALRunnable3,
+ uint8_t, uint16_t, const uint8_t*>
+ DutModeRecvNotification;
+
+ typedef BluetoothNotificationHALRunnable2
+ LeTestModeNotification;
+
+ // Bluedroid callbacks
+
+ static const bt_property_t*
+ AlignedProperties(bt_property_t* aProperties, size_t aNumProperties,
+ nsAutoArrayPtr& aPropertiesArray)
+ {
+ // See Bug 989976: consider aProperties address is not aligned. If
+ // it is aligned, we return the pointer directly; otherwise we make
+ // an aligned copy. The argument |aPropertiesArray| keeps track of
+ // the memory buffer.
+ if (!(reinterpret_cast(aProperties) % sizeof(void*))) {
+ return aProperties;
+ }
+
+ bt_property_t* properties = new bt_property_t[aNumProperties];
+ memcpy(properties, aProperties, aNumProperties * sizeof(*properties));
+ aPropertiesArray = properties;
+
+ return properties;
+ }
+
+ static void
+ AdapterStateChanged(bt_state_t aStatus)
+ {
+ AdapterStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::AdapterStateChangedNotification,
+ aStatus);
+ }
+
+ static void
+ AdapterProperties(bt_status_t aStatus, int aNumProperties,
+ bt_property_t* aProperties)
+ {
+ nsAutoArrayPtr propertiesArray;
+
+ AdapterPropertiesNotification::Dispatch(
+ &BluetoothNotificationHandler::AdapterPropertiesNotification,
+ ConvertDefault(aStatus, STATUS_FAIL), aNumProperties,
+ ConvertArray(
+ AlignedProperties(aProperties, aNumProperties, propertiesArray),
+ aNumProperties));
+ }
+
+ static void
+ RemoteDeviceProperties(bt_status_t aStatus, bt_bdaddr_t* aBdAddress,
+ int aNumProperties, bt_property_t* aProperties)
+ {
+ nsAutoArrayPtr propertiesArray;
+
+ RemoteDevicePropertiesNotification::Dispatch(
+ &BluetoothNotificationHandler::RemoteDevicePropertiesNotification,
+ ConvertDefault(aStatus, STATUS_FAIL), aBdAddress, aNumProperties,
+ ConvertArray(
+ AlignedProperties(aProperties, aNumProperties, propertiesArray),
+ aNumProperties));
+ }
+
+ static void
+ DeviceFound(int aNumProperties, bt_property_t* aProperties)
+ {
+ nsAutoArrayPtr propertiesArray;
+
+ DeviceFoundNotification::Dispatch(
+ &BluetoothNotificationHandler::DeviceFoundNotification,
+ aNumProperties,
+ ConvertArray(
+ AlignedProperties(aProperties, aNumProperties, propertiesArray),
+ aNumProperties));
+ }
+
+ static void
+ DiscoveryStateChanged(bt_discovery_state_t aState)
+ {
+ DiscoveryStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::DiscoveryStateChangedNotification,
+ aState);
+ }
+
+ static void
+ PinRequest(bt_bdaddr_t* aRemoteBdAddress,
+ bt_bdname_t* aRemoteBdName, uint32_t aRemoteClass)
+ {
+ PinRequestNotification::Dispatch(
+ &BluetoothNotificationHandler::PinRequestNotification,
+ aRemoteBdAddress, aRemoteBdName, aRemoteClass);
+ }
+
+ static void
+ SspRequest(bt_bdaddr_t* aRemoteBdAddress, bt_bdname_t* aRemoteBdName,
+ uint32_t aRemoteClass, bt_ssp_variant_t aPairingVariant,
+ uint32_t aPasskey)
+ {
+ SspRequestNotification::Dispatch(
+ &BluetoothNotificationHandler::SspRequestNotification,
+ aRemoteBdAddress, aRemoteBdName, aRemoteClass,
+ aPairingVariant, aPasskey);
+ }
+
+ static void
+ BondStateChanged(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
+ bt_bond_state_t aState)
+ {
+ BondStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::BondStateChangedNotification,
+ aStatus, aRemoteBdAddress, aState);
+ }
+
+ static void
+ AclStateChanged(bt_status_t aStatus, bt_bdaddr_t* aRemoteBdAddress,
+ bt_acl_state_t aState)
+ {
+ AclStateChangedNotification::Dispatch(
+ &BluetoothNotificationHandler::AclStateChangedNotification,
+ aStatus, aRemoteBdAddress, aState);
+ }
+
+ static void
+ ThreadEvt(bt_cb_thread_evt evt)
+ {
+ // This callback maintains internal state and is not exported.
+ }
+
+ static void
+ DutModeRecv(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen)
+ {
+ DutModeRecvNotification::Dispatch(
+ &BluetoothNotificationHandler::DutModeRecvNotification,
+ aOpcode, ConvertArray(aBuf, aLen), aLen);
+ }
+
+ static void
+ LeTestMode(bt_status_t aStatus, uint16_t aNumPackets)
+ {
+ LeTestModeNotification::Dispatch(
+ &BluetoothNotificationHandler::LeTestModeNotification,
+ aStatus, aNumPackets);
+ }
+};
+
+// 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) ) )
+
+BluetoothHALInterface*
+BluetoothHALInterface::GetInstance()
+{
+ static BluetoothHALInterface* sBluetoothInterface;
+
+ if (sBluetoothInterface) {
+ return sBluetoothInterface;
+ }
+
+ /* get driver module */
+
+ const hw_module_t* module;
+ int err = hw_get_module(BT_HARDWARE_MODULE_ID, &module);
+ if (err) {
+ BT_WARNING("hw_get_module failed: %s", strerror(err));
+ return nullptr;
+ }
+
+ /* get device */
+
+ hw_device_t* device;
+ err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
+ if (err) {
+ BT_WARNING("open failed: %s", strerror(err));
+ return nullptr;
+ }
+
+ const bluetooth_device_t* bt_device =
+ container(bluetooth_device_t, device, common);
+
+ /* get interface */
+
+ const bt_interface_t* bt_interface = bt_device->get_bluetooth_interface();
+ if (!bt_interface) {
+ BT_WARNING("get_bluetooth_interface failed");
+ goto err_get_bluetooth_interface;
+ }
+
+ if (bt_interface->size != sizeof(*bt_interface)) {
+ BT_WARNING("interface of incorrect size");
+ goto err_bt_interface_size;
+ }
+
+ sBluetoothInterface = new BluetoothHALInterface(bt_interface);
+
+ return sBluetoothInterface;
+
+err_bt_interface_size:
+err_get_bluetooth_interface:
+ err = device->close(device);
+ if (err) {
+ BT_WARNING("close failed: %s", strerror(err));
+ }
+ return nullptr;
+}
+
+BluetoothHALInterface::BluetoothHALInterface(
+ const bt_interface_t* aInterface)
+: mInterface(aInterface)
+{
+ MOZ_ASSERT(mInterface);
+}
+
+BluetoothHALInterface::~BluetoothHALInterface()
+{ }
+
+void
+BluetoothHALInterface::Init(
+ BluetoothNotificationHandler* aNotificationHandler,
+ BluetoothResultHandler* aRes)
+{
+ static bt_callbacks_t sBluetoothCallbacks = {
+ sizeof(sBluetoothCallbacks),
+ BluetoothCallback::AdapterStateChanged,
+ BluetoothCallback::AdapterProperties,
+ BluetoothCallback::RemoteDeviceProperties,
+ BluetoothCallback::DeviceFound,
+ BluetoothCallback::DiscoveryStateChanged,
+ BluetoothCallback::PinRequest,
+ BluetoothCallback::SspRequest,
+ BluetoothCallback::BondStateChanged,
+ BluetoothCallback::AclStateChanged,
+ BluetoothCallback::ThreadEvt,
+ BluetoothCallback::DutModeRecv,
+#if ANDROID_VERSION >= 18
+ BluetoothCallback::LeTestMode
+#endif
+ };
+
+ sNotificationHandler = aNotificationHandler;
+
+ int status = mInterface->init(&sBluetoothCallbacks);
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Init,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::Cleanup(BluetoothResultHandler* aRes)
+{
+ mInterface->cleanup();
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Cleanup,
+ STATUS_SUCCESS);
+ }
+
+ sNotificationHandler = nullptr;
+}
+
+void
+BluetoothHALInterface::Enable(BluetoothResultHandler* aRes)
+{
+ int status = mInterface->enable();
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Enable,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::Disable(BluetoothResultHandler* aRes)
+{
+ int status = mInterface->disable();
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Disable,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Adapter Properties */
+
+void
+BluetoothHALInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
+{
+ int status = mInterface->get_adapter_properties();
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::GetAdapterProperties,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::GetAdapterProperty(const nsAString& aName,
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_property_type_t type;
+
+ /* FIXME: you need to implement the missing conversion functions */
+ NS_NOTREACHED("Conversion function missing");
+
+ if (false /* TODO: we don't support any values for aName currently */) {
+ status = mInterface->get_adapter_property(type);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::GetAdapterProperties,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::SetAdapterProperty(
+ const BluetoothNamedValue& aProperty, BluetoothResultHandler* aRes)
+{
+ int status;
+ ConvertNamedValue convertProperty(aProperty);
+ bt_property_t property;
+
+ if (NS_SUCCEEDED(Convert(convertProperty, property))) {
+ status = mInterface->set_adapter_property(&property);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::SetAdapterProperty,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Remote Device Properties */
+
+void
+BluetoothHALInterface::GetRemoteDeviceProperties(
+ const nsAString& aRemoteAddr, BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_bdaddr_t addr;
+
+ if (NS_SUCCEEDED(Convert(aRemoteAddr, addr))) {
+ status = mInterface->get_remote_device_properties(&addr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::GetRemoteDeviceProperties,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::GetRemoteDeviceProperty(
+ const nsAString& aRemoteAddr, const nsAString& aName,
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_bdaddr_t remoteAddr;
+ bt_property_type_t name;
+
+ /* FIXME: you need to implement the missing conversion functions */
+ NS_NOTREACHED("Conversion function missing");
+
+ if (NS_SUCCEEDED(Convert(aRemoteAddr, remoteAddr)) &&
+ false /* TODO: we don't support any values for aName currently */) {
+ status = mInterface->get_remote_device_property(&remoteAddr, name);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::GetRemoteDeviceProperty,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::SetRemoteDeviceProperty(
+ const nsAString& aRemoteAddr, const BluetoothNamedValue& aProperty,
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_bdaddr_t remoteAddr;
+ bt_property_t property;
+
+ /* FIXME: you need to implement the missing conversion functions */
+ NS_NOTREACHED("Conversion function missing");
+
+ if (NS_SUCCEEDED(Convert(aRemoteAddr, remoteAddr)) &&
+ false /* TODO: we don't support any values for aProperty currently */) {
+ status = mInterface->set_remote_device_property(&remoteAddr, &property);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::SetRemoteDeviceProperty,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Remote Services */
+
+void
+BluetoothHALInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr,
+ const uint8_t aUuid[16],
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_bdaddr_t remoteAddr;
+ bt_uuid_t uuid;
+
+ if (NS_SUCCEEDED(Convert(aRemoteAddr, remoteAddr)) &&
+ NS_SUCCEEDED(Convert(aUuid, uuid))) {
+ status = mInterface->get_remote_service_record(&remoteAddr, &uuid);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::GetRemoteServiceRecord,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::GetRemoteServices(const nsAString& aRemoteAddr,
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_bdaddr_t remoteAddr;
+
+ if (NS_SUCCEEDED(Convert(aRemoteAddr, remoteAddr))) {
+ status = mInterface->get_remote_services(&remoteAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::GetRemoteServices,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Discovery */
+
+void
+BluetoothHALInterface::StartDiscovery(BluetoothResultHandler* aRes)
+{
+ int status = mInterface->start_discovery();
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::StartDiscovery,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::CancelDiscovery(BluetoothResultHandler* aRes)
+{
+ int status = mInterface->cancel_discovery();
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::CancelDiscovery,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Bonds */
+
+void
+BluetoothHALInterface::CreateBond(const nsAString& aBdAddr,
+ BluetoothResultHandler* aRes)
+{
+ bt_bdaddr_t bdAddr;
+ int status;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->create_bond(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::CreateBond,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::RemoveBond(const nsAString& aBdAddr,
+ BluetoothResultHandler* aRes)
+{
+ bt_bdaddr_t bdAddr;
+ int status;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->remove_bond(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::RemoveBond,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::CancelBond(const nsAString& aBdAddr,
+ BluetoothResultHandler* aRes)
+{
+ bt_bdaddr_t bdAddr;
+ int status;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->cancel_bond(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::CancelBond,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Authentication */
+
+void
+BluetoothHALInterface::PinReply(const nsAString& aBdAddr, bool aAccept,
+ const nsAString& aPinCode,
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_bdaddr_t bdAddr;
+ uint8_t accept;
+ bt_pin_code_t pinCode;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) &&
+ NS_SUCCEEDED(Convert(aAccept, accept)) &&
+ NS_SUCCEEDED(Convert(aPinCode, pinCode))) {
+ status = mInterface->pin_reply(&bdAddr, accept, aPinCode.Length(),
+ &pinCode);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::PinReply,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::SspReply(const nsAString& aBdAddr,
+ const nsAString& aVariant,
+ bool aAccept, uint32_t aPasskey,
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ bt_bdaddr_t bdAddr;
+ bt_ssp_variant_t variant;
+ uint8_t accept;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) &&
+ NS_SUCCEEDED(Convert(aVariant, variant)) &&
+ NS_SUCCEEDED(Convert(aAccept, accept))) {
+ status = mInterface->ssp_reply(&bdAddr, variant, accept, aPasskey);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::SspReply,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* DUT Mode */
+
+void
+BluetoothHALInterface::DutModeConfigure(bool aEnable,
+ BluetoothResultHandler* aRes)
+{
+ int status;
+ uint8_t enable;
+
+ if (NS_SUCCEEDED(Convert(aEnable, enable))) {
+ status = mInterface->dut_mode_configure(enable);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::DutModeConfigure,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHALInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+ BluetoothResultHandler* aRes)
+{
+ int status = mInterface->dut_mode_send(aOpcode, aBuf, aLen);
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::DutModeSend,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* LE Mode */
+
+void
+BluetoothHALInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+ BluetoothResultHandler* aRes)
+{
+#if ANDROID_VERSION >= 18
+ int status = mInterface->le_test_mode(aOpcode, aBuf, aLen);
+#else
+ int status = BT_STATUS_UNSUPPORTED;
+#endif
+
+ if (aRes) {
+ DispatchBluetoothHALResult(aRes,
+ &BluetoothResultHandler::LeTestMode,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Profile Interfaces */
+
+template
+T*
+BluetoothHALInterface::CreateProfileInterface()
+{
+ typename interface_traits::const_interface_type* interface =
+ reinterpret_cast::const_interface_type*>(
+ mInterface->get_profile_interface(interface_traits::profile_id()));
+
+ if (!interface) {
+ BT_WARNING("Bluetooth profile '%s' is not supported",
+ interface_traits::profile_id());
+ return nullptr;
+ }
+
+ if (interface->size != sizeof(*interface)) {
+ BT_WARNING("interface of incorrect size");
+ return nullptr;
+ }
+
+ return new T(interface);
+}
+
+#if ANDROID_VERSION < 18
+/*
+ * Bluedroid versions that don't support AVRCP will call this function
+ * to create an AVRCP interface. All interface methods will fail with
+ * the error constant STATUS_UNSUPPORTED.
+ */
+template <>
+BluetoothAvrcpHALInterface*
+BluetoothHALInterface::CreateProfileInterface()
+{
+ BT_WARNING("Bluetooth profile 'avrcp' is not supported");
+
+ return new BluetoothAvrcpHALInterface();
+}
+#endif
+
+template
+T*
+BluetoothHALInterface::GetProfileInterface()
+{
+ static T* sBluetoothProfileInterface;
+
+ if (sBluetoothProfileInterface) {
+ return sBluetoothProfileInterface;
+ }
+
+ sBluetoothProfileInterface = CreateProfileInterface();
+
+ return sBluetoothProfileInterface;
+}
+
+BluetoothSocketInterface*
+BluetoothHALInterface::GetBluetoothSocketInterface()
+{
+ return GetProfileInterface();
+}
+
+BluetoothHandsfreeInterface*
+BluetoothHALInterface::GetBluetoothHandsfreeInterface()
+{
+ return GetProfileInterface();
+}
+
+BluetoothA2dpInterface*
+BluetoothHALInterface::GetBluetoothA2dpInterface()
+{
+ return GetProfileInterface();
+}
+
+BluetoothAvrcpInterface*
+BluetoothHALInterface::GetBluetoothAvrcpInterface()
+{
+ return GetProfileInterface();
+}
+
+END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothHALInterface.h b/dom/bluetooth/bluedroid/BluetoothHALInterface.h
new file mode 100644
index 000000000000..9c81eab79c7a
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothHALInterface.h
@@ -0,0 +1,110 @@
+/* -*- 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_bluetoothhalinterface_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothhalinterface_h__
+
+#include
+#include "BluetoothInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothHALInterface MOZ_FINAL : public BluetoothInterface
+{
+public:
+ static BluetoothHALInterface* 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();
+ BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface();
+ BluetoothA2dpInterface* GetBluetoothA2dpInterface();
+ BluetoothAvrcpInterface* GetBluetoothAvrcpInterface();
+
+protected:
+ BluetoothHALInterface(const bt_interface_t* aInterface);
+ ~BluetoothHALInterface();
+
+private:
+ template
+ T* CreateProfileInterface();
+
+ template
+ T* GetProfileInterface();
+
+ const bt_interface_t* mInterface;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
diff --git a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
new file mode 100644
index 000000000000..b996363d59b8
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.cpp
@@ -0,0 +1,616 @@
+/* -*- 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 "BluetoothHandsfreeHALInterface.h"
+#include "BluetoothHALHelpers.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+typedef
+ BluetoothHALInterfaceRunnable0
+ BluetoothHandsfreeHALResultRunnable;
+
+typedef
+ BluetoothHALInterfaceRunnable1
+ BluetoothHandsfreeHALErrorRunnable;
+
+static nsresult
+DispatchBluetoothHandsfreeHALResult(
+ BluetoothHandsfreeResultHandler* aRes,
+ void (BluetoothHandsfreeResultHandler::*aMethod)(),
+ BluetoothStatus aStatus)
+{
+ MOZ_ASSERT(aRes);
+
+ nsRunnable* runnable;
+
+ if (aStatus == STATUS_SUCCESS) {
+ runnable = new BluetoothHandsfreeHALResultRunnable(aRes, aMethod);
+ } else {
+ runnable = new BluetoothHandsfreeHALErrorRunnable(aRes,
+ &BluetoothHandsfreeResultHandler::OnError, aStatus);
+ }
+ nsresult rv = NS_DispatchToMainThread(runnable);
+ if (NS_FAILED(rv)) {
+ BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+ }
+ return rv;
+}
+
+// Notification handling
+//
+
+static BluetoothHandsfreeNotificationHandler* sHandsfreeNotificationHandler;
+
+struct BluetoothHandsfreeHALCallback
+{
+ class HandsfreeNotificationHandlerWrapper
+ {
+ public:
+ typedef BluetoothHandsfreeNotificationHandler ObjectType;
+
+ static ObjectType* GetInstance()
+ {
+ MOZ_ASSERT(NS_IsMainThread());
+
+ return sHandsfreeNotificationHandler;
+ }
+ };
+
+ // Notifications
+
+ typedef BluetoothNotificationHALRunnable2<
+ HandsfreeNotificationHandlerWrapper, void,
+ BluetoothHandsfreeConnectionState, nsString,
+ BluetoothHandsfreeConnectionState, const nsAString&>
+ ConnectionStateNotification;
+
+ typedef BluetoothNotificationHALRunnable2<
+ HandsfreeNotificationHandlerWrapper, void,
+ BluetoothHandsfreeAudioState, nsString,
+ BluetoothHandsfreeAudioState, const nsAString&>
+ AudioStateNotification;
+
+ typedef BluetoothNotificationHALRunnable1<
+ HandsfreeNotificationHandlerWrapper, void,
+ BluetoothHandsfreeVoiceRecognitionState>
+ VoiceRecognitionNotification;
+
+ typedef BluetoothNotificationHALRunnable0<
+ HandsfreeNotificationHandlerWrapper, void>
+ AnswerCallNotification;
+
+ typedef BluetoothNotificationHALRunnable0<
+ HandsfreeNotificationHandlerWrapper, void>
+ HangupCallNotification;
+
+ typedef BluetoothNotificationHALRunnable2<
+ HandsfreeNotificationHandlerWrapper, void,
+ BluetoothHandsfreeVolumeType, int>
+ VolumeNotification;
+
+ typedef BluetoothNotificationHALRunnable1<
+ HandsfreeNotificationHandlerWrapper, void, nsString, const nsAString&>
+ DialCallNotification;
+
+ typedef BluetoothNotificationHALRunnable1<
+ HandsfreeNotificationHandlerWrapper, void, char>
+ DtmfNotification;
+
+ typedef BluetoothNotificationHALRunnable1<
+ HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeNRECState>
+ NRECNotification;
+
+ typedef BluetoothNotificationHALRunnable1<
+ HandsfreeNotificationHandlerWrapper, void, BluetoothHandsfreeCallHoldType>
+ CallHoldNotification;
+
+ typedef BluetoothNotificationHALRunnable0<
+ HandsfreeNotificationHandlerWrapper, void>
+ CnumNotification;
+
+ typedef BluetoothNotificationHALRunnable0<
+ HandsfreeNotificationHandlerWrapper, void>
+ CindNotification;
+
+ typedef BluetoothNotificationHALRunnable0<
+ HandsfreeNotificationHandlerWrapper, void>
+ CopsNotification;
+
+ typedef BluetoothNotificationHALRunnable0<
+ HandsfreeNotificationHandlerWrapper, void>
+ ClccNotification;
+
+ typedef BluetoothNotificationHALRunnable1<
+ HandsfreeNotificationHandlerWrapper, void, nsCString, const nsACString&>
+ UnknownAtNotification;
+
+ typedef BluetoothNotificationHALRunnable0<
+ HandsfreeNotificationHandlerWrapper, void>
+ KeyPressedNotification;
+
+ // Bluedroid Handsfree callbacks
+
+ static void
+ ConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddr)
+ {
+ ConnectionStateNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification,
+ aState, aBdAddr);
+ }
+
+ static void
+ AudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddr)
+ {
+ AudioStateNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::AudioStateNotification,
+ aState, aBdAddr);
+ }
+
+ static void
+ VoiceRecognition(bthf_vr_state_t aState)
+ {
+ VoiceRecognitionNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification,
+ aState);
+ }
+
+ static void
+ AnswerCall()
+ {
+ AnswerCallNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::AnswerCallNotification);
+ }
+
+ static void
+ HangupCall()
+ {
+ HangupCallNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::HangupCallNotification);
+ }
+
+ static void
+ Volume(bthf_volume_type_t aType, int aVolume)
+ {
+ VolumeNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::VolumeNotification,
+ aType, aVolume);
+ }
+
+ static void
+ DialCall(char* aNumber)
+ {
+ DialCallNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::DialCallNotification, aNumber);
+ }
+
+ static void
+ Dtmf(char aDtmf)
+ {
+ DtmfNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::DtmfNotification, aDtmf);
+ }
+
+ static void
+ NoiseReductionEchoCancellation(bthf_nrec_t aNrec)
+ {
+ NRECNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::NRECNotification, aNrec);
+ }
+
+ static void
+ CallHold(bthf_chld_type_t aChld)
+ {
+ CallHoldNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::CallHoldNotification, aChld);
+ }
+
+ static void
+ Cnum()
+ {
+ CnumNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::CnumNotification);
+ }
+
+ static void
+ Cind()
+ {
+ CindNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::CindNotification);
+ }
+
+ static void
+ Cops()
+ {
+ CopsNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::CopsNotification);
+ }
+
+ static void
+ Clcc()
+ {
+ ClccNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::ClccNotification);
+ }
+
+ static void
+ UnknownAt(char* aAtString)
+ {
+ UnknownAtNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::UnknownAtNotification,
+ aAtString);
+ }
+
+ static void
+ KeyPressed()
+ {
+ KeyPressedNotification::Dispatch(
+ &BluetoothHandsfreeNotificationHandler::KeyPressedNotification);
+ }
+};
+
+// Interface
+//
+
+BluetoothHandsfreeHALInterface::BluetoothHandsfreeHALInterface(
+ const bthf_interface_t* aInterface)
+: mInterface(aInterface)
+{
+ MOZ_ASSERT(mInterface);
+}
+
+BluetoothHandsfreeHALInterface::~BluetoothHandsfreeHALInterface()
+{ }
+
+void
+BluetoothHandsfreeHALInterface::Init(
+ BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ static bthf_callbacks_t sCallbacks = {
+ sizeof(sCallbacks),
+ BluetoothHandsfreeHALCallback::ConnectionState,
+ BluetoothHandsfreeHALCallback::AudioState,
+ BluetoothHandsfreeHALCallback::VoiceRecognition,
+ BluetoothHandsfreeHALCallback::AnswerCall,
+ BluetoothHandsfreeHALCallback::HangupCall,
+ BluetoothHandsfreeHALCallback::Volume,
+ BluetoothHandsfreeHALCallback::DialCall,
+ BluetoothHandsfreeHALCallback::Dtmf,
+ BluetoothHandsfreeHALCallback::NoiseReductionEchoCancellation,
+ BluetoothHandsfreeHALCallback::CallHold,
+ BluetoothHandsfreeHALCallback::Cnum,
+ BluetoothHandsfreeHALCallback::Cind,
+ BluetoothHandsfreeHALCallback::Cops,
+ BluetoothHandsfreeHALCallback::Clcc,
+ BluetoothHandsfreeHALCallback::UnknownAt,
+ BluetoothHandsfreeHALCallback::KeyPressed
+ };
+
+ sHandsfreeNotificationHandler = aNotificationHandler;
+
+ bt_status_t status = mInterface->init(&sCallbacks);
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::Init,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::Cleanup(
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ mInterface->cleanup();
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::Cleanup, STATUS_SUCCESS);
+ }
+}
+
+/* Connect / Disconnect */
+
+void
+BluetoothHandsfreeHALInterface::Connect(
+ const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bt_bdaddr_t bdAddr;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->connect(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::Connect,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::Disconnect(
+ const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bt_bdaddr_t bdAddr;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->disconnect(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::Disconnect,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::ConnectAudio(
+ const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bt_bdaddr_t bdAddr;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->connect_audio(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::ConnectAudio,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::DisconnectAudio(
+ const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bt_bdaddr_t bdAddr;
+
+ if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr))) {
+ status = mInterface->disconnect_audio(&bdAddr);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::DisconnectAudio,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Voice Recognition */
+
+void
+BluetoothHandsfreeHALInterface::StartVoiceRecognition(
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status = mInterface->start_voice_recognition();
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::StopVoiceRecognition(
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status = mInterface->stop_voice_recognition();
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Volume */
+
+void
+BluetoothHandsfreeHALInterface::VolumeControl(
+ BluetoothHandsfreeVolumeType aType, int aVolume,
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bthf_volume_type_t type = BTHF_VOLUME_TYPE_SPK;
+
+ if (NS_SUCCEEDED(Convert(aType, type))) {
+ status = mInterface->volume_control(type, aVolume);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::VolumeControl,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Device status */
+
+void
+BluetoothHandsfreeHALInterface::DeviceStatusNotification(
+ BluetoothHandsfreeNetworkState aNtkState,
+ BluetoothHandsfreeServiceType aSvcType, int aSignal,
+ int aBattChg, BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bthf_network_state_t ntkState = BTHF_NETWORK_STATE_NOT_AVAILABLE;
+ bthf_service_type_t svcType = BTHF_SERVICE_TYPE_HOME;
+
+ if (NS_SUCCEEDED(Convert(aNtkState, ntkState)) &&
+ NS_SUCCEEDED(Convert(aSvcType, svcType))) {
+ status = mInterface->device_status_notification(ntkState, svcType,
+ aSignal, aBattChg);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::DeviceStatusNotification,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Responses */
+
+void
+BluetoothHandsfreeHALInterface::CopsResponse(
+ const char* aCops, BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status = mInterface->cops_response(aCops);
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::CopsResponse,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::CindResponse(
+ int aSvc, int aNumActive, int aNumHeld,
+ BluetoothHandsfreeCallState aCallSetupState,
+ int aSignal, int aRoam, int aBattChg,
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE;
+
+ if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState))) {
+ status = mInterface->cind_response(aSvc, aNumActive, aNumHeld,
+ callSetupState, aSignal,
+ aRoam, aBattChg);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::CindResponse,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::FormattedAtResponse(
+ const char* aRsp, BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status = mInterface->formatted_at_response(aRsp);
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::AtResponse(
+ BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bthf_at_response_t responseCode = BTHF_AT_RESPONSE_ERROR;
+
+ if (NS_SUCCEEDED(Convert(aResponseCode, responseCode))) {
+ status = mInterface->at_response(responseCode, aErrorCode);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::AtResponse,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+void
+BluetoothHandsfreeHALInterface::ClccResponse(
+ int aIndex,
+ BluetoothHandsfreeCallDirection aDir,
+ BluetoothHandsfreeCallState aState,
+ BluetoothHandsfreeCallMode aMode,
+ BluetoothHandsfreeCallMptyType aMpty,
+ const nsAString& aNumber,
+ BluetoothHandsfreeCallAddressType aType,
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bthf_call_direction_t dir = BTHF_CALL_DIRECTION_OUTGOING;
+ bthf_call_state_t state = BTHF_CALL_STATE_ACTIVE;
+ bthf_call_mode_t mode = BTHF_CALL_TYPE_VOICE;
+ bthf_call_mpty_type_t mpty = BTHF_CALL_MPTY_TYPE_SINGLE;
+ bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN;
+
+ if (NS_SUCCEEDED(Convert(aDir, dir)) &&
+ NS_SUCCEEDED(Convert(aState, state)) &&
+ NS_SUCCEEDED(Convert(aMode, mode)) &&
+ NS_SUCCEEDED(Convert(aMpty, mpty)) &&
+ NS_SUCCEEDED(Convert(aType, type))) {
+ status = mInterface->clcc_response(aIndex, dir, state, mode, mpty,
+ NS_ConvertUTF16toUTF8(aNumber).get(),
+ type);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::ClccResponse,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+/* Phone State */
+
+void
+BluetoothHandsfreeHALInterface::PhoneStateChange(int aNumActive, int aNumHeld,
+ BluetoothHandsfreeCallState aCallSetupState, const nsAString& aNumber,
+ BluetoothHandsfreeCallAddressType aType,
+ BluetoothHandsfreeResultHandler* aRes)
+{
+ bt_status_t status;
+ bthf_call_state_t callSetupState = BTHF_CALL_STATE_ACTIVE;
+ bthf_call_addrtype_t type = BTHF_CALL_ADDRTYPE_UNKNOWN;
+
+ if (NS_SUCCEEDED(Convert(aCallSetupState, callSetupState)) &&
+ NS_SUCCEEDED(Convert(aType, type))) {
+ status = mInterface->phone_state_change(
+ aNumActive, aNumHeld, callSetupState,
+ NS_ConvertUTF16toUTF8(aNumber).get(), type);
+ } else {
+ status = BT_STATUS_PARM_INVALID;
+ }
+
+ if (aRes) {
+ DispatchBluetoothHandsfreeHALResult(
+ aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange,
+ ConvertDefault(status, STATUS_FAIL));
+ }
+}
+
+END_BLUETOOTH_NAMESPACE
diff --git a/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h
new file mode 100644
index 000000000000..f53d4251fb65
--- /dev/null
+++ b/dom/bluetooth/bluedroid/BluetoothHandsfreeHALInterface.h
@@ -0,0 +1,95 @@
+/* -*- 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_bluetoothhandsfreehalinterface_h__
+#define mozilla_dom_bluetooth_bluedroid_bluetoothhandsfreehalinterface_h__
+
+#include
+#include
+#include "BluetoothCommon.h"
+#include "BluetoothInterface.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class BluetoothHALInterface;
+
+class BluetoothHandsfreeHALInterface MOZ_FINAL
+ : public BluetoothHandsfreeInterface
+{
+public:
+ friend class BluetoothHALInterface;
+
+ void Init(BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+ BluetoothHandsfreeResultHandler* aRes);
+ void Cleanup(BluetoothHandsfreeResultHandler* aRes);
+
+ /* Connect / Disconnect */
+
+ void Connect(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes);
+ void Disconnect(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes);
+ void ConnectAudio(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes);
+ void DisconnectAudio(const nsAString& aBdAddr,
+ BluetoothHandsfreeResultHandler* aRes);
+
+ /* Voice Recognition */
+
+ void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
+ void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
+
+ /* Volume */
+
+ void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
+ BluetoothHandsfreeResultHandler* aRes);
+
+ /* Device status */
+
+ void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
+ BluetoothHandsfreeServiceType aSvcType,
+ int aSignal, int aBattChg,
+ BluetoothHandsfreeResultHandler* aRes);
+
+ /* Responses */
+
+ void CopsResponse(const char* aCops,
+ BluetoothHandsfreeResultHandler* aRes);
+ void CindResponse(int aSvc, int aNumActive, int aNumHeld,
+ BluetoothHandsfreeCallState aCallSetupState, int aSignal,
+ int aRoam, int aBattChg,
+ BluetoothHandsfreeResultHandler* aRes);
+ void FormattedAtResponse(const char* aRsp,
+ BluetoothHandsfreeResultHandler* aRes);
+ void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+ BluetoothHandsfreeResultHandler* aRes);
+ void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
+ BluetoothHandsfreeCallState aState,
+ BluetoothHandsfreeCallMode aMode,
+ BluetoothHandsfreeCallMptyType aMpty,
+ const nsAString& aNumber,
+ BluetoothHandsfreeCallAddressType aType,
+ BluetoothHandsfreeResultHandler* aRes);
+
+ /* Phone State */
+
+ void PhoneStateChange(int aNumActive, int aNumHeld,
+ BluetoothHandsfreeCallState aCallSetupState,
+ const nsAString& aNumber,
+ BluetoothHandsfreeCallAddressType aType,
+ BluetoothHandsfreeResultHandler* aRes);
+
+protected:
+ BluetoothHandsfreeHALInterface(const bthf_interface_t* aInterface);
+ ~BluetoothHandsfreeHALInterface();
+
+private:
+ const bthf_interface_t* mInterface;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
diff --git a/dom/bluetooth/bluedroid/BluetoothInterface.cpp b/dom/bluetooth/bluedroid/BluetoothInterface.cpp
deleted file mode 100644
index 17e8feeb6985..000000000000
--- a/dom/bluetooth/bluedroid/BluetoothInterface.cpp
+++ /dev/null
@@ -1,4427 +0,0 @@
-/* -*- 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 "BluetoothInterface.h"
-#include
-#include
-#include
-#include "base/message_loop.h"
-#include "nsAutoPtr.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-
-#if MOZ_IS_GCC && MOZ_GCC_VERSION_AT_LEAST(4, 7, 0)
-/* use designated array initializers if supported */
-#define CONVERT(in_, out_) \
- [in_] = out_
-#else
-/* otherwise init array element by position */
-#define CONVERT(in_, out_) \
- out_
-#endif
-
-#define MAX_UUID_SIZE 16
-
-BEGIN_BLUETOOTH_NAMESPACE
-
-template
-struct interface_traits
-{ };
-
-//
-// Conversion
-//
-
-static nsresult
-Convert(bt_status_t aIn, BluetoothStatus& aOut)
-{
- static const BluetoothStatus sStatus[] = {
- CONVERT(BT_STATUS_SUCCESS, STATUS_SUCCESS),
- CONVERT(BT_STATUS_FAIL, STATUS_FAIL),
- CONVERT(BT_STATUS_NOT_READY, STATUS_NOT_READY),
- CONVERT(BT_STATUS_NOMEM, STATUS_NOMEM),
- CONVERT(BT_STATUS_BUSY, STATUS_BUSY),
- CONVERT(BT_STATUS_DONE, STATUS_DONE),
- CONVERT(BT_STATUS_UNSUPPORTED, STATUS_UNSUPPORTED),
- CONVERT(BT_STATUS_PARM_INVALID, STATUS_PARM_INVALID),
- CONVERT(BT_STATUS_UNHANDLED, STATUS_UNHANDLED),
- CONVERT(BT_STATUS_AUTH_FAILURE, STATUS_AUTH_FAILURE),
- CONVERT(BT_STATUS_RMT_DEV_DOWN, STATUS_RMT_DEV_DOWN)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sStatus[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(int aIn, BluetoothStatus& aOut)
-{
- return Convert(static_cast(aIn), aOut);
-}
-
-static nsresult
-Convert(const nsAString& aIn, bt_property_type_t& aOut)
-{
- if (aIn.EqualsLiteral("Name")) {
- aOut = BT_PROPERTY_BDNAME;
- } else if (aIn.EqualsLiteral("Discoverable")) {
- aOut = BT_PROPERTY_ADAPTER_SCAN_MODE;
- } else if (aIn.EqualsLiteral("DiscoverableTimeout")) {
- aOut = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
- } else {
- BT_LOGR("Invalid property name: %s", NS_ConvertUTF16toUTF8(aIn).get());
- return NS_ERROR_ILLEGAL_VALUE;
- }
- return NS_OK;
-}
-
-static nsresult
-Convert(bool aIn, bt_scan_mode_t& aOut)
-{
- static const bt_scan_mode_t sScanMode[] = {
- CONVERT(false, BT_SCAN_MODE_CONNECTABLE),
- CONVERT(true, BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sScanMode[aIn];
- return NS_OK;
-}
-
-
-static nsresult
-Convert(bt_scan_mode_t aIn, BluetoothScanMode& aOut)
-{
- static const BluetoothScanMode sScanMode[] = {
- CONVERT(BT_SCAN_MODE_NONE, SCAN_MODE_NONE),
- CONVERT(BT_SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE),
- CONVERT(BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE,
- SCAN_MODE_CONNECTABLE_DISCOVERABLE)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sScanMode)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sScanMode[aIn];
- return NS_OK;
-}
-
-struct ConvertNamedValue
-{
- ConvertNamedValue(const BluetoothNamedValue& aNamedValue)
- : mNamedValue(aNamedValue)
- { }
-
- const BluetoothNamedValue& mNamedValue;
-
- // temporary fields
- nsCString mStringValue;
- bt_scan_mode_t mScanMode;
-};
-
-static nsresult
-Convert(ConvertNamedValue& aIn, bt_property_t& aOut)
-{
- nsresult rv = Convert(aIn.mNamedValue.name(), aOut.type);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- if (aIn.mNamedValue.value().type() == BluetoothValue::Tuint32_t) {
- // Set discoverable timeout
- aOut.val =
- reinterpret_cast(aIn.mNamedValue.value().get_uint32_t());
- } else if (aIn.mNamedValue.value().type() == BluetoothValue::TnsString) {
- // Set name
- aIn.mStringValue =
- NS_ConvertUTF16toUTF8(aIn.mNamedValue.value().get_nsString());
- aOut.val =
- const_cast(static_cast(aIn.mStringValue.get()));
- aOut.len = strlen(static_cast(aOut.val));
- } else if (aIn.mNamedValue.value().type() == BluetoothValue::Tbool) {
- // Set scan mode
- rv = Convert(aIn.mNamedValue.value().get_bool(), aIn.mScanMode);
- if (NS_FAILED(rv)) {
- return rv;
- }
- aOut.val = &aIn.mScanMode;
- aOut.len = sizeof(aIn.mScanMode);
- } else {
- BT_LOGR("Invalid property value type");
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const nsAString& aIn, bt_bdaddr_t& aOut)
-{
- NS_ConvertUTF16toUTF8 bdAddressUTF8(aIn);
- const char* str = bdAddressUTF8.get();
-
- for (size_t i = 0; i < MOZ_ARRAY_LENGTH(aOut.address); ++i, ++str) {
- aOut.address[i] =
- static_cast(strtoul(str, const_cast(&str), 16));
- }
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const nsAString& aIn, bt_ssp_variant_t& aOut)
-{
- if (aIn.EqualsLiteral("PasskeyConfirmation")) {
- aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION;
- } else if (aIn.EqualsLiteral("PasskeyEntry")) {
- aOut = BT_SSP_VARIANT_PASSKEY_ENTRY;
- } else if (aIn.EqualsLiteral("Consent")) {
- aOut = BT_SSP_VARIANT_CONSENT;
- } else if (aIn.EqualsLiteral("PasskeyNotification")) {
- aOut = BT_SSP_VARIANT_PASSKEY_NOTIFICATION;
- } else {
- BT_LOGR("Invalid SSP variant name: %s", NS_ConvertUTF16toUTF8(aIn).get());
- aOut = BT_SSP_VARIANT_PASSKEY_CONFIRMATION; // silences compiler warning
- return NS_ERROR_ILLEGAL_VALUE;
- }
- return NS_OK;
-}
-
-static nsresult
-Convert(const bt_ssp_variant_t& aIn, nsAString& aOut)
-{
- static const char * const sSspVariant[] = {
- CONVERT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION, "PasskeyConfirmation"),
- CONVERT(BT_SSP_VARIANT_PASSKEY_ENTRY, "PasskeyEntry"),
- CONVERT(BT_SSP_VARIANT_CONSENT, "Consent"),
- CONVERT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION, "PasskeyNotification")
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = NS_ConvertUTF8toUTF16(sSspVariant[aIn]);
- return NS_OK;
-}
-
-static nsresult
-Convert(const bool& aIn, uint8_t& aOut)
-{
- // casting converts true/false to either 1 or 0
- aOut = static_cast(aIn);
- return NS_OK;
-}
-
-static nsresult
-Convert(const uint8_t aIn[16], bt_uuid_t& aOut)
-{
- if (sizeof(aOut.uu) != 16) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- memcpy(aOut.uu, aIn, sizeof(aOut.uu));
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const bt_uuid_t& aIn, BluetoothUuid& aOut)
-{
- if (sizeof(aIn.uu) != sizeof(aOut.mUuid)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- memcpy(aOut.mUuid, aIn.uu, sizeof(aOut.mUuid));
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const nsAString& aIn, bt_pin_code_t& aOut)
-{
- if (aIn.Length() > MOZ_ARRAY_LENGTH(aOut.pin)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
-
- NS_ConvertUTF16toUTF8 pinCodeUTF8(aIn);
- const char* str = pinCodeUTF8.get();
-
- nsAString::size_type i;
-
- // Fill pin into aOut
- for (i = 0; i < aIn.Length(); ++i, ++str) {
- aOut.pin[i] = static_cast(*str);
- }
-
- // Clear remaining bytes in aOut
- size_t ntrailing =
- (MOZ_ARRAY_LENGTH(aOut.pin) - aIn.Length()) * sizeof(aOut.pin[0]);
- memset(aOut.pin + aIn.Length(), 0, ntrailing);
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const bt_bdaddr_t& aIn, nsAString& aOut)
-{
- char str[BLUETOOTH_ADDRESS_LENGTH + 1];
-
- int res = snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
- static_cast(aIn.address[0]),
- static_cast(aIn.address[1]),
- static_cast(aIn.address[2]),
- static_cast(aIn.address[3]),
- static_cast(aIn.address[4]),
- static_cast(aIn.address[5]));
- if (res < 0) {
- return NS_ERROR_ILLEGAL_VALUE;
- } else if ((size_t)res >= sizeof(str)) {
- return NS_ERROR_OUT_OF_MEMORY; /* string buffer too small */
- }
-
- aOut = NS_ConvertUTF8toUTF16(str);
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const bt_bdaddr_t* aIn, nsAString& aOut)
-{
- if (!aIn) {
- aOut.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
- return NS_OK;
- }
- return Convert(*aIn, aOut);
-}
-
-static nsresult
-Convert(bt_state_t aIn, bool& aOut)
-{
- static const bool sState[] = {
- CONVERT(BT_STATE_OFF, false),
- CONVERT(BT_STATE_ON, true)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bt_property_type_t aIn, BluetoothPropertyType& aOut)
-{
- static const BluetoothPropertyType sPropertyType[] = {
- CONVERT(0, static_cast(0)), // invalid, required by gcc
- CONVERT(BT_PROPERTY_BDNAME, PROPERTY_BDNAME),
- CONVERT(BT_PROPERTY_BDADDR, PROPERTY_BDADDR),
- CONVERT(BT_PROPERTY_UUIDS, PROPERTY_UUIDS),
- CONVERT(BT_PROPERTY_CLASS_OF_DEVICE, PROPERTY_CLASS_OF_DEVICE),
- CONVERT(BT_PROPERTY_TYPE_OF_DEVICE, PROPERTY_TYPE_OF_DEVICE),
- CONVERT(BT_PROPERTY_SERVICE_RECORD, PROPERTY_SERVICE_RECORD),
- CONVERT(BT_PROPERTY_ADAPTER_SCAN_MODE, PROPERTY_ADAPTER_SCAN_MODE),
- CONVERT(BT_PROPERTY_ADAPTER_BONDED_DEVICES,
- PROPERTY_ADAPTER_BONDED_DEVICES),
- CONVERT(BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT,
- PROPERTY_ADAPTER_DISCOVERY_TIMEOUT),
- CONVERT(BT_PROPERTY_REMOTE_FRIENDLY_NAME, PROPERTY_REMOTE_FRIENDLY_NAME),
- CONVERT(BT_PROPERTY_REMOTE_RSSI, PROPERTY_REMOTE_RSSI),
- CONVERT(BT_PROPERTY_REMOTE_VERSION_INFO,PROPERTY_REMOTE_VERSION_INFO)
- };
- if (aIn == BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP) {
- /* This case is handled separately to not populate
- * |sPropertyType| with empty entries. */
- aOut = PROPERTY_REMOTE_DEVICE_TIMESTAMP;
- return NS_OK;
- }
- if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPropertyType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sPropertyType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bt_discovery_state_t aIn, bool& aOut)
-{
- static const bool sDiscoveryState[] = {
- CONVERT(BT_DISCOVERY_STOPPED, false),
- CONVERT(BT_DISCOVERY_STARTED, true)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sDiscoveryState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sDiscoveryState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(const char* aIn, nsACString& aOut)
-{
- aOut.Assign(aIn);
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const char* aIn, nsAString& aOut)
-{
- aOut = NS_ConvertUTF8toUTF16(aIn);
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const bt_bdname_t& aIn, nsAString& aOut)
-{
- return Convert(reinterpret_cast(aIn.name), aOut);
-}
-
-static nsresult
-Convert(const bt_bdname_t* aIn, nsAString& aOut)
-{
- if (!aIn) {
- aOut.Truncate();
- return NS_OK;
- }
- return Convert(*aIn, aOut);
-}
-
-static nsresult
-Convert(bt_bond_state_t aIn, BluetoothBondState& aOut)
-{
- static const BluetoothBondState sBondState[] = {
- CONVERT(BT_BOND_STATE_NONE, BOND_STATE_NONE),
- CONVERT(BT_BOND_STATE_BONDING, BOND_STATE_BONDING),
- CONVERT(BT_BOND_STATE_BONDED, BOND_STATE_BONDED)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sBondState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sBondState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bt_acl_state_t aIn, bool& aOut)
-{
- static const bool sAclState[] = {
- CONVERT(BT_ACL_STATE_CONNECTED, true),
- CONVERT(BT_ACL_STATE_DISCONNECTED, false)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sAclState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sAclState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bt_device_type_t aIn, BluetoothDeviceType& aOut)
-{
- static const BluetoothDeviceType sDeviceType[] = {
- CONVERT(0, static_cast(0)), // invalid, required by gcc
- CONVERT(BT_DEVICE_DEVTYPE_BREDR, DEVICE_TYPE_BREDR),
- CONVERT(BT_DEVICE_DEVTYPE_BLE, DEVICE_TYPE_BLE),
- CONVERT(BT_DEVICE_DEVTYPE_DUAL, DEVICE_TYPE_DUAL)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sDeviceType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sDeviceType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(const bt_service_record_t& aIn, BluetoothServiceRecord& aOut)
-{
- nsresult rv = Convert(aIn.uuid, aOut.mUuid);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- aOut.mChannel = aIn.channel;
-
- MOZ_ASSERT(sizeof(aIn.name) == sizeof(aOut.mName));
- memcpy(aOut.mName, aIn.name, sizeof(aOut.mName));
-
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothSocketType aIn, btsock_type_t& aOut)
-{
- // FIXME: Array member [0] is currently invalid, but required
- // by gcc. Start values in |BluetoothSocketType| at index
- // 0 to fix this problem.
- static const btsock_type_t sSocketType[] = {
- CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
- CONVERT(BluetoothSocketType::RFCOMM, BTSOCK_RFCOMM),
- CONVERT(BluetoothSocketType::SCO, BTSOCK_SCO),
- CONVERT(BluetoothSocketType::L2CAP, BTSOCK_L2CAP),
- // EL2CAP is not supported by Bluedroid
- };
- if (aIn == BluetoothSocketType::EL2CAP ||
- aIn >= MOZ_ARRAY_LENGTH(sSocketType) || !sSocketType[aIn]) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sSocketType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeAtResponse aIn, bthf_at_response_t& aOut)
-{
- static const bthf_at_response_t sAtResponse[] = {
- CONVERT(HFP_AT_RESPONSE_ERROR, BTHF_AT_RESPONSE_ERROR),
- CONVERT(HFP_AT_RESPONSE_OK, BTHF_AT_RESPONSE_OK)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sAtResponse)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sAtResponse[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeCallAddressType aIn, bthf_call_addrtype_t& aOut)
-{
- static const bthf_call_addrtype_t sCallAddressType[] = {
- CONVERT(HFP_CALL_ADDRESS_TYPE_UNKNOWN, BTHF_CALL_ADDRTYPE_UNKNOWN),
- CONVERT(HFP_CALL_ADDRESS_TYPE_INTERNATIONAL,
- BTHF_CALL_ADDRTYPE_INTERNATIONAL)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sCallAddressType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sCallAddressType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeCallDirection aIn, bthf_call_direction_t& aOut)
-{
- static const bthf_call_direction_t sCallDirection[] = {
- CONVERT(HFP_CALL_DIRECTION_OUTGOING, BTHF_CALL_DIRECTION_OUTGOING),
- CONVERT(HFP_CALL_DIRECTION_INCOMING, BTHF_CALL_DIRECTION_INCOMING)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sCallDirection)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sCallDirection[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeCallMode aIn, bthf_call_mode_t& aOut)
-{
- static const bthf_call_mode_t sCallMode[] = {
- CONVERT(HFP_CALL_MODE_VOICE, BTHF_CALL_TYPE_VOICE),
- CONVERT(HFP_CALL_MODE_DATA, BTHF_CALL_TYPE_DATA),
- CONVERT(HFP_CALL_MODE_FAX, BTHF_CALL_TYPE_FAX)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sCallMode)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sCallMode[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeCallMptyType aIn, bthf_call_mpty_type_t& aOut)
-{
- static const bthf_call_mpty_type_t sCallMptyType[] = {
- CONVERT(HFP_CALL_MPTY_TYPE_SINGLE, BTHF_CALL_MPTY_TYPE_SINGLE),
- CONVERT(HFP_CALL_MPTY_TYPE_MULTI, BTHF_CALL_MPTY_TYPE_MULTI)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sCallMptyType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sCallMptyType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeCallState aIn, bthf_call_state_t& aOut)
-{
- static const bthf_call_state_t sCallState[] = {
- CONVERT(HFP_CALL_STATE_ACTIVE, BTHF_CALL_STATE_ACTIVE),
- CONVERT(HFP_CALL_STATE_HELD, BTHF_CALL_STATE_HELD),
- CONVERT(HFP_CALL_STATE_DIALING, BTHF_CALL_STATE_DIALING),
- CONVERT(HFP_CALL_STATE_ALERTING, BTHF_CALL_STATE_ALERTING),
- CONVERT(HFP_CALL_STATE_INCOMING, BTHF_CALL_STATE_INCOMING),
- CONVERT(HFP_CALL_STATE_WAITING, BTHF_CALL_STATE_WAITING),
- CONVERT(HFP_CALL_STATE_IDLE, BTHF_CALL_STATE_IDLE)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sCallState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sCallState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeNetworkState aIn, bthf_network_state_t& aOut)
-{
- static const bthf_network_state_t sNetworkState[] = {
- CONVERT(HFP_NETWORK_STATE_NOT_AVAILABLE, BTHF_NETWORK_STATE_NOT_AVAILABLE),
- CONVERT(HFP_NETWORK_STATE_AVAILABLE, BTHF_NETWORK_STATE_AVAILABLE)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sNetworkState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sNetworkState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeServiceType aIn, bthf_service_type_t& aOut)
-{
- static const bthf_service_type_t sServiceType[] = {
- CONVERT(HFP_SERVICE_TYPE_HOME, BTHF_SERVICE_TYPE_HOME),
- CONVERT(HFP_SERVICE_TYPE_ROAMING, BTHF_SERVICE_TYPE_ROAMING)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sServiceType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sServiceType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(BluetoothHandsfreeVolumeType aIn, bthf_volume_type_t& aOut)
-{
- static const bthf_volume_type_t sVolumeType[] = {
- CONVERT(HFP_VOLUME_TYPE_SPEAKER, BTHF_VOLUME_TYPE_SPK),
- CONVERT(HFP_VOLUME_TYPE_MICROPHONE, BTHF_VOLUME_TYPE_MIC)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sVolumeType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bthf_audio_state_t aIn, BluetoothHandsfreeAudioState& aOut)
-{
- static const BluetoothHandsfreeAudioState sAudioState[] = {
- CONVERT(BTHF_AUDIO_STATE_DISCONNECTED, HFP_AUDIO_STATE_DISCONNECTED),
- CONVERT(BTHF_AUDIO_STATE_CONNECTING, HFP_AUDIO_STATE_CONNECTING),
- CONVERT(BTHF_AUDIO_STATE_CONNECTED, HFP_AUDIO_STATE_CONNECTED),
- CONVERT(BTHF_AUDIO_STATE_DISCONNECTING, HFP_AUDIO_STATE_DISCONNECTING)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sAudioState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bthf_chld_type_t aIn, BluetoothHandsfreeCallHoldType& aOut)
-{
- static const BluetoothHandsfreeCallHoldType sCallHoldType[] = {
- CONVERT(BTHF_CHLD_TYPE_RELEASEHELD, HFP_CALL_HOLD_RELEASEHELD),
- CONVERT(BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD,
- HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD),
- CONVERT(BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD,
- HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD),
- CONVERT(BTHF_CHLD_TYPE_ADDHELDTOCONF, HFP_CALL_HOLD_ADDHELDTOCONF)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sCallHoldType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sCallHoldType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bthf_connection_state_t aIn, BluetoothHandsfreeConnectionState& aOut)
-{
- static const BluetoothHandsfreeConnectionState sConnectionState[] = {
- CONVERT(BTHF_CONNECTION_STATE_DISCONNECTED,
- HFP_CONNECTION_STATE_DISCONNECTED),
- CONVERT(BTHF_CONNECTION_STATE_CONNECTING, HFP_CONNECTION_STATE_CONNECTING),
- CONVERT(BTHF_CONNECTION_STATE_CONNECTED, HFP_CONNECTION_STATE_CONNECTED),
- CONVERT(BTHF_CONNECTION_STATE_SLC_CONNECTED,
- HFP_CONNECTION_STATE_SLC_CONNECTED),
- CONVERT(BTHF_CONNECTION_STATE_DISCONNECTING,
- HFP_CONNECTION_STATE_DISCONNECTING)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sConnectionState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bthf_nrec_t aIn, BluetoothHandsfreeNRECState& aOut)
-{
- static const BluetoothHandsfreeNRECState sNRECState[] = {
- CONVERT(BTHF_NREC_STOP, HFP_NREC_STOPPED),
- CONVERT(BTHF_NREC_START, HFP_NREC_STARTED)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sNRECState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sNRECState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bthf_vr_state_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut)
-{
- static const BluetoothHandsfreeVoiceRecognitionState
- sVoiceRecognitionState[] = {
- CONVERT(BTHF_VR_STATE_STOPPED, HFP_VOICE_RECOGNITION_STOPPED),
- CONVERT(BTHF_VR_STATE_STARTED, HFP_VOICE_RECOGNITION_STARTED)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sVoiceRecognitionState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sVoiceRecognitionState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(bthf_volume_type_t aIn, BluetoothHandsfreeVolumeType& aOut)
-{
- static const BluetoothHandsfreeVolumeType sVolumeType[] = {
- CONVERT(BTHF_VOLUME_TYPE_SPK, HFP_VOLUME_TYPE_SPEAKER),
- CONVERT(BTHF_VOLUME_TYPE_MIC, HFP_VOLUME_TYPE_MICROPHONE)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sVolumeType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(btav_connection_state_t aIn, BluetoothA2dpConnectionState& aOut)
-{
- static const BluetoothA2dpConnectionState sConnectionState[] = {
- CONVERT(BTAV_CONNECTION_STATE_DISCONNECTED,
- A2DP_CONNECTION_STATE_DISCONNECTED),
- CONVERT(BTAV_CONNECTION_STATE_CONNECTING,
- A2DP_CONNECTION_STATE_CONNECTING),
- CONVERT(BTAV_CONNECTION_STATE_CONNECTED,
- A2DP_CONNECTION_STATE_CONNECTED),
- CONVERT(BTAV_CONNECTION_STATE_DISCONNECTING,
- A2DP_CONNECTION_STATE_DISCONNECTING),
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sConnectionState[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(btav_audio_state_t aIn, BluetoothA2dpAudioState& aOut)
-{
- static const BluetoothA2dpAudioState sAudioState[] = {
- CONVERT(BTAV_AUDIO_STATE_REMOTE_SUSPEND, A2DP_AUDIO_STATE_REMOTE_SUSPEND),
- CONVERT(BTAV_AUDIO_STATE_STOPPED, A2DP_AUDIO_STATE_STOPPED),
- CONVERT(BTAV_AUDIO_STATE_STARTED, A2DP_AUDIO_STATE_STARTED),
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sAudioState[aIn];
- return NS_OK;
-}
-
-#if ANDROID_VERSION >= 18
-static nsresult
-Convert(const bt_remote_version_t& aIn, BluetoothRemoteInfo& aOut)
-{
- aOut.mVerMajor = aIn.version;
- aOut.mVerMinor = aIn.sub_ver;
- aOut.mManufacturer = aIn.manufacturer;
-
- return NS_OK;
-}
-
-static nsresult
-Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut)
-{
- static const btrc_play_status_t sPlayStatus[] = {
- CONVERT(PLAYSTATUS_STOPPED, BTRC_PLAYSTATE_STOPPED),
- CONVERT(PLAYSTATUS_PLAYING, BTRC_PLAYSTATE_PLAYING),
- CONVERT(PLAYSTATUS_PAUSED, BTRC_PLAYSTATE_PAUSED),
- CONVERT(PLAYSTATUS_FWD_SEEK, BTRC_PLAYSTATE_FWD_SEEK),
- CONVERT(PLAYSTATUS_REV_SEEK, BTRC_PLAYSTATE_REV_SEEK)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sPlayStatus)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sPlayStatus[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(enum BluetoothAvrcpPlayerAttribute aIn, btrc_player_attr_t& aOut)
-{
- static const btrc_player_attr_t sPlayerAttr[] = {
- CONVERT(AVRCP_PLAYER_ATTRIBUTE_EQUALIZER, BTRC_PLAYER_ATTR_EQUALIZER),
- CONVERT(AVRCP_PLAYER_ATTRIBUTE_REPEAT, BTRC_PLAYER_ATTR_REPEAT),
- CONVERT(AVRCP_PLAYER_ATTRIBUTE_SHUFFLE, BTRC_PLAYER_ATTR_SHUFFLE),
- CONVERT(AVRCP_PLAYER_ATTRIBUTE_SCAN, BTRC_PLAYER_ATTR_SCAN)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sPlayerAttr[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(btrc_player_attr_t aIn, enum BluetoothAvrcpPlayerAttribute& aOut)
-{
- static const BluetoothAvrcpPlayerAttribute sPlayerAttr[] = {
- CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
- CONVERT(BTRC_PLAYER_ATTR_EQUALIZER, AVRCP_PLAYER_ATTRIBUTE_EQUALIZER),
- CONVERT(BTRC_PLAYER_ATTR_REPEAT, AVRCP_PLAYER_ATTRIBUTE_REPEAT),
- CONVERT(BTRC_PLAYER_ATTR_SHUFFLE, AVRCP_PLAYER_ATTRIBUTE_SHUFFLE),
- CONVERT(BTRC_PLAYER_ATTR_SCAN, AVRCP_PLAYER_ATTRIBUTE_SCAN)
- };
- if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sPlayerAttr)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sPlayerAttr[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(enum BluetoothAvrcpStatus aIn, btrc_status_t& aOut)
-{
- static const btrc_status_t sStatus[] = {
- CONVERT(AVRCP_STATUS_BAD_COMMAND, BTRC_STS_BAD_CMD),
- CONVERT(AVRCP_STATUS_BAD_PARAMETER, BTRC_STS_BAD_PARAM),
- CONVERT(AVRCP_STATUS_NOT_FOUND, BTRC_STS_NOT_FOUND),
- CONVERT(AVRCP_STATUS_INTERNAL_ERROR, BTRC_STS_INTERNAL_ERR),
- CONVERT(AVRCP_STATUS_SUCCESS, BTRC_STS_NO_ERROR)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sStatus)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sStatus[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(enum BluetoothAvrcpEvent aIn, btrc_event_id_t& aOut)
-{
- static const btrc_event_id_t sEventId[] = {
- CONVERT(AVRCP_EVENT_PLAY_STATUS_CHANGED, BTRC_EVT_PLAY_STATUS_CHANGED),
- CONVERT(AVRCP_EVENT_TRACK_CHANGE, BTRC_EVT_TRACK_CHANGE),
- CONVERT(AVRCP_EVENT_TRACK_REACHED_END, BTRC_EVT_TRACK_REACHED_END),
- CONVERT(AVRCP_EVENT_TRACK_REACHED_START, BTRC_EVT_TRACK_REACHED_START),
- CONVERT(AVRCP_EVENT_PLAY_POS_CHANGED, BTRC_EVT_PLAY_POS_CHANGED),
- CONVERT(AVRCP_EVENT_APP_SETTINGS_CHANGED, BTRC_EVT_APP_SETTINGS_CHANGED)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sEventId)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sEventId[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(btrc_event_id_t aIn, enum BluetoothAvrcpEvent& aOut)
-{
- static const BluetoothAvrcpEvent sEventId[] = {
- CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
- CONVERT(BTRC_EVT_PLAY_STATUS_CHANGED, AVRCP_EVENT_PLAY_STATUS_CHANGED),
- CONVERT(BTRC_EVT_TRACK_CHANGE, AVRCP_EVENT_TRACK_CHANGE),
- CONVERT(BTRC_EVT_TRACK_REACHED_END, AVRCP_EVENT_TRACK_REACHED_END),
- CONVERT(BTRC_EVT_TRACK_REACHED_START, AVRCP_EVENT_TRACK_REACHED_START),
- CONVERT(BTRC_EVT_PLAY_POS_CHANGED, AVRCP_EVENT_PLAY_POS_CHANGED),
- CONVERT(6, static_cast(0)), // invalid, [6] required by gcc
- CONVERT(7, static_cast(0)), // invalid, [7] required by gcc
- CONVERT(BTRC_EVT_APP_SETTINGS_CHANGED, AVRCP_EVENT_APP_SETTINGS_CHANGED)
- };
- if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sEventId[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(btrc_media_attr_t aIn, enum BluetoothAvrcpMediaAttribute& aOut)
-{
- static const BluetoothAvrcpMediaAttribute sEventId[] = {
- CONVERT(0, static_cast(0)), // invalid, [0] required by gcc
- CONVERT(BTRC_MEDIA_ATTR_TITLE, AVRCP_MEDIA_ATTRIBUTE_TITLE),
- CONVERT(BTRC_MEDIA_ATTR_ARTIST, AVRCP_MEDIA_ATTRIBUTE_ARTIST),
- CONVERT(BTRC_MEDIA_ATTR_ALBUM, AVRCP_MEDIA_ATTRIBUTE_ALBUM),
- CONVERT(BTRC_MEDIA_ATTR_TRACK_NUM, AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM),
- CONVERT(BTRC_MEDIA_ATTR_NUM_TRACKS, AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS),
- CONVERT(BTRC_MEDIA_ATTR_GENRE, AVRCP_MEDIA_ATTRIBUTE_GENRE),
- CONVERT(BTRC_MEDIA_ATTR_PLAYING_TIME, AVRCP_MEDIA_ATTRIBUTE_PLAYING_TIME)
- };
- if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sEventId)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sEventId[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(enum BluetoothAvrcpNotification aIn, btrc_notification_type_t& aOut)
-{
- static const btrc_notification_type_t sNotificationType[] = {
- CONVERT(AVRCP_NTF_INTERIM, BTRC_NOTIFICATION_TYPE_INTERIM),
- CONVERT(AVRCP_NTF_CHANGED, BTRC_NOTIFICATION_TYPE_CHANGED)
- };
- if (aIn >= MOZ_ARRAY_LENGTH(sNotificationType)) {
- return NS_ERROR_ILLEGAL_VALUE;
- }
- aOut = sNotificationType[aIn];
- return NS_OK;
-}
-
-static nsresult
-Convert(const BluetoothAvrcpElementAttribute& aIn, btrc_element_attr_val_t& aOut)
-{
- const NS_ConvertUTF16toUTF8 value(aIn.mValue);
- size_t len = std::min(strlen(value.get()), sizeof(aOut.text) - 1);
-
- memcpy(aOut.text, value.get(), len);
- aOut.text[len] = '\0';
- aOut.attr_id = aIn.mId;
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const btrc_player_settings_t& aIn, BluetoothAvrcpPlayerSettings& aOut)
-{
- aOut.mNumAttr = aIn.num_attr;
- memcpy(aOut.mIds, aIn.attr_ids, aIn.num_attr);
- memcpy(aOut.mValues, aIn.attr_values, aIn.num_attr);
-
- return NS_OK;
-}
-#endif // ANDROID_VERSION >= 18
-
-#if ANDROID_VERSION >= 19
-static nsresult
-Convert(btrc_remote_features_t aIn, unsigned long& aOut)
-{
- /* The input type's name is misleading. The converted value is
- * actually a bitmask.
- */
- aOut = static_cast(aIn);
- return NS_OK;
-}
-#endif // ANDROID_VERSION >= 19
-
-/* |ConvertArray| is a helper for converting arrays. Pass an
- * instance of this structure as the first argument to |Convert|
- * to convert an array. The output type has to support the array
- * subscript operator.
- */
-template
-struct ConvertArray
-{
- ConvertArray(const T* aData, unsigned long aLength)
- : mData(aData)
- , mLength(aLength)
- { }
-
- const T* mData;
- unsigned long mLength;
-};
-
-/* This implementation of |Convert| converts the elements of an
- * array one-by-one. The result data structures must have enough
- * memory allocated.
- */
-template
-static nsresult
-Convert(const ConvertArray& aIn, Tout& aOut)
-{
- for (unsigned long i = 0; i < aIn.mLength; ++i) {
- nsresult rv = Convert(aIn.mData[i], aOut[i]);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return NS_OK;
-}
-
-/* This implementation of |Convert| is a helper that automatically
- * allocates enough memory to hold the conversion results. The
- * actual conversion is performed by the array-conversion helper
- * above.
- */
-template
-static nsresult
-Convert(const ConvertArray& aIn, nsAutoArrayPtr& aOut)
-{
- aOut = new Tout[aIn.mLength];
- Tout* out = aOut.get();
-
- return Convert(aIn, out);
-}
-
-/* |ConvertDefault| is a helper function to return the result of a
- * conversion or a default value if the conversion fails.
- */
-template
-static Tout
-ConvertDefault(const Tin& aIn, const Tout& aDefault)
-{
- Tout out = aDefault; // assignment silences compiler warning
- if (NS_FAILED(Convert(aIn, out))) {
- return aDefault;
- }
- return out;
-}
-
-/* This implementation of |Convert| is a helper for copying the
- * input value into the output value. It handles all cases that
- * need no conversion.
- */
-template
-static nsresult
-Convert(const T& aIn, T& aOut)
-{
- aOut = aIn;
-
- return NS_OK;
-}
-
-static nsresult
-Convert(const bt_property_t& aIn, BluetoothProperty& aOut)
-{
- /* type conversion */
-
- nsresult rv = Convert(aIn.type, aOut.mType);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- /* value conversion */
-
- switch (aOut.mType) {
- case PROPERTY_BDNAME:
- /* fall through */
- case PROPERTY_REMOTE_FRIENDLY_NAME:
- {
- // We construct an nsCString here because bdname
- // returned from Bluedroid is not 0-terminated.
- aOut.mString = NS_ConvertUTF8toUTF16(
- nsCString(static_cast(aIn.val), aIn.len));
- }
- break;
- case PROPERTY_BDADDR:
- rv = Convert(*static_cast(aIn.val), aOut.mString);
- break;
- case PROPERTY_UUIDS:
- {
- size_t numUuids = aIn.len / MAX_UUID_SIZE;
- ConvertArray array(
- static_cast(aIn.val), numUuids);
- aOut.mUuidArray.SetLength(numUuids);
- rv = Convert(array, aOut.mUuidArray);
- }
- break;
- case PROPERTY_CLASS_OF_DEVICE:
- /* fall through */
- case PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
- aOut.mUint32 = *static_cast(aIn.val);
- break;
- case PROPERTY_TYPE_OF_DEVICE:
- rv = Convert(*static_cast(aIn.val),
- aOut.mDeviceType);
- break;
- case PROPERTY_SERVICE_RECORD:
- rv = Convert(*static_cast(aIn.val),
- aOut.mServiceRecord);
- break;
- case PROPERTY_ADAPTER_SCAN_MODE:
- rv = Convert(*static_cast(aIn.val),
- aOut.mScanMode);
- break;
- case PROPERTY_ADAPTER_BONDED_DEVICES:
- {
- size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES;
- ConvertArray array(
- static_cast(aIn.val), numAddresses);
- aOut.mStringArray.SetLength(numAddresses);
- rv = Convert(array, aOut.mStringArray);
- }
- break;
- case PROPERTY_REMOTE_RSSI:
- aOut.mInt32 = *static_cast(aIn.val);
- break;
-#if ANDROID_VERSION >= 18
- case PROPERTY_REMOTE_VERSION_INFO:
- rv = Convert(*static_cast(aIn.val),
- aOut.mRemoteInfo);
- break;
-#endif
- case PROPERTY_REMOTE_DEVICE_TIMESTAMP:
- /* nothing to do */
- break;
- default:
- /* mismatch with type conversion */
- NS_NOTREACHED("Unhandled property type");
- break;
- }
- if (NS_FAILED(rv)) {
- return rv;
- }
- return NS_OK;
-}
-
-//
-// Result handling
-//
-
-template
-class BluetoothInterfaceRunnable0 : public nsRunnable
-{
-public:
- BluetoothInterfaceRunnable0(Obj* aObj, Res (Obj::*aMethod)())
- : mObj(aObj)
- , mMethod(aMethod)
- {
- MOZ_ASSERT(mObj);
- MOZ_ASSERT(mMethod);
- }
-
- NS_METHOD
- Run() MOZ_OVERRIDE
- {
- ((*mObj).*mMethod)();
- return NS_OK;
- }
-
-private:
- nsRefPtr mObj;
- void (Obj::*mMethod)();
-};
-
-template
-class BluetoothInterfaceRunnable1 : public nsRunnable
-{
-public:
- BluetoothInterfaceRunnable1(Obj* aObj, Res (Obj::*aMethod)(Arg1),
- const Arg1& aArg1)
- : mObj(aObj)
- , mMethod(aMethod)
- , mArg1(aArg1)
- {
- MOZ_ASSERT(mObj);
- MOZ_ASSERT(mMethod);
- }
-
- NS_METHOD
- Run() MOZ_OVERRIDE
- {
- ((*mObj).*mMethod)(mArg1);
- return NS_OK;
- }
-
-private:
- nsRefPtr mObj;
- Res (Obj::*mMethod)(Arg1);
- Tin1 mArg1;
-};
-
-template
-class BluetoothInterfaceRunnable3 : public nsRunnable
-{
-public:
- BluetoothInterfaceRunnable3(Obj* aObj,
- Res (Obj::*aMethod)(Arg1, Arg2, Arg3),
- const Arg1& aArg1, const Arg2& aArg2,
- const Arg3& aArg3)
- : mObj(aObj)
- , mMethod(aMethod)
- , mArg1(aArg1)
- , mArg2(aArg2)
- , mArg3(aArg3)
- {
- MOZ_ASSERT(mObj);
- MOZ_ASSERT(mMethod);
- }
-
- NS_METHOD
- Run() MOZ_OVERRIDE
- {
- ((*mObj).*mMethod)(mArg1, mArg2, mArg3);
- return NS_OK;
- }
-
-private:
- nsRefPtr mObj;
- Res (Obj::*mMethod)(Arg1, Arg2, Arg3);
- Tin1 mArg1;
- Tin2 mArg2;
- Tin3 mArg3;
-};
-
-//
-// Notification handling
-//
-
-template
-class BluetoothNotificationRunnable0 : public nsRunnable
-{
-public:
- typedef typename ObjectWrapper::ObjectType ObjectType;
- typedef BluetoothNotificationRunnable0 SelfType;
-
- static already_AddRefed Create(Res (ObjectType::*aMethod)())
- {
- nsRefPtr runnable(new SelfType(aMethod));
-
- return runnable.forget();
- }
-
- static void
- Dispatch(Res (ObjectType::*aMethod)())
- {
- nsRefPtr runnable = Create(aMethod);
-
- 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() MOZ_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);
- }
-
- Res (ObjectType::*mMethod)();
-};
-
-template
-class BluetoothNotificationRunnable1 : public nsRunnable
-{
-public:
- typedef typename ObjectWrapper::ObjectType ObjectType;
- typedef BluetoothNotificationRunnable1 SelfType;
-
- template
- static already_AddRefed Create(
- Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
- {
- nsRefPtr runnable(new SelfType(aMethod));
-
- if (NS_FAILED(runnable->ConvertAndSet(aIn1))) {
- return nullptr;
- }
- return runnable.forget();
- }
-
- template
- static void
- Dispatch(Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
- {
- nsRefPtr runnable = Create(aMethod, aIn1);
-
- 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() MOZ_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
- nsresult
- ConvertAndSet(const T1& aIn1)
- {
- nsresult rv = Convert(aIn1, mArg1);
- if (NS_FAILED(rv)) {
- return rv;
- }
- return NS_OK;
- }
-
- Res (ObjectType::*mMethod)(Arg1);
- Tin1 mArg1;
-};
-
-template