merge m-c to oak
authorRobert Strong <robert.bugzilla@gmail.com>
Tue, 23 Sep 2014 12:13:30 -0700
changeset 491277 6e4b7c3b7ba59edcbe6e01e6f822e4f0e9e34e45
parent 491276 5bc09eab2c55c379c641ba8508043afee3ea0134 (current diff)
parent 206693 9e193395b9128bc16fe160219b6e63b6dce479d5 (diff)
child 491278 1faa9b2bb5ff19386f7852893ba57cbfb7f1b1f3
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
milestone35.0a1
merge m-c to oak
dom/bluetooth2/bluedroid/BluetoothInterface.cpp
dom/bluetooth2/bluedroid/BluetoothInterface.h
intl/uconv/8859-1.ut
intl/uconv/nsISO88591ToUnicode.cpp
intl/uconv/ucvlatin/8859-11.uf
intl/uconv/ucvlatin/8859-9.uf
intl/uconv/ucvlatin/nsISO885911ToUnicode.cpp
intl/uconv/ucvlatin/nsISO885911ToUnicode.h
intl/uconv/ucvlatin/nsISO88599ToUnicode.cpp
intl/uconv/ucvlatin/nsISO88599ToUnicode.h
intl/uconv/ucvlatin/nsTIS620ToUnicode.cpp
intl/uconv/ucvlatin/nsTIS620ToUnicode.h
intl/uconv/ucvlatin/nsUnicodeToISO885911.cpp
intl/uconv/ucvlatin/nsUnicodeToISO885911.h
intl/uconv/ucvlatin/nsUnicodeToISO88599.cpp
intl/uconv/ucvlatin/nsUnicodeToISO88599.h
intl/uconv/ucvlatin/nsUnicodeToTIS620.cpp
intl/uconv/ucvlatin/nsUnicodeToTIS620.h
intl/uconv/ucvlatin/tis620.uf
mobile/android/search/res/drawable/search_card_background.xml
mobile/android/search/res/drawable/search_card_default.xml
mobile/android/search/res/drawable/search_card_pressed.xml
mobile/android/search/res/layout/search_card_history.xml
testing/web-platform/meta/media-source/URL-createObjectURL-revoke.html.ini
testing/web-platform/meta/media-source/mediasource-closed.html.ini
toolkit/modules/PermissionsUtils.jsm
toolkit/modules/tests/xpcshell/test_PermissionsUtils.js
toolkit/mozapps/extensions/test/xpcshell/test_permissions.js
toolkit/mozapps/extensions/test/xpcshell/test_permissions_prefs.js
toolkit/xre/nsAppRunner.cpp
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1063304 moved IPDL PMobileConnection into its own namespace and needed a clobber.
+Bug 1065897: Updated moz.build requires CLOBBER
--- a/b2g/components/ProcessGlobal.js
+++ b/b2g/components/ProcessGlobal.js
@@ -28,19 +28,47 @@ function debug(msg) {
 function log(msg) {
   // This file implements console.log(), so use dump().
   //dump('ProcessGlobal: ' + msg + '\n');
 }
 
 function formatStackFrame(aFrame) {
   let functionName = aFrame.functionName || '<anonymous>';
   return '    at ' + functionName +
-         ' (' + aFrame.filename + ':' + aFrame.lineNumber + ')';
+         ' (' + aFrame.filename + ':' + aFrame.lineNumber +
+         ':' + aFrame.columnNumber + ')';
 }
 
+function ConsoleMessage(aMsg, aLevel) {
+  this.timeStamp = Date.now();
+  this.msg = aMsg;
+
+  switch (aLevel) {
+    case 'error':
+    case 'assert':
+      this.logLevel = Ci.nsIConsoleMessage.error;
+      break;
+    case 'warn':
+      this.logLevel = Ci.nsIConsoleMessage.warn;
+      break;
+    case 'log':
+    case 'info':
+      this.logLevel = Ci.nsIConsoleMessage.info;
+      break;
+    default:
+      this.logLevel = Ci.nsIConsoleMessage.debug;
+      break;
+  }
+}
+
+ConsoleMessage.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIConsoleMessage]),
+  toString: function() { return this.msg; }
+};
+
 const gFactoryResetFile = "/persist/__post_reset_cmd__";
 
 function ProcessGlobal() {}
 ProcessGlobal.prototype = {
   classID: Components.ID('{1a94c87a-5ece-4d11-91e1-d29c29f21b28}'),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
 
@@ -126,17 +154,17 @@ ProcessGlobal.prototype = {
       } else {
         stackTrace = formatStackFrame(message);
       }
 
       if (stackTrace) {
         args.push('\n' + stackTrace);
       }
 
-      let prefix = 'Content JS ' + message.level.toUpperCase() + ': ';
-      Services.console.logStringMessage(prefix + Array.join(args, ' '));
+      let msg = 'Content JS ' + message.level.toUpperCase() + ': ' + Array.join(args, ' ');
+      Services.console.logMessage(new ConsoleMessage(msg, message.level));
       break;
     }
     }
   },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ProcessGlobal]);
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
+  <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
@@ -129,12 +129,12 @@
   <project name="android-development" path="development" remote="b2g" revision="dab55669da8f48b6e57df95d5af9f16b4a87b0b1"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="197cd9492b9fadaa915c5daf36ff557f8f4a8d1c"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="libnfcemu" path="external/libnfcemu" remote="b2g" revision="125ccf9bd5986c7728ea44508b3e1d1185ac028b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d259117b4976decbe2f76eeed85218bf0109190f"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9f28c4faea3b2f01db227b2467b08aeba96d9bec"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="54a712b46fe937dacdaed9b1261c63847129a719"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="8b1365af38c9a653df97349ee53a3f5d64fd590a"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
+  <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/releng-flame-kk.tt
+++ b/b2g/config/flame-kk/releng-flame-kk.tt
@@ -1,7 +1,8 @@
 [
-{"size": 118323840,
-"digest": "f18aabdf19ce8b630d9724ecf7d3a130e6b020a9e4d4e222bba6d4b3d4303c30dc3c5162a55b0f85de926077be59e17cfe49eb7314dca7e1bb5741a260148083",
-"filename": "backup-flame.tar.xz",
-"algorithm": "sha512"
+{
+"size": 91247216,
+"digest": "2b4be549f98695488ea7288d9e7f8ac0fa45112bedefa485a6e016c4af73fa21bb6b3992beda516f268417207c5deb57afad3959d3b1fbd07d5269b3a6be6a27",
+"algorithm": "sha512",
+"filename": "backup-flame.tar.xz"
 }
 ]
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
+  <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
@@ -146,13 +146,13 @@
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="2a1ded216a91bf62a72b1640cf01ab4998f37028"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="e5a971282719907f73fb1da964ca40aad67a3be0"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="9883ea57b0668d8f60dba025d4522dfa69a1fbfa"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="a558dc844bf5144fc38603fd8f4df8d9557052a5"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
   <project name="platform/system/core" path="system/core" revision="350eac5403124dacb2a5fd9e28ac290a59fc3b8e"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="54a712b46fe937dacdaed9b1261c63847129a719"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
   <project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
   <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="7704e16da545f4207812e593743d6743e1afb9c5"/>
 </manifest>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
@@ -140,13 +140,13 @@
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="5e110615212302c5d798a3c223dcee458817651c"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="fa9ffd47948eb24466de227e48fe9c4a7c5e7711"/>
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="cd76b19aafd4229ccf83853d02faef8c51ca8b34"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="8a0d0b0d9889ef99c4c6317c810db4c09295f15a"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="2208fa3537ace873b8f9ec2355055761c79dfd5f"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="c4e2ac95907a5519a0e09f01a0d8e27fec101af0"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="e1eb226fa3ad3874ea7b63c56a9dc7012d7ff3c2"/>
   <project name="platform/system/core" path="system/core" revision="adc485d8755af6a61641d197de7cfef667722580"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="54a712b46fe937dacdaed9b1261c63847129a719"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
   <project name="platform/system/qcom" path="system/qcom" revision="1cdab258b15258b7f9657da70e6f06ebd5a2fc25"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="4ae5df252123591d5b941191790e7abed1bce5a4"/>
   <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="ce18b47b4a4f93a581d672bbd5cb6d12fe796ca9"/>
 </manifest>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "536a583e498fedee95712dbb12b03ba212ed8064", 
+    "revision": "6890cdf5807b0c9a4341b97ee39fd692dc95fd0c", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
@@ -124,17 +124,17 @@
   <project name="platform/system/netd" path="system/netd" revision="56112dd7b811301b718d0643a82fd5cac9522073"/>
   <project name="platform/system/security" path="system/security" revision="f48ff68fedbcdc12b570b7699745abb6e7574907"/>
   <project name="platform/system/vold" path="system/vold" revision="8de05d4a52b5a91e7336e6baa4592f945a6ddbea"/>
   <default remote="caf" revision="refs/tags/android-4.3_r2.1" sync-j="4"/>
   <!-- Nexus 4 specific things -->
   <project name="device-mako" path="device/lge/mako" remote="b2g" revision="78d17f0c117f0c66dd55ee8d5c5dde8ccc93ecba"/>
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="3a9a17613cc685aa232432566ad6cc607eab4ec1"/>
   <project name="device/lge/mako-kernel" path="device/lge/mako-kernel" revision="d1729e53d71d711c8fde25eab8728ff2b9b4df0e"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="54a712b46fe937dacdaed9b1261c63847129a719"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="2a5dc67db7c9e6651c5fff855a6f69c1f2061ca7"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="7d33aaf740bbf6c7c6e9c34a92b371eda311b66b"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="0e56e450367cd802241b27164a2979188242b95f"/>
   <project name="platform/hardware/broadcom/wlan" path="hardware/broadcom/wlan" revision="0e1929fa3aa38bf9d40e9e953d619fab8164c82e"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="b0a528d839cfd9d170d092fe3743b5252b4243a6"/>
   <project name="platform/hardware/qcom/bt" path="hardware/qcom/bt" revision="380945eaa249a2dbdde0daa4c8adb8ca325edba6"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="6f3b0272cefaffeaed2a7d2bb8f633059f163ddc"/>
   <project name="platform/hardware/qcom/keymaster" path="hardware/qcom/keymaster" revision="16da8262c997a5a0d797885788a64a0771b26910"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="689b476ba3eb46c34b81343295fe144a0e81a18e"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3c898380b47f298cd3b7a0dacb3a6529e94322d4"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="37b8a812c642ca616bf9457cb9b71e45261cdfa8"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="b81855b6b67f285d6f27a4f8c1cfe2e0387ea57c"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f3e998242fb9a857cf50f5bf3a02304a530ea617"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/app/default_permissions
+++ b/browser/app/default_permissions
@@ -1,9 +1,16 @@
 # This file has default permissions for the permission manager.
 # The file-format is strict:
 # * matchtype \t type \t permission \t host
 # * Only "host" is supported for matchtype
 # * type is a string that identifies the type of permission (e.g. "cookie")
 # * permission is an integer between 1 and 15
 # See nsPermissionManager.cpp for more...
 
-# (This file is intentionally blank for the moment...)
+# UITour
+host	uitour	1	www.mozilla.org
+host	uitour	1	support.mozilla.org
+host	uitour	1	about:home
+
+# XPInstall
+host	install	1	addons.mozilla.org
+host	install	1	marketplace.firefox.com
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -239,31 +239,26 @@ pref("extensions.update.interval", 86400
 // Non-symmetric (not shared by extensions) extension-specific [update] preferences
 pref("extensions.dss.enabled", false);          // Dynamic Skin Switching                                               
 pref("extensions.dss.switchPending", false);    // Non-dynamic switch pending after next
                                                 // restart.
 
 pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties");
 pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties");
 
-pref("xpinstall.whitelist.add", "addons.mozilla.org");
-pref("xpinstall.whitelist.add.180", "marketplace.firefox.com");
-
 pref("lightweightThemes.update.enabled", true);
 pref("lightweightThemes.getMoreURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes");
 pref("lightweightThemes.recommendedThemes", "[{\"id\":\"recommended-1\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/a-web-browser-renaissance/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.footer.jpg\",\"textcolor\":\"#000000\",\"accentcolor\":\"#f2d9b1\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.preview.jpg\",\"author\":\"Sean.Martell\",\"version\":\"0\"},{\"id\":\"recommended-2\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/space-fantasy/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.footer.jpg\",\"textcolor\":\"#ffffff\",\"accentcolor\":\"#d9d9d9\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.preview.jpg\",\"author\":\"fx5800p\",\"version\":\"1.0\"},{\"id\":\"recommended-3\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/linen-light/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.footer.png\",\"textcolor\":\"#None\",\"accentcolor\":\"#ada8a8\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/3.preview.png\",\"author\":\"DVemer\",\"version\":\"1.0\"},{\"id\":\"recommended-4\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/pastel-gradient/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.footer.png\",\"textcolor\":\"#000000\",\"accentcolor\":\"#000000\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.preview.png\",\"author\":\"darrinhenein\",\"version\":\"1.0\"},{\"id\":\"recommended-5\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/carbon-light/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.footer.png\",\"textcolor\":\"#3b3b3b\",\"accentcolor\":\"#2e2e2e\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/5.preview.jpg\",\"author\":\"Jaxivo\",\"version\":\"1.0\"}]");
 
 // UI tour experience.
 pref("browser.uitour.enabled", true);
 pref("browser.uitour.requireSecure", true);
 pref("browser.uitour.themeOrigin", "https://addons.mozilla.org/%LOCALE%/firefox/themes/");
 pref("browser.uitour.pinnedTabUrl", "https://support.mozilla.org/%LOCALE%/kb/pinned-tabs-keep-favorite-websites-open");
 pref("browser.uitour.url", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/tour/");
-pref("browser.uitour.whitelist.add.260", "www.mozilla.org,support.mozilla.org");
-pref("browser.uitour.whitelist.add.340", "about:home");
 
 pref("browser.customizemode.tip0.shown", false);
 pref("browser.customizemode.tip0.learnMoreUrl", "https://support.mozilla.org/1/firefox/%VERSION%/%OS%/%LOCALE%/customize");
 
 pref("keyword.enabled", true);
 pref("browser.fixup.domainwhitelist.localhost", true);
 
 pref("general.useragent.locale", "@AB_CD@");
--- a/browser/base/content/newtab/grid.js
+++ b/browser/base/content/newtab/grid.js
@@ -188,16 +188,23 @@ let gGrid = {
         this.createSite(links[i], cells[i]);
     }
   },
 
   /**
    * Make sure the correct number of rows and columns are visible
    */
   _resizeGrid: function Grid_resizeGrid() {
+    // If we're somehow called before the page has finished loading,
+    // let's bail out to avoid caching zero heights and widths.
+    // We'll be called again when the load event fires.
+    if (document.readyState != "complete") {
+      return;
+    }
+
     // Save the cell's computed height/width including margin and border
     if (this._cellMargin === undefined) {
       let refCell = document.querySelector(".newtab-cell");
       this._cellMargin = parseFloat(getComputedStyle(refCell).marginTop) * 2;
       this._cellHeight = refCell.offsetHeight + this._cellMargin;
       this._cellWidth = refCell.offsetWidth + this._cellMargin;
     }
 
--- a/browser/base/content/test/general/browser_sanitize-sitepermissions.js
+++ b/browser/base/content/test/general/browser_sanitize-sitepermissions.js
@@ -1,37 +1,52 @@
 // Bug 380852 - Delete permission manager entries in Clear Recent History
 
 let tempScope = {};
 Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader)
                                            .loadSubScript("chrome://browser/content/sanitize.js", tempScope);
 let Sanitizer = tempScope.Sanitizer;
 
+function countPermissions() {
+  let result = 0;
+  let enumerator = Services.perms.enumerator;
+  while (enumerator.hasMoreElements()) {
+    result++;
+    enumerator.getNext();
+  }
+  return result;
+}
+
 function test() {
-  
-  // Add a permission entry
-  var pm = Services.perms;
-  pm.add(makeURI("http://example.com"), "testing", pm.ALLOW_ACTION);
-  
-  // Sanity check
-  ok(pm.enumerator.hasMoreElements(), "Permission manager should have elements, since we just added one");
-  
+  // sanitize before we start so we have a good baseline.
   // Set up the sanitizer to just clear siteSettings
   let s = new Sanitizer();
   s.ignoreTimespan = false;
   s.prefDomain = "privacy.cpd.";
   var itemPrefs = gPrefService.getBranch(s.prefDomain);
   itemPrefs.setBoolPref("history", false);
   itemPrefs.setBoolPref("downloads", false);
   itemPrefs.setBoolPref("cache", false);
   itemPrefs.setBoolPref("cookies", false);
   itemPrefs.setBoolPref("formdata", false);
   itemPrefs.setBoolPref("offlineApps", false);
   itemPrefs.setBoolPref("passwords", false);
   itemPrefs.setBoolPref("sessions", false);
   itemPrefs.setBoolPref("siteSettings", true);
-  
+  s.sanitize();
+
+  // Count how many permissions we start with - some are defaults that
+  // will not be sanitized.
+  let numAtStart = countPermissions();
+
+  // Add a permission entry
+  var pm = Services.perms;
+  pm.add(makeURI("http://example.com"), "testing", pm.ALLOW_ACTION);
+
+  // Sanity check
+  ok(pm.enumerator.hasMoreElements(), "Permission manager should have elements, since we just added one");
+
   // Clear it
   s.sanitize();
-  
+
   // Make sure it's gone
-  ok(!pm.enumerator.hasMoreElements(), "Permission manager shouldn't have entries after Sanitizing");
+  is(numAtStart, countPermissions(), "Permission manager should have the same count it started with");
 }
--- a/browser/components/loop/MozLoopAPI.jsm
+++ b/browser/components/loop/MozLoopAPI.jsm
@@ -453,16 +453,24 @@ function injectLoopAPI(targetWindow) {
     logOutFromFxA: {
       enumerable: true,
       writable: true,
       value: function() {
         return MozLoopService.logOutFromFxA();
       }
     },
 
+    openFxASettings: {
+      enumerable: true,
+      writable: true,
+      value: function() {
+        return MozLoopService.openFxASettings();
+      },
+    },
+
     /**
      * Copies passed string onto the system clipboard.
      *
      * @param {String} str The string to copy
      */
     copyString: {
       enumerable: true,
       writable: true,
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -21,16 +21,17 @@ const LOOP_SESSION_TYPE = {
 };
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/osfile.jsm", this);
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm");
+Cu.importGlobalProperties(["URL"]);
 
 this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE"];
 
 XPCOMUtils.defineLazyModuleGetter(this, "console",
   "resource://gre/modules/devtools/Console.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "injectLoopAPI",
   "resource:///modules/loop/MozLoopAPI.jsm");
@@ -1350,16 +1351,22 @@ this.MozLoopService = {
     gFxAOAuthClient = null;
     gFxAOAuthClientPromise = null;
 
     // clearError calls notifyStatusChanged so should be done last when the
     // state is clean.
     MozLoopServiceInternal.clearError("registration");
   }),
 
+  openFxASettings: function() {
+    let url = new URL("/settings", gFxAOAuthClient.parameters.content_uri);
+    let win = Services.wm.getMostRecentWindow("navigator:browser");
+    win.switchToTabHavingURI(url.toString(), true);
+  },
+
   /**
    * Performs a hawk based request to the loop server.
    *
    * @param {LOOP_SESSION_TYPE} sessionType The type of session to use for the request.
    *                                        One of the LOOP_SESSION_TYPE members.
    * @param {String} path The path to make the request to.
    * @param {String} method The request method, e.g. 'POST', 'GET'.
    * @param {Object} payloadObj An object which is converted to JSON and
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -208,21 +208,21 @@ loop.panel = (function(_, mozL10n) {
 
   /**
    * Panel settings (gear) menu.
    */
   var SettingsDropdown = React.createClass({displayName: 'SettingsDropdown',
     mixins: [sharedMixins.DropdownMenuMixin],
 
     handleClickSettingsEntry: function() {
-      // XXX to be implemented
+      // XXX to be implemented at the same time as unhiding the entry
     },
 
     handleClickAccountEntry: function() {
-      // XXX to be implemented
+      navigator.mozLoop.openFxASettings();
     },
 
     handleClickAuthEntry: function() {
       if (this._isSignedIn()) {
         navigator.mozLoop.logOutFromFxA();
       } else {
         navigator.mozLoop.logInToFxA();
       }
@@ -237,16 +237,17 @@ loop.panel = (function(_, mozL10n) {
       return (
         React.DOM.div({className: "settings-menu dropdown"}, 
           React.DOM.a({className: "btn btn-settings", onClick: this.showDropdownMenu, 
              title: __("settings_menu_button_tooltip")}), 
           React.DOM.ul({className: cx({"dropdown-menu": true, hide: !this.state.showMenu}), 
               onMouseLeave: this.hideDropdownMenu}, 
             SettingsDropdownEntry({label: __("settings_menu_item_settings"), 
                                    onClick: this.handleClickSettingsEntry, 
+                                   displayed: false, 
                                    icon: "settings"}), 
             SettingsDropdownEntry({label: __("settings_menu_item_account"), 
                                    onClick: this.handleClickAccountEntry, 
                                    icon: "account", 
                                    displayed: this._isSignedIn()}), 
             SettingsDropdownEntry({label: this._isSignedIn() ?
                                           __("settings_menu_item_signout") :
                                           __("settings_menu_item_signin"), 
@@ -422,17 +423,17 @@ loop.panel = (function(_, mozL10n) {
    * FxA sign in/up link component.
    */
   var AuthLink = React.createClass({displayName: 'AuthLink',
     handleSignUpLinkClick: function() {
       navigator.mozLoop.logInToFxA();
     },
 
     render: function() {
-      if (navigator.mozLoop.loggedInToFxA) { // XXX to be implemented
+      if (navigator.mozLoop.userProfile) {
         return null;
       }
       return (
         React.DOM.p({className: "signin-link"}, 
           React.DOM.a({href: "#", onClick: this.handleSignUpLinkClick}, 
             __("panel_footer_signin_or_signup_link")
           )
         )
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -208,21 +208,21 @@ loop.panel = (function(_, mozL10n) {
 
   /**
    * Panel settings (gear) menu.
    */
   var SettingsDropdown = React.createClass({
     mixins: [sharedMixins.DropdownMenuMixin],
 
     handleClickSettingsEntry: function() {
-      // XXX to be implemented
+      // XXX to be implemented at the same time as unhiding the entry
     },
 
     handleClickAccountEntry: function() {
-      // XXX to be implemented
+      navigator.mozLoop.openFxASettings();
     },
 
     handleClickAuthEntry: function() {
       if (this._isSignedIn()) {
         navigator.mozLoop.logOutFromFxA();
       } else {
         navigator.mozLoop.logInToFxA();
       }
@@ -237,16 +237,17 @@ loop.panel = (function(_, mozL10n) {
       return (
         <div className="settings-menu dropdown">
           <a className="btn btn-settings" onClick={this.showDropdownMenu}
              title={__("settings_menu_button_tooltip")} />
           <ul className={cx({"dropdown-menu": true, hide: !this.state.showMenu})}
               onMouseLeave={this.hideDropdownMenu}>
             <SettingsDropdownEntry label={__("settings_menu_item_settings")}
                                    onClick={this.handleClickSettingsEntry}
+                                   displayed={false}
                                    icon="settings" />
             <SettingsDropdownEntry label={__("settings_menu_item_account")}
                                    onClick={this.handleClickAccountEntry}
                                    icon="account"
                                    displayed={this._isSignedIn()} />
             <SettingsDropdownEntry label={this._isSignedIn() ?
                                           __("settings_menu_item_signout") :
                                           __("settings_menu_item_signin")}
@@ -422,17 +423,17 @@ loop.panel = (function(_, mozL10n) {
    * FxA sign in/up link component.
    */
   var AuthLink = React.createClass({
     handleSignUpLinkClick: function() {
       navigator.mozLoop.logInToFxA();
     },
 
     render: function() {
-      if (navigator.mozLoop.loggedInToFxA) { // XXX to be implemented
+      if (navigator.mozLoop.userProfile) {
         return null;
       }
       return (
         <p className="signin-link">
           <a href="#" onClick={this.handleSignUpLinkClick}>
             {__("panel_footer_signin_or_signup_link")}
           </a>
         </p>
--- a/browser/components/loop/content/shared/css/panel.css
+++ b/browser/components/loop/content/shared/css/panel.css
@@ -216,17 +216,16 @@ body[dir=rtl] .dropdown-menu-item {
 
 .status-dnd {
   border: 1px solid #888;
 }
 
 /* Sign in/up link */
 
 .signin-link {
-  display: none; /* XXX This should be displayed as soon bug 979845 lands */
   flex: 2 1 auto;
   margin-top: 14px;
   border-right: 1px solid #aaa;
   padding-right: 1em;
   margin-right: 1em;
   text-align: right;
 }
 
@@ -234,17 +233,16 @@ body[dir=rtl] .dropdown-menu-item {
   font-size: .9em;
   text-decoration: none;
   color: #888;
 }
 
 /* Settings (gear) menu */
 
 .btn-settings {
-  display: none; /* XXX This should be displayed as soon bug 979845 lands */
   background: transparent url(../img/svg/glyph-settings-16x16.svg) no-repeat center center;
   background-size: contain;
   width: 12px;
   height: 12px;
 }
 
 .footer .btn-settings {
   margin-top: 17px; /* used to align the gear icon with the availability dropdown menu inner text */
--- a/browser/components/loop/test/desktop-local/panel_test.js
+++ b/browser/components/loop/test/desktop-local/panel_test.js
@@ -186,16 +186,17 @@ describe("loop.panel", function() {
       });
 
     describe("SettingsDropdown", function() {
       var view;
 
       beforeEach(function() {
         navigator.mozLoop.logInToFxA = sandbox.stub();
         navigator.mozLoop.logOutFromFxA = sandbox.stub();
+        navigator.mozLoop.openFxASettings = sandbox.stub();
       });
 
       it("should show a signin entry when user is not authenticated",
         function() {
           navigator.mozLoop.loggedInToFxA = false;
 
           var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown());
 
@@ -220,16 +221,27 @@ describe("loop.panel", function() {
         navigator.mozLoop.userProfile = {email: "test@example.com"};
 
         var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown());
 
         expect(view.getDOMNode().querySelectorAll(".icon-account"))
           .to.have.length.of(1);
       });
 
+      it("should open the FxA settings when the account entry is clicked", function() {
+        navigator.mozLoop.userProfile = {email: "test@example.com"};
+
+        var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown());
+
+        TestUtils.Simulate.click(
+          view.getDOMNode().querySelector(".icon-account"));
+
+        sinon.assert.calledOnce(navigator.mozLoop.openFxASettings);
+      });
+
       it("should hide any account entry when user is not authenticated",
         function() {
           navigator.mozLoop.loggedInToFxA = false;
 
           var view = TestUtils.renderIntoDocument(loop.panel.SettingsDropdown());
 
           expect(view.getDOMNode().querySelectorAll(".icon-account"))
             .to.have.length.of(0);
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -736,16 +736,20 @@ BrowserGlue.prototype = {
     WebappManager.uninit();
 #ifdef NIGHTLY_BUILD
     if (Services.prefs.getBoolPref("dom.identity.enabled")) {
       SignInToWebsiteUX.uninit();
     }
 #endif
     webrtcUI.uninit();
     FormValidationHandler.uninit();
+
+    // XXX: Temporary hack to allow Loop FxA login after a restart to work.
+    // Remove this once bug 1071247 is deployed.
+    Services.prefs.clearUserPref("loop.hawk-session-token.fxa");
   },
 
   // All initial windows have opened.
   _onWindowsRestored: function BG__onWindowsRestored() {
     // Show update notification, if needed.
     if (Services.prefs.prefHasUserValue("app.update.postupdate"))
       this._showUpdateNotification();
 
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -124,18 +124,16 @@ PlacesController.prototype = {
     // filters out other commands that we do _not_ support (see 329587).
     const CMD_PREFIX = "placesCmd_";
     return (aCommand.substr(0, CMD_PREFIX.length) == CMD_PREFIX);
   },
 
   isCommandEnabled: function PC_isCommandEnabled(aCommand) {
     if (PlacesUIUtils.useAsyncTransactions) {
       switch (aCommand) {
-      case "cmd_delete":
-      case "placesCmd_delete":
       case "placesCmd_new:folder":
       case "placesCmd_new:bookmark":
       case "placesCmd_createBookmark":
         return false;
       }
     }
 
     switch (aCommand) {
@@ -238,17 +236,17 @@ PlacesController.prototype = {
       this.copy();
       break;
     case "cmd_paste":
     case "placesCmd_paste":
       this.paste().then(null, Components.utils.reportError);
       break;
     case "cmd_delete":
     case "placesCmd_delete":
-      this.remove("Remove Selection");
+      this.remove("Remove Selection").then(null, Components.utils.reportError);
       break;
     case "placesCmd_deleteDataHost":
       var host;
       if (PlacesUtils.nodeIsHost(this._view.selectedNode)) {
         var queries = this._view.selectedNode.getQueries();
         host = queries[0].domain;
       }
       else
@@ -868,32 +866,45 @@ PlacesController.prototype = {
       if (this._shouldSkipNode(node, removedFolders))
         continue;
 
       if (PlacesUtils.nodeIsTagQuery(node.parent)) {
         // This is a uri node inside a tag container.  It needs a special
         // untag transaction.
         var tagItemId = PlacesUtils.getConcreteItemId(node.parent);
         var uri = NetUtil.newURI(node.uri);
-        let txn = new PlacesUntagURITransaction(uri, [tagItemId]);
-        transactions.push(txn);
+        if (PlacesUIUtils.useAsyncTransactions) {
+          let tag = node.parent.title;
+          if (!tag)
+            tag = PlacesUtils.bookmarks.getItemTitle(tagItemId);
+          transactions.push(PlacesTransactions.Untag({ uri: uri, tag: tag }));
+        }
+        else {
+          let txn = new PlacesUntagURITransaction(uri, [tagItemId]);
+          transactions.push(txn);
+        }
       }
       else if (PlacesUtils.nodeIsTagQuery(node) && node.parent &&
                PlacesUtils.nodeIsQuery(node.parent) &&
                PlacesUtils.asQuery(node.parent).queryOptions.resultType ==
                  Ci.nsINavHistoryQueryOptions.RESULTS_AS_TAG_QUERY) {
         // This is a tag container.
         // Untag all URIs tagged with this tag only if the tag container is
         // child of the "Tags" query in the library, in all other places we
         // must only remove the query node.
-        var tag = node.title;
-        var URIs = PlacesUtils.tagging.getURIsForTag(tag);
-        for (var j = 0; j < URIs.length; j++) {
-          let txn = new PlacesUntagURITransaction(URIs[j], [tag]);
-          transactions.push(txn);
+        let tag = node.title;
+        let URIs = PlacesUtils.tagging.getURIsForTag(tag);
+        if (PlacesUIUtils.useAsyncTransactions) {
+          transactions.push(PlacesTransactions.Untag({ tag: tag, uris: URIs }));
+        }
+        else {
+          for (var j = 0; j < URIs.length; j++) {
+            let txn = new PlacesUntagURITransaction(URIs[j], [tag]);
+            transactions.push(txn);
+          }
         }
       }
       else if (PlacesUtils.nodeIsURI(node) &&
                PlacesUtils.nodeIsQuery(node.parent) &&
                PlacesUtils.asQuery(node.parent).queryOptions.queryType ==
                  Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
         // This is a uri node inside an history query.
         PlacesUtils.bhistory.removePage(NetUtil.newURI(node.uri));
@@ -911,40 +922,51 @@ PlacesController.prototype = {
       }
       else {
         // This is a common bookmark item.
         if (PlacesUtils.nodeIsFolder(node)) {
           // If this is a folder we add it to our array of folders, used
           // to skip nodes that are children of an already removed folder.
           removedFolders.push(node);
         }
-        let txn = new PlacesRemoveItemTransaction(node.itemId);
-        transactions.push(txn);
+        if (PlacesUIUtils.useAsyncTransactions) {
+          transactions.push(
+            PlacesTransactions.Remove({ guid: node.bookmarkGuid }));
+        }
+        else {
+          let txn = new PlacesRemoveItemTransaction(node.itemId);
+          transactions.push(txn);
+        }
       }
     }
   },
 
   /**
    * Removes the set of selected ranges from bookmarks.
    * @param   txnName
    *          See |remove|.
    */
-  _removeRowsFromBookmarks: function PC__removeRowsFromBookmarks(txnName) {
+  _removeRowsFromBookmarks: Task.async(function* (txnName) {
     var ranges = this._view.removableSelectionRanges;
     var transactions = [];
     var removedFolders = [];
 
     for (var i = 0; i < ranges.length; i++)
       this._removeRange(ranges[i], transactions, removedFolders);
 
     if (transactions.length > 0) {
-      var txn = new PlacesAggregatedTransaction(txnName, transactions);
-      PlacesUtils.transactionManager.doTransaction(txn);
+      if (PlacesUIUtils.useAsyncTransactions) {
+        yield PlacesTransactions.transact(transactions);
+      }
+      else {
+        var txn = new PlacesAggregatedTransaction(txnName, transactions);
+        PlacesUtils.transactionManager.doTransaction(txn);
+      }
     }
-  },
+  }),
 
   /**
    * Removes the set of selected ranges from history.
    *
    * @note history deletes are not undoable.
    */
   _removeRowsFromHistory: function PC__removeRowsFromHistory() {
     let nodes = this._view.selectedNodes;
@@ -969,17 +991,17 @@ PlacesController.prototype = {
     function pagesChunkGenerator(aURIs) {
       while (aURIs.length) {
         let URIslice = aURIs.splice(0, REMOVE_PAGES_CHUNKLEN);
         PlacesUtils.bhistory.removePages(URIslice, URIslice.length);
         Services.tm.mainThread.dispatch(function() {
           try {
             gen.next();
           } catch (ex if ex instanceof StopIteration) {}
-        }, Ci.nsIThread.DISPATCH_NORMAL); 
+        }, Ci.nsIThread.DISPATCH_NORMAL);
         yield undefined;
       }
     }
     let gen = pagesChunkGenerator(URIs);
     gen.next();
   },
 
   /**
@@ -1010,38 +1032,48 @@ PlacesController.prototype = {
   },
 
   /**
    * Removes the selection
    * @param   aTxnName
    *          A name for the transaction if this is being performed
    *          as part of another operation.
    */
-  remove: function PC_remove(aTxnName) {
+  remove: Task.async(function* (aTxnName) {
     if (!this._hasRemovableSelection(false))
       return;
 
     NS_ASSERT(aTxnName !== undefined, "Must supply Transaction Name");
 
     var root = this._view.result.root;
 
-    if (PlacesUtils.nodeIsFolder(root))
-      this._removeRowsFromBookmarks(aTxnName);
+    if (PlacesUtils.nodeIsFolder(root)) {
+      if (PlacesUIUtils.useAsyncTransactions)
+        yield this._removeRowsFromBookmarks(aTxnName);
+      else
+        this._removeRowsFromBookmarks(aTxnName);
+    }
     else if (PlacesUtils.nodeIsQuery(root)) {
       var queryType = PlacesUtils.asQuery(root).queryOptions.queryType;
-      if (queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS)
-        this._removeRowsFromBookmarks(aTxnName);
-      else if (queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY)
+      if (queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS) {
+        if (PlacesUIUtils.useAsyncTransactions)
+          yield this._removeRowsFromBookmarks(aTxnName);
+        else
+          this._removeRowsFromBookmarks(aTxnName);
+      }
+      else if (queryType == Ci.nsINavHistoryQueryOptions.QUERY_TYPE_HISTORY) {
         this._removeRowsFromHistory();
-      else
+      }
+      else {
         NS_ASSERT(false, "implement support for QUERY_TYPE_UNIFIED");
+      }
     }
     else
       NS_ASSERT(false, "unexpected root");
-  },
+  }),
 
   /**
    * Fills a DataTransfer object with the content of the selection that can be
    * dropped elsewhere.
    * @param   aEvent
    *          The dragstart event.
    */
   setDataTransfer: function PC_setDataTransfer(aEvent) {
@@ -1444,18 +1476,18 @@ let PlacesControllerDragHelper = {
    *        The flavors list of type DOMStringList.
    */
   getFirstValidFlavor: function PCDH_getFirstValidFlavor(aFlavors) {
     for (let i = 0; i < aFlavors.length; i++) {
       if (PlacesUIUtils.SUPPORTED_FLAVORS.indexOf(aFlavors[i]) != -1)
         return aFlavors[i];
     }
 
-    // If no supported flavor is found, check if data includes text/plain 
-    // contents.  If so, request them as text/unicode, a conversion will happen 
+    // If no supported flavor is found, check if data includes text/plain
+    // contents.  If so, request them as text/unicode, a conversion will happen
     // automatically.
     if (aFlavors.contains("text/plain")) {
         return PlacesUtils.TYPE_UNICODE;
     }
 
     return null;
   },
 
@@ -1731,17 +1763,17 @@ function goUpdatePlacesCommands() {
   updatePlacesCommand("placesCmd_paste");
   updatePlacesCommand("placesCmd_delete");
 }
 
 function doGetPlacesControllerForCommand(aCommand)
 {
   // A context menu may be built for non-focusable views.  Thus, we first try
   // to look for a view associated with document.popupNode
-  let popupNode; 
+  let popupNode;
   try {
     popupNode = document.popupNode;
   } catch (e) {
     // The document went away (bug 797307).
     return null;
   }
   if (popupNode) {
     let view = PlacesUIUtils.getViewForNode(popupNode);
--- a/browser/components/places/content/editBookmarkOverlay.xul
+++ b/browser/components/places/content/editBookmarkOverlay.xul
@@ -9,82 +9,70 @@
 
 <?xml-stylesheet href="chrome://browser/skin/places/editBookmarkOverlay.css"?>
 <?xml-stylesheet href="chrome://browser/skin/places/places.css"?>
 
 <overlay id="editBookmarkOverlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <vbox id="editBookmarkPanelContent" flex="1">
-    <broadcaster id="paneElementsBroadcaster"/>
-
     <hbox id="editBMPanel_selectionCount" hidden="true" pack="center">
       <label id="editBMPanel_itemsCountText"/>
     </hbox>
 
     <grid id="editBookmarkPanelGrid" flex="1">
       <columns id="editBMPanel_columns">
         <column id="editBMPanel_labelColumn" />
         <column flex="1" id="editBMPanel_editColumn" />
       </columns>
       <rows id="editBMPanel_rows">
         <row align="center" id="editBMPanel_nameRow">
           <label value="&editBookmarkOverlay.name.label;"
                  class="editBMPanel_rowLabel"
                  accesskey="&editBookmarkOverlay.name.accesskey;"
-                 control="editBMPanel_namePicker"
-                 observes="paneElementsBroadcaster"/>
-          <textbox id="editBMPanel_namePicker"
-                   observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_namePicker"/>
+          <textbox id="editBMPanel_namePicker"/>
         </row>
 
         <row align="center" id="editBMPanel_locationRow">
           <label value="&editBookmarkOverlay.location.label;"
                  class="editBMPanel_rowLabel"
                  accesskey="&editBookmarkOverlay.location.accesskey;"
-                 control="editBMPanel_locationField"
-                 observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_locationField"/>
           <textbox id="editBMPanel_locationField"
-                   class="uri-element"
-                   observes="paneElementsBroadcaster"/>
+                   class="uri-element"/>
         </row>
 
         <row align="center" id="editBMPanel_feedLocationRow">
           <label value="&editBookmarkOverlay.feedLocation.label;"
                  class="editBMPanel_rowLabel"
                  accesskey="&editBookmarkOverlay.feedLocation.accesskey;"
-                 control="editBMPanel_feedLocationField"
-                 observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_feedLocationField"/>
           <textbox id="editBMPanel_feedLocationField"
-                   class="uri-element"
-                   observes="paneElementsBroadcaster"/>
+                   class="uri-element"/>
         </row>
 
         <row align="center" id="editBMPanel_siteLocationRow">
           <label value="&editBookmarkOverlay.siteLocation.label;"
                  class="editBMPanel_rowLabel"
                  accesskey="&editBookmarkOverlay.siteLocation.accesskey;"
-                 control="editBMPanel_siteLocationField"
-                 observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_siteLocationField"/>
           <textbox id="editBMPanel_siteLocationField"
-                   class="uri-element"
-                   observes="paneElementsBroadcaster"/>
+                   class="uri-element"/>
         </row>
 
         <row align="center" id="editBMPanel_folderRow">
           <label value="&editBookmarkOverlay.folder.label;"
                  class="editBMPanel_rowLabel"
-                 control="editBMPanel_folderMenuList"
-                 observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_folderMenuList"/>
           <hbox flex="1" align="center">
             <menulist id="editBMPanel_folderMenuList"
                       class="folder-icon"
                       flex="1"
-                      oncommand="gEditItemOverlay.onFolderMenuListCommand(event);"
-                      observes="paneElementsBroadcaster">
+                      oncommand="gEditItemOverlay.onFolderMenuListCommand(event);">
               <menupopup>
                 <!-- Static item for special folders -->
                 <menuitem id="editBMPanel_toolbarFolderItem"
                           class="menuitem-iconic folder-icon"/>
                 <menuitem id="editBMPanel_bmRootItem"
                           class="menuitem-iconic folder-icon"/>
                 <menuitem id="editBMPanel_unfiledRootItem"
                           class="menuitem-iconic folder-icon"/>
@@ -95,34 +83,32 @@
                 <menuseparator id="editBMPanel_foldersSeparator" hidden="true"/>
               </menupopup>
             </menulist>
             <button id="editBMPanel_foldersExpander"
                     class="expander-down"
                     tooltiptext="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
                     tooltiptextdown="&editBookmarkOverlay.foldersExpanderDown.tooltip;"
                     tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
-                    oncommand="gEditItemOverlay.toggleFolderTreeVisibility();"
-                    observes="paneElementsBroadcaster"/>
+                    oncommand="gEditItemOverlay.toggleFolderTreeVisibility();"/>
           </hbox>
         </row>
 
         <row id="editBMPanel_folderTreeRow" collapsed="true" flex="1">
           <spacer/>
           <vbox flex="1">
             <tree id="editBMPanel_folderTree"
                   flex="1"
                   class="placesTree"
                   type="places"
                   height="150"
                   minheight="150"
                   editable="true"
                   onselect="gEditItemOverlay.onFolderTreeSelect();"
-                  hidecolumnpicker="true"
-                  observes="paneElementsBroadcaster">
+                  hidecolumnpicker="true">
               <treecols>
                 <treecol anonid="title" flex="1" primary="true" hideheader="true"/>
               </treecols>
               <treechildren flex="1"/>
             </tree>
 
             <hbox id="editBMPanel_newFolderBox">
               <button label="&editBookmarkOverlay.newFolderButton.label;"
@@ -132,81 +118,70 @@
             </hbox>
           </vbox>
         </row>
 
         <row align="center" id="editBMPanel_tagsRow">
           <label value="&editBookmarkOverlay.tags.label;"
                  class="editBMPanel_rowLabel"
                  accesskey="&editBookmarkOverlay.tags.accesskey;"
-                 control="editBMPanel_tagsField"
-                 observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_tagsField"/>
           <hbox flex="1" align="center">
             <textbox id="editBMPanel_tagsField"
                      type="autocomplete"
                      class="padded"
                      flex="1"
                      autocompletesearch="places-tag-autocomplete" 
                      completedefaultindex="true"
                      tabscrolling="true"
                      showcommentcolumn="true"
-                     observes="paneElementsBroadcaster"
                      placeholder="&editBookmarkOverlay.tagsEmptyDesc.label;"
-                     maxlength="1000"
-                     />
+                     maxlength="1000"/>
             <button id="editBMPanel_tagsSelectorExpander"
                     class="expander-down"
                     tooltiptext="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
                     tooltiptextdown="&editBookmarkOverlay.tagsExpanderDown.tooltip;"
                     tooltiptextup="&editBookmarkOverlay.expanderUp.tooltip;"
-                    oncommand="gEditItemOverlay.toggleTagsSelector();"
-                    observes="paneElementsBroadcaster"/>
+                    oncommand="gEditItemOverlay.toggleTagsSelector();"/>
           </hbox>
         </row>
 
         <row id="editBMPanel_tagsSelectorRow"
              align="center"
              collapsed="true">
           <spacer/>
           <listbox id="editBMPanel_tagsSelector"
-                   height="150"
-                   observes="paneElementsBroadcaster"/>
+                   height="150"/>
         </row>
 
         <row align="center" id="editBMPanel_keywordRow">
           <observes element="additionalInfoBroadcaster" attribute="hidden"/>
           <label value="&editBookmarkOverlay.keyword.label;"
                  class="editBMPanel_rowLabel"
                  accesskey="&editBookmarkOverlay.keyword.accesskey;"
-                 control="editBMPanel_keywordField"
-                 observes="paneElementsBroadcaster"/>
-          <textbox id="editBMPanel_keywordField"
-                   observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_keywordField"/>
+          <textbox id="editBMPanel_keywordField"/>
         </row>
 
         <row id="editBMPanel_descriptionRow">
           <observes element="additionalInfoBroadcaster" attribute="hidden"/>
           <label value="&editBookmarkOverlay.description.label;"
                  class="editBMPanel_rowLabel"
                  accesskey="&editBookmarkOverlay.description.accesskey;"
-                 control="editBMPanel_descriptionField"
-                 observes="paneElementsBroadcaster"/>
+                 control="editBMPanel_descriptionField"/>
           <textbox id="editBMPanel_descriptionField"
-                   multiline="true"
-                   observes="paneElementsBroadcaster"/>
+                   multiline="true"/>
         </row>
       </rows>
     </grid>
 
     <checkbox id="editBMPanel_loadInSidebarCheckbox"
               label="&editBookmarkOverlay.loadInSidebar.label;"
               accesskey="&editBookmarkOverlay.loadInSidebar.accesskey;"
-              oncommand="gEditItemOverlay.onLoadInSidebarCheckboxCommand();"
-              observes="paneElementsBroadcaster">
+              oncommand="gEditItemOverlay.onLoadInSidebarCheckboxCommand();">
       <observes element="additionalInfoBroadcaster" attribute="hidden"/>
     </checkbox>
 
     <!-- If the ids are changing or additional fields are being added, be sure
          to sync the values in places.js -->
     <broadcaster id="additionalInfoBroadcaster"/>
-
   </vbox>
 </overlay>
--- a/browser/components/places/content/places.js
+++ b/browser/components/places/content/places.js
@@ -556,29 +556,16 @@ var PlacesOrganizer = {
             Ci.nsIFilePicker.modeSave);
     fp.appendFilter(PlacesUIUtils.getString("bookmarksRestoreFilterName"),
                     RESTORE_FILEPICKER_FILTER_EXT);
     fp.defaultString = PlacesBackups.getFilenameForDate();
     fp.displayDirectory = backupsDir;
     fp.open(fpCallback);
   },
 
-  _paneDisabled: false,
-  _setDetailsFieldsDisabledState:
-  function PO__setDetailsFieldsDisabledState(aDisabled) {
-    if (aDisabled) {
-      document.getElementById("paneElementsBroadcaster")
-              .setAttribute("disabled", "true");
-    }
-    else {
-      document.getElementById("paneElementsBroadcaster")
-              .removeAttribute("disabled");
-    }
-  },
-
   _detectAndSetDetailsPaneMinimalState:
   function PO__detectAndSetDetailsPaneMinimalState(aNode) {
     /**
      * The details of simple folder-items (as opposed to livemarks) or the
      * of livemark-children are not likely to fill the infoBox anyway,
      * thus we remove the "More/Less" button and show all details.
      *
      * the wasminimal attribute here is used to persist the "more/less"
--- a/browser/components/sessionstore/SessionWorker.js
+++ b/browser/components/sessionstore/SessionWorker.js
@@ -58,22 +58,16 @@ const STATE_RECOVERY_BACKUP = "recoveryB
 const STATE_UPGRADE_BACKUP = "upgradeBackup";
 /**
  * We just started without a valid session store file (we haven't
  * written anything to disk yet). The backup directory may not exist.
  */
 const STATE_EMPTY = "empty";
 
 let Agent = {
-  // Boolean that tells whether we already made a
-  // call to write(). We will only attempt to move
-  // sessionstore.js to sessionstore.bak on the
-  // first write.
-  hasWrittenState: false,
-
   // Path to the files used by the SessionWorker
   Paths: null,
 
   /**
    * The current state of the worker, as one of the following strings:
    * - "permanent", once the first write has been completed;
    * - "empty", before the first write has been completed,
    *   if we have started without any sessionstore;
--- a/browser/devtools/framework/target.js
+++ b/browser/devtools/framework/target.js
@@ -215,16 +215,24 @@ TabTarget.prototype = {
     return this._client;
   },
 
   get chrome() {
     return this._chrome;
   },
 
   get window() {
+    // XXX - this is a footgun for e10s - there .contentWindow will be null,
+    // and even though .contentWindowAsCPOW *might* work, it will not work
+    // in all contexts.  Consumers of .window need to be refactored to not
+    // rely on this.
+    if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
+      Cu.reportError("The .window getter on devtools' |target| object isn't e10s friendly!\n"
+                     + Error().stack);
+    }
     // Be extra careful here, since this may be called by HS_getHudByWindow
     // during shutdown.
     if (this._tab && this._tab.linkedBrowser) {
       return this._tab.linkedBrowser.contentWindow;
     }
     return null;
   },
 
@@ -537,17 +545,17 @@ TabWebProgressListener.prototype = {
     let isRequest = flag & Ci.nsIWebProgressListener.STATE_IS_REQUEST;
 
     // Skip non-interesting states.
     if (!isStart || !isDocument || !isRequest || !isNetwork) {
       return;
     }
 
     // emit event if the top frame is navigating
-    if (this.target && this.target.window == progress.DOMWindow) {
+    if (progress.isTopLevel) {
       // Emit the event if the target is not remoted or store the payload for
       // later emission otherwise.
       if (this.target._client) {
         this.target._navRequest = request;
       } else {
         this.target.emit("will-navigate", request);
       }
     }
--- a/browser/devtools/framework/test/browser.ini
+++ b/browser/devtools/framework/test/browser.ini
@@ -3,34 +3,37 @@ subsuite = devtools
 support-files =
   browser_toolbox_options_disable_js.html
   browser_toolbox_options_disable_js_iframe.html
   browser_toolbox_options_disable_cache.sjs
   head.js
   doc_theme.css
 
 [browser_devtools_api.js]
+skip-if = e10s # Bug 1070837 - devtools/framework/toolbox.js |doc| getter not e10s friendly
 [browser_dynamic_tool_enabling.js]
 [browser_keybindings.js]
 [browser_new_activation_workflow.js]
 [browser_target_events.js]
 [browser_target_remote.js]
 [browser_two_tabs.js]
 [browser_toolbox_dynamic_registration.js]
 [browser_toolbox_highlight.js]
 [browser_toolbox_hosts.js]
 [browser_toolbox_options.js]
 [browser_toolbox_options_disable_buttons.js]
 [browser_toolbox_options_disable_cache.js]
 skip-if = e10s # Bug 1030318
 [browser_toolbox_options_disable_js.js]
+skip-if = e10s # Bug 1070837 - devtools/framework/toolbox.js |doc| getter not e10s friendly
 # [browser_toolbox_raise.js] # Bug 962258
 # skip-if = os == "win"
 [browser_toolbox_ready.js]
 [browser_toolbox_select_event.js]
+skip-if = e10s # Bug 1069044 - destroyInspector may hang during shutdown
 [browser_toolbox_sidebar.js]
 [browser_toolbox_tabsswitch_shortcuts.js]
 [browser_toolbox_tool_ready.js]
 [browser_toolbox_window_reload_target.js]
 [browser_toolbox_window_shortcuts.js]
 [browser_toolbox_window_title_changes.js]
 [browser_toolbox_zoom.js]
 [browser_toolbox_custom_host.js]
--- a/browser/devtools/framework/test/browser_toolbox_window_reload_target.js
+++ b/browser/devtools/framework/test/browser_toolbox_window_reload_target.js
@@ -19,34 +19,35 @@ function test() {
                   .map(def => def.id);
       gDevTools.showToolbox(target, toolIDs[0], Toolbox.HostType.BOTTOM)
                .then(startReloadTest);
     });
   });
 }
 
 function startReloadTest(aToolbox) {
+  getFrameScript(); // causes frame-script-utils to be loaded into the child.
   toolbox = aToolbox;
 
   reloadsSent = 0;
   let reloads = 0;
-  let reloadCounter = (event) => {
+  let reloadCounter = (msg) => {
     reloads++;
     info("Detected reload #"+reloads);
     is(reloads, reloadsSent, "Reloaded from devtools window once and only for "+description+"");
   };
-  gBrowser.selectedBrowser.addEventListener('load', reloadCounter, true);
+  gBrowser.selectedBrowser.messageManager.addMessageListener("devtools:test:load", reloadCounter);
 
   testAllTheTools("docked", () => {
     let origHostType = toolbox.hostType;
     toolbox.switchHost(Toolbox.HostType.WINDOW).then(() => {
       toolbox.doc.defaultView.focus();
       testAllTheTools("undocked", () => {
         toolbox.switchHost(origHostType).then(() => {
-          gBrowser.selectedBrowser.removeEventListener('load', reloadCounter, true);
+          gBrowser.selectedBrowser.messageManager.removeMessageListener("devtools:test:load", reloadCounter);
           // If we finish too early, the inspector breaks promises:
           toolbox.getPanel("inspector").once("new-root", finishUp);
         });
       });
     });
   }, toolIDs.length-1 /* only test 1 tool in docked mode, to cut down test time */);
 }
 
@@ -73,20 +74,20 @@ function synthesizeKeyForToolbox(keyId) 
   let mod = {};
   el.getAttribute("modifiers").split(" ").forEach((m) => mod[m+"Key"] = true);
   info("Synthesizing: key="+key+", mod="+JSON.stringify(mod));
   EventUtils.synthesizeKey(key, mod, toolbox.doc.defaultView);
 }
 
 function testReload(key, docked, toolID, callback) {
   let complete = () => {
-    gBrowser.selectedBrowser.removeEventListener('load', complete, true);
+    gBrowser.selectedBrowser.messageManager.removeMessageListener("devtools:test:load", complete);
     return callback();
   };
-  gBrowser.selectedBrowser.addEventListener('load', complete, true);
+  gBrowser.selectedBrowser.messageManager.addMessageListener("devtools:test:load", complete);
 
   description = docked+" devtools with tool "+toolID+", key #" + key;
   info("Testing reload in "+description);
   synthesizeKeyForToolbox(key);
   reloadsSent++;
 }
 
 function finishUp() {
--- a/browser/devtools/shared/frame-script-utils.js
+++ b/browser/devtools/shared/frame-script-utils.js
@@ -11,8 +11,12 @@ addMessageListener("devtools:test:histor
 addMessageListener("devtools:test:navigate", function ({ data }) {
   content.location = data.location;
 });
 
 addMessageListener("devtools:test:reload", function ({ data }) {
   data = data || {};
   content.location.reload(data.forceget);
 });
+
+addEventListener("load", function() {
+  sendAsyncMessage("devtools:test:load");
+}, true);
--- a/browser/modules/UITour.jsm
+++ b/browser/modules/UITour.jsm
@@ -9,30 +9,27 @@ this.EXPORTED_SYMBOLS = ["UITour"];
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
   "resource://gre/modules/LightweightThemeManager.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PermissionsUtils",
-  "resource://gre/modules/PermissionsUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ResetProfile",
   "resource://gre/modules/ResetProfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
   "resource:///modules/CustomizableUI.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "UITelemetry",
   "resource://gre/modules/UITelemetry.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
   "resource:///modules/BrowserUITelemetry.jsm");
 
 
 const UITOUR_PERMISSION   = "uitour";
-const PREF_PERM_BRANCH    = "browser.uitour.";
 const PREF_SEENPAGEIDS    = "browser.uitour.seenPageIDs";
 const MAX_BUTTONS         = 4;
 
 const BUCKET_NAME         = "UITour";
 const BUCKET_TIMESTEPS    = [
   1 * 60 * 1000, // Until 1 minute after tab is closed/inactive.
   3 * 60 * 1000, // Until 3 minutes after tab is closed/inactive.
   10 * 60 * 1000, // Until 10 minutes after tab is closed/inactive.
@@ -597,37 +594,28 @@ this.UITour = {
                            .getInterface(Ci.nsIWebNavigation)
                            .QueryInterface(Ci.nsIDocShellTreeItem)
                            .rootTreeItem
                            .QueryInterface(Ci.nsIInterfaceRequestor)
                            .getInterface(Ci.nsIDOMWindow)
                            .wrappedJSObject;
   },
 
-  importPermissions: function() {
-    try {
-      PermissionsUtils.importFromPrefs(PREF_PERM_BRANCH, UITOUR_PERMISSION);
-    } catch (e) {
-      Cu.reportError(e);
-    }
-  },
-
   ensureTrustedOrigin: function(aDocument) {
     if (aDocument.defaultView.top != aDocument.defaultView)
       return false;
 
     let uri = aDocument.documentURIObject;
 
     if (uri.schemeIs("chrome"))
       return true;
 
     if (!this.isSafeScheme(uri))
       return false;
 
-    this.importPermissions();
     let permission = Services.perms.testPermission(uri, UITOUR_PERMISSION);
     return permission == Services.perms.ALLOW_ACTION;
   },
 
   isSafeScheme: function(aURI) {
     let allowedSchemes = new Set(["https", "about"]);
     if (!Services.prefs.getBoolPref("browser.uitour.requireSecure"))
       allowedSchemes.add("http");
--- a/config/external/nss/Makefile.in
+++ b/config/external/nss/Makefile.in
@@ -123,17 +123,17 @@ DEFAULT_GMAKE_FLAGS += SOURCE_MD_DIR=$(A
 DEFAULT_GMAKE_FLAGS += SOURCE_MDHEADERS_DIR=$(NSPR_INCLUDE_DIR)
 DEFAULT_GMAKE_FLAGS += DIST=$(ABS_DIST)
 DEFAULT_GMAKE_FLAGS += NSPR_INCLUDE_DIR=$(NSPR_INCLUDE_DIR)
 DEFAULT_GMAKE_FLAGS += NSPR_LIB_DIR=$(NSPR_LIB_DIR)
 DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1
 DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1
 DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1
 ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_1)
-DEFAULT_GMAKE_FLAGS += OS_DLLFLAGS='-static-libgcc'
+DEFAULT_GMAKE_FLAGS += OS_DLLFLAGS='-static-libgcc' NSPR31_LIB_PREFIX=lib
 endif
 ifndef MOZ_NATIVE_SQLITE
 ifdef MOZ_FOLD_LIBS
 DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=nss3
 else
 DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3
 endif # MOZ_FOLD_LIBS
 DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include
--- a/configure.in
+++ b/configure.in
@@ -2069,17 +2069,17 @@ ia64*-hpux*)
         LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++"
         NSPR_LDFLAGS="$NSPR_LDFLAGS -static-libgcc"
         # Use temp file for windres (bug 213281)
         RCFLAGS='-O coff --use-temp-file'
         # mingw doesn't require kernel32, user32, and advapi32 explicitly
         LIBS="$LIBS -luuid -lgdi32 -lwinmm -lwsock32 -luserenv -lsecur32 -lnetapi32"
         MOZ_FIX_LINK_PATHS=
         DLL_PREFIX=
-        IMPORT_LIB_SUFFIX=dll.a
+        IMPORT_LIB_SUFFIX=a
 
         WIN32_CONSOLE_EXE_LDFLAGS=-mconsole
         WIN32_GUI_EXE_LDFLAGS=-mwindows
 
         # We use mix of both POSIX and Win32 printf format across the tree, so format
         # warnings are useless on mingw.
         MOZ_C_SUPPORTS_WARNING(-Wno-, format, ac_c_has_wno_format)
         MOZ_CXX_SUPPORTS_WARNING(-Wno-, format, ac_cxx_has_wno_format)
@@ -6934,21 +6934,17 @@ if test "$NS_TRACE_MALLOC"; then
     MOZ_MEMORY=
 fi
 
 if test "${OS_TARGET}" = "Android"; then
   dnl On Android, we use WRAP_LDFLAGS to link everything to mozglue
   :
 elif test "${OS_TARGET}" = "WINNT" -o "${OS_TARGET}" = "Darwin"; then
   dnl On Windows and OSX, we want to link all our binaries against mozglue
-  if test -z "$GNU_CC"; then
-    MOZ_GLUE_LDFLAGS='$(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
-  else
-    MOZ_GLUE_LDFLAGS='-L$(LIBXUL_DIST)/lib $(call EXPAND_LIBNAME,mozglue)'
-  fi
+  MOZ_GLUE_LDFLAGS='$(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
 else
   dnl On other Unix systems, we only want to link executables against mozglue
   MOZ_GLUE_PROGRAM_LDFLAGS='$(MKSHLIB_FORCE_ALL) $(call EXPAND_LIBNAME_PATH,mozglue,$(LIBXUL_DIST)/lib)'
   dnl On other Unix systems, where mozglue is a static library, jemalloc is
   dnl separated for the SDK, so we need to add it here.
   if test "$MOZ_MEMORY" = 1 -o \( "$LIBXUL_SDK" -a -f "$LIBXUL_SDK/lib/${LIB_PREFIX}memory.${LIB_SUFFIX}" \); then
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS "'$(call EXPAND_LIBNAME_PATH,memory,$(LIBXUL_DIST)/lib)'
   fi
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -686,16 +686,21 @@ public:
    * SVG's "evt" and the rest of the world's "event", and because onerror
    * on window takes 5 args.
    */
   static void GetEventArgNames(int32_t aNameSpaceID, nsIAtom *aEventName,
                                bool aIsForWindow,
                                uint32_t *aArgCount, const char*** aArgNames);
 
   /**
+   * Returns true if this document is in a Private Browsing window.
+   */
+  static bool IsInPrivateBrowsing(nsIDocument* aDoc);
+
+  /**
    * If aNode is not an element, return true exactly when aContent's binding
    * parent is null.
    *
    * If aNode is an element, return true exactly when aContent's binding parent
    * is the same as aNode's.
    *
    * This method is particularly useful for callers who are trying to ensure
    * that they are working with a non-anonymous descendant of a given node.  If
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -748,40 +748,33 @@ EventSource::InitChannelAndRequestEventS
     channelPolicy->SetContentSecurityPolicy(csp);
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_DATAREQUEST);
   }
 
   nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   nsCOMPtr<nsIDocument> doc =
     nsContentUtils::GetDocumentFromScriptContext(sc);
 
-  nsCOMPtr<nsIPrincipal> principal = mPrincipal;
-  if (nsContentUtils::IsSystemPrincipal(principal)) {
-    // Don't give this channel the system principal.
-    principal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
   nsCOMPtr<nsIChannel> channel;
   // If we have the document, use it
   if (doc) {
     rv = NS_NewChannel(getter_AddRefs(channel),
                        mSrc,
                        doc,
                        nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
                        nsIContentPolicy::TYPE_DATAREQUEST,
                        channelPolicy,    // aChannelPolicy
                        mLoadGroup,       // loadGroup
                        nullptr,          // aCallbacks
                        loadFlags);       // aLoadFlags
   } else {
     // otherwise use the principal
     rv = NS_NewChannel(getter_AddRefs(channel),
                        mSrc,
-                       principal,
+                       mPrincipal,
                        nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
                        nsIContentPolicy::TYPE_DATAREQUEST,
                        channelPolicy,    // aChannelPolicy
                        mLoadGroup,       // loadGroup
                        nullptr,          // aCallbacks
                        loadFlags);       // aLoadFlags
   }
 
--- a/content/base/src/WebSocket.cpp
+++ b/content/base/src/WebSocket.cpp
@@ -717,16 +717,17 @@ WebSocket::Init(JSContext* aCx,
     }
 
     AppendUTF16toUTF8(aProtocolArray[index], mRequestedProtocolList);
   }
 
   // Check content policy.
   int16_t shouldLoad = nsIContentPolicy::ACCEPT;
   nsCOMPtr<nsIDocument> originDoc = nsContentUtils::GetDocumentFromScriptContext(sc);
+  mOriginDocument = do_GetWeakReference(originDoc);
   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_WEBSOCKET,
                                  mURI,
                                  mPrincipal,
                                  originDoc,
                                  EmptyCString(),
                                  nullptr,
                                  &shouldLoad,
                                  nsContentUtils::GetContentPolicy(),
@@ -796,16 +797,27 @@ WebSocket::EstablishConnection()
   rv = GetLoadGroup(getter_AddRefs(loadGroup));
   if (loadGroup) {
     rv = wsChannel->SetLoadGroup(loadGroup);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = loadGroup->AddRequest(this, nullptr);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  // manually adding loadinfo to the channel since it
+  // was not set during channel creation.
+  nsCOMPtr<nsIDocument> doc = do_QueryReferent(mOriginDocument);
+  nsCOMPtr<nsILoadInfo> loadInfo =
+    new LoadInfo(mPrincipal,
+                 doc,
+                 nsILoadInfo::SEC_NORMAL,
+                 nsIContentPolicy::TYPE_WEBSOCKET);
+  rv = wsChannel->SetLoadInfo(loadInfo);
+  NS_ENSURE_SUCCESS(rv, rv);
+
   if (!mRequestedProtocolList.IsEmpty()) {
     rv = wsChannel->SetProtocol(mRequestedProtocolList);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCString asciiOrigin;
   rv = nsContentUtils::GetASCIIOrigin(mPrincipal, asciiOrigin);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/content/base/src/WebSocket.h
+++ b/content/base/src/WebSocket.h
@@ -230,16 +230,17 @@ protected: //data
   nsCOMPtr<nsIURI> mURI;
   nsCString mRequestedProtocolList;
   nsCString mEstablishedProtocol;
   nsCString mEstablishedExtensions;
 
   uint16_t mReadyState;
 
   nsCOMPtr<nsIPrincipal> mPrincipal;
+  nsWeakPtr              mOriginDocument;
 
   uint32_t mOutgoingBufferedAmount;
 
   dom::BinaryType mBinaryType;
 
   // Web Socket owner information:
   // - the script file name, UTF8 encoded.
   // - source code line number where the Web Socket object was constructed.
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2918,34 +2918,46 @@ nsContentUtils::CanLoadImage(nsIURI* aUR
 
   if (aImageBlockingStatus) {
     *aImageBlockingStatus =
       NS_FAILED(rv) ? nsIContentPolicy::REJECT_REQUEST : decision;
   }
   return NS_FAILED(rv) ? false : NS_CP_ACCEPTED(decision);
 }
 
-imgLoader*
-nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc)
-{
-  if (!aDoc)
-    return imgLoader::Singleton();
+// static
+bool
+nsContentUtils::IsInPrivateBrowsing(nsIDocument* aDoc)
+{
+  if (!aDoc) {
+    return false;
+  }
   bool isPrivate = false;
   nsCOMPtr<nsILoadGroup> loadGroup = aDoc->GetDocumentLoadGroup();
   nsCOMPtr<nsIInterfaceRequestor> callbacks;
   if (loadGroup) {
     loadGroup->GetNotificationCallbacks(getter_AddRefs(callbacks));
     if (callbacks) {
       nsCOMPtr<nsILoadContext> loadContext = do_GetInterface(callbacks);
       isPrivate = loadContext && loadContext->UsePrivateBrowsing();
     }
   } else {
     nsCOMPtr<nsIChannel> channel = aDoc->GetChannel();
     isPrivate = channel && NS_UsePrivateBrowsing(channel);
   }
+  return isPrivate;
+}
+
+imgLoader*
+nsContentUtils::GetImgLoaderForDocument(nsIDocument* aDoc)
+{
+  if (!aDoc) {
+    return imgLoader::Singleton();
+  }
+  bool isPrivate = IsInPrivateBrowsing(aDoc);
   return isPrivate ? imgLoader::PBSingleton() : imgLoader::Singleton();
 }
 
 // static
 imgLoader*
 nsContentUtils::GetImgLoaderForChannel(nsIChannel* aChannel)
 {
   if (!aChannel)
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1730,45 +1730,45 @@ nsXMLHttpRequest::Open(const nsACString&
   rv = mPrincipal->GetCsp(getter_AddRefs(csp));
   NS_ENSURE_SUCCESS(rv, rv);
   if (csp) {
     channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
     channelPolicy->SetContentSecurityPolicy(csp);
     channelPolicy->SetLoadType(nsIContentPolicy::TYPE_XMLHTTPREQUEST);
   }
 
-  nsCOMPtr<nsIPrincipal> documentPrincipal;
+  nsSecurityFlags secFlags = nsILoadInfo::SEC_NORMAL;
   if (IsSystemXHR()) {
     // Don't give this document the system principal.  We need to keep track of
     // mPrincipal being system because we use it for various security checks
     // that should be passing, but the document data shouldn't get a system
-    // principal.
-    documentPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    // principal.  Hence we set the sandbox flag in loadinfo, so that 
+    // GetChannelResultPrincipal will give us the nullprincipal.
+    secFlags |= nsILoadInfo::SEC_SANDBOXED;
   } else {
-    documentPrincipal = mPrincipal;
+    secFlags |= nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
   }
 
   // If we have the document, use it
   if (doc) {
     rv = NS_NewChannel(getter_AddRefs(mChannel),
                        uri,
                        doc,
-                       nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
+                       secFlags,
                        nsIContentPolicy::TYPE_XMLHTTPREQUEST,
                        channelPolicy,
                        loadGroup,
                        nullptr,   // aCallbacks
                        nsIRequest::LOAD_BACKGROUND);
   } else {
     //otherwise use the principal
     rv = NS_NewChannel(getter_AddRefs(mChannel),
                        uri,
-                       documentPrincipal,
-                       nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
+                       mPrincipal,
+                       secFlags,
                        nsIContentPolicy::TYPE_XMLHTTPREQUEST,
                        channelPolicy,
                        loadGroup,
                        nullptr,   // aCallbacks
                        nsIRequest::LOAD_BACKGROUND);
   }
 
   if (NS_FAILED(rv)) return rv;
@@ -1982,29 +1982,16 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
   // Don't do anything if we have timed out.
   if (mState & XML_HTTP_REQUEST_TIMED_OUT) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIChannel> channel(do_QueryInterface(request));
   NS_ENSURE_TRUE(channel, NS_ERROR_UNEXPECTED);
 
-  nsCOMPtr<nsIPrincipal> documentPrincipal;
-  if (IsSystemXHR()) {
-    // Don't give this document the system principal.  We need to keep track of
-    // mPrincipal being system because we use it for various security checks
-    // that should be passing, but the document data shouldn't get a system
-    // principal.
-    nsresult rv;
-    documentPrincipal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-  } else {
-    documentPrincipal = mPrincipal;
-  }
-
   nsresult status;
   request->GetStatus(&status);
   mErrorLoad = mErrorLoad || NS_FAILED(status);
 
   if (mUpload && !mUploadComplete && !mErrorLoad &&
       (mState & XML_HTTP_REQUEST_ASYNC)) {
     if (mProgressTimerIsActive) {
       mProgressTimerIsActive = false;
@@ -2132,31 +2119,33 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
     nsCOMPtr<nsIDocument> doc =
       nsContentUtils::GetDocumentFromScriptContext(sc);
     nsCOMPtr<nsIURI> chromeXHRDocURI, chromeXHRDocBaseURI;
     if (doc) {
       chromeXHRDocURI = doc->GetDocumentURI();
       chromeXHRDocBaseURI = doc->GetBaseURI();
     }
 
-    // Create an empty document from it.  Here we have to cheat a little bit...
-    // Setting the base URI to |baseURI| won't work if the document has a null
-    // principal, so use mPrincipal when creating the document, then reset the
-    // principal.
+    // Create an empty document from it.
     const nsAString& emptyStr = EmptyString();
     nsCOMPtr<nsIDOMDocument> responseDoc;
     nsIGlobalObject* global = DOMEventTargetHelper::GetParentObject();
+
+    nsCOMPtr<nsIPrincipal> requestingPrincipal;
+    rv = nsContentUtils::GetSecurityManager()->
+       GetChannelResultPrincipal(channel, getter_AddRefs(requestingPrincipal));
+    NS_ENSURE_SUCCESS(rv, rv);
+
     rv = NS_NewDOMDocument(getter_AddRefs(responseDoc),
                            emptyStr, emptyStr, nullptr, docURI,
-                           baseURI, mPrincipal, true, global,
+                           baseURI, requestingPrincipal, true, global,
                            mIsHtml ? DocumentFlavorHTML :
                                      DocumentFlavorLegacyGuess);
     NS_ENSURE_SUCCESS(rv, rv);
     mResponseXML = do_QueryInterface(responseDoc);
-    mResponseXML->SetPrincipal(documentPrincipal);
     mResponseXML->SetChromeXHRDocURI(chromeXHRDocURI);
     mResponseXML->SetChromeXHRDocBaseURI(chromeXHRDocBaseURI);
 
     if (nsContentUtils::IsSystemPrincipal(mPrincipal)) {
       mResponseXML->ForceEnableXULXBL();
     }
 
     if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
--- a/content/base/test/chrome/chrome.ini
+++ b/content/base/test/chrome/chrome.ini
@@ -47,14 +47,15 @@ skip-if = buildapp == 'mulet'
 [test_bug765993.html]
 [test_bug780199.xul]
 [test_bug780529.xul]
 [test_bug800386.xul]
 [test_bug814638.xul]
 [test_bug816340.xul]
 [test_bug914381.html]
 [test_bug990812.xul]
+[test_bug1063837.xul]
 [test_cpows.xul]
 skip-if = buildapp == 'mulet'
 [test_document_register.xul]
 [test_domparsing.xul]
 [test_fileconstructor.xul]
 [test_title.xul]
new file mode 100644
--- /dev/null
+++ b/content/base/test/chrome/test_bug1063837.xul
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=206691
+-->
+<window title="Mozilla Bug 1063837"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1063837"
+     target="_blank">Mozilla Bug 1063837</a>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+
+  /** Test for Bug 1063837 **/
+  SimpleTest.waitForExplicitFinish();
+
+  addLoadEvent(function() {
+    var xhr = new XMLHttpRequest();
+    xhr.open("GET", location, false);
+    xhr.onload = function() {
+      ok(xhr.responseXML, "We should have response content!");
+      var principal = xhr.responseXML.nodePrincipal;
+      ok(principal.URI.schemeIs("moz-nullprincipal"), "The response document should have a null principal");
+      SimpleTest.finish();
+    }
+    xhr.send();
+  });
+  ]]></script>
+</window>
--- a/dom/bluetooth/tests/marionette/head.js
+++ b/dom/bluetooth/tests/marionette/head.js
@@ -481,25 +481,28 @@ function getSettings(aKey) {
  * Reject params: (none)
  *
  * @param aSettings
  *        An object of format |{key1: value1, key2: value2, ...}|.
  *
  * @return A deferred promise.
  */
 function setSettings(aSettings) {
-  let request = navigator.mozSettings.createLock().set(aSettings);
-
-  return wrapDomRequestAsPromise(request)
-    .then(function resolve() {
+  let lock = window.navigator.mozSettings.createLock();
+  let request = lock.set(aSettings);
+  let deferred = Promise.defer();
+  lock.onsettingstransactionsuccess = function () {
       ok(true, "setSettings(" + JSON.stringify(aSettings) + ")");
-    }, function reject(aEvent) {
+    deferred.resolve();
+  };
+  lock.onsettingstransactionfailure = function (aEvent) {
       ok(false, "setSettings(" + JSON.stringify(aSettings) + ")");
-      throw aEvent.target.error;
-    });
+    deferred.reject();
+  };
+  return deferred.promise;
 }
 
 /**
  * Get mozSettings value of 'bluetooth.enabled'.
  *
  * Resolve if that mozSettings value is retrieved successfully, reject
  * otherwise.
  *
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/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
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/BluetoothInterface.h
@@ -0,0 +1,634 @@
+/* -*- 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_bluetoothinterface_h__
+#define mozilla_dom_bluetooth_bluetoothinterface_h__
+
+#include "BluetoothCommon.h"
+#include "mozilla/dom/bluetooth/BluetoothTypes.h"
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+//
+// Socket Interface
+//
+
+class BluetoothSocketResultHandler
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothSocketResultHandler)
+
+  virtual ~BluetoothSocketResultHandler() { }
+
+  virtual void OnError(BluetoothStatus aStatus)
+  {
+    BT_WARNING("Received error code %d", (int)aStatus);
+  }
+
+  virtual void Listen(int aSockFd) { }
+  virtual void Connect(int aSockFd, const nsAString& aBdAddress,
+                       int aConnectionState) { }
+  virtual void Accept(int aSockFd, const nsAString& aBdAddress,
+                      int aConnectionState) { }
+};
+
+class BluetoothSocketInterface
+{
+public:
+  // Init and Cleanup is handled by BluetoothInterface
+
+  virtual void Listen(BluetoothSocketType aType,
+                      const nsAString& aServiceName,
+                      const uint8_t aServiceUuid[16],
+                      int aChannel, bool aEncrypt, bool aAuth,
+                      BluetoothSocketResultHandler* aRes) = 0;
+
+  virtual void Connect(const nsAString& aBdAddr,
+                       BluetoothSocketType aType,
+                       const uint8_t aUuid[16],
+                       int aChannel, bool aEncrypt, bool aAuth,
+                       BluetoothSocketResultHandler* aRes) = 0;
+
+  virtual void Accept(int aFd, BluetoothSocketResultHandler* aRes) = 0;
+
+protected:
+  virtual ~BluetoothSocketInterface();
+};
+
+//
+// Handsfree Interface
+//
+
+class BluetoothHandsfreeNotificationHandler
+{
+public:
+  virtual ~BluetoothHandsfreeNotificationHandler();
+
+  virtual void
+  ConnectionStateNotification(BluetoothHandsfreeConnectionState aState,
+                              const nsAString& aBdAddr)
+  { }
+
+  virtual void
+  AudioStateNotification(BluetoothHandsfreeAudioState aState,
+                         const nsAString& aBdAddr)
+  { }
+
+  virtual void
+  VoiceRecognitionNotification(BluetoothHandsfreeVoiceRecognitionState aState)
+  { }
+
+  virtual void
+  AnswerCallNotification()
+  { }
+
+  virtual void
+  HangupCallNotification()
+  { }
+
+  virtual void
+  VolumeNotification(BluetoothHandsfreeVolumeType aType, int aVolume)
+  { }
+
+  virtual void
+  DialCallNotification(const nsAString& aNumber)
+  { }
+
+  virtual void
+  DtmfNotification(char aDtmf)
+  { }
+
+  virtual void
+  NRECNotification(BluetoothHandsfreeNRECState aNrec)
+  { }
+
+  virtual void
+  CallHoldNotification(BluetoothHandsfreeCallHoldType aChld)
+  { }
+
+  virtual void
+  CnumNotification()
+  { }
+
+  virtual void
+  CindNotification()
+  { }
+
+  virtual void
+  CopsNotification()
+  { }
+
+  virtual void
+  ClccNotification()
+  { }
+
+  virtual void
+  UnknownAtNotification(const nsACString& aAtString)
+  { }
+
+  virtual void
+  KeyPressedNotification()
+  { }
+
+protected:
+  BluetoothHandsfreeNotificationHandler()
+  { }
+};
+
+class BluetoothHandsfreeResultHandler
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothHandsfreeResultHandler)
+
+  virtual ~BluetoothHandsfreeResultHandler() { }
+
+  virtual void OnError(BluetoothStatus aStatus)
+  {
+    BT_WARNING("Received error code %d", (int)aStatus);
+  }
+
+  virtual void Init() { }
+  virtual void Cleanup() { }
+
+  virtual void Connect() { }
+  virtual void Disconnect() { }
+  virtual void ConnectAudio() { }
+  virtual void DisconnectAudio() { }
+
+  virtual void StartVoiceRecognition() { }
+  virtual void StopVoiceRecognition() { }
+
+  virtual void VolumeControl() { }
+
+  virtual void DeviceStatusNotification() { }
+
+  virtual void CopsResponse() { }
+  virtual void CindResponse() { }
+  virtual void FormattedAtResponse() { }
+  virtual void AtResponse() { }
+  virtual void ClccResponse() { }
+  virtual void PhoneStateChange() { }
+};
+
+class BluetoothHandsfreeInterface
+{
+public:
+  virtual void Init(
+    BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+    BluetoothHandsfreeResultHandler* aRes) = 0;
+  virtual void Cleanup(BluetoothHandsfreeResultHandler* aRes) = 0;
+
+  /* Connect / Disconnect */
+
+  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 */
+
+  virtual void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes) = 0;
+  virtual void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes) = 0;
+
+  /* Volume */
+
+  virtual void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
+                             BluetoothHandsfreeResultHandler* aRes) = 0;
+
+  /* Device status */
+
+  virtual void DeviceStatusNotification(
+    BluetoothHandsfreeNetworkState aNtkState,
+    BluetoothHandsfreeServiceType aSvcType,
+    int aSignal, int aBattChg, BluetoothHandsfreeResultHandler* aRes) = 0;
+
+  /* Responses */
+
+  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 */
+
+  virtual void PhoneStateChange(int aNumActive, int aNumHeld,
+                                BluetoothHandsfreeCallState aCallSetupState,
+                                const nsAString& aNumber,
+                                BluetoothHandsfreeCallAddressType aType,
+                                BluetoothHandsfreeResultHandler* aRes) = 0;
+
+protected:
+  BluetoothHandsfreeInterface();
+  virtual ~BluetoothHandsfreeInterface();
+};
+
+//
+// Bluetooth Advanced Audio Interface
+//
+
+class BluetoothA2dpNotificationHandler
+{
+public:
+  virtual ~BluetoothA2dpNotificationHandler();
+
+  virtual void
+  ConnectionStateNotification(BluetoothA2dpConnectionState aState,
+                              const nsAString& aBdAddr)
+  { }
+
+  virtual void
+  AudioStateNotification(BluetoothA2dpAudioState aState,
+                         const nsAString& aBdAddr)
+  { }
+
+protected:
+  BluetoothA2dpNotificationHandler()
+  { }
+};
+
+class BluetoothA2dpResultHandler
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothA2dpResultHandler)
+
+  virtual ~BluetoothA2dpResultHandler() { }
+
+  virtual void OnError(BluetoothStatus aStatus)
+  {
+    BT_WARNING("Received error code %d", (int)aStatus);
+  }
+
+  virtual void Init() { }
+  virtual void Cleanup() { }
+  virtual void Connect() { }
+  virtual void Disconnect() { }
+};
+
+class BluetoothA2dpInterface
+{
+public:
+  virtual void Init(BluetoothA2dpNotificationHandler* aNotificationHandler,
+                    BluetoothA2dpResultHandler* aRes) = 0;
+  virtual void Cleanup(BluetoothA2dpResultHandler* aRes) = 0;
+
+  virtual void Connect(const nsAString& aBdAddr,
+                       BluetoothA2dpResultHandler* aRes) = 0;
+  virtual void Disconnect(const nsAString& aBdAddr,
+                          BluetoothA2dpResultHandler* aRes) = 0;
+
+protected:
+  BluetoothA2dpInterface();
+  virtual ~BluetoothA2dpInterface();
+};
+
+//
+// Bluetooth AVRCP Interface
+//
+
+class BluetoothAvrcpNotificationHandler
+{
+public:
+  virtual ~BluetoothAvrcpNotificationHandler();
+
+  virtual void
+  GetPlayStatusNotification()
+  { }
+
+  virtual void
+  ListPlayerAppAttrNotification()
+  { }
+
+  virtual void
+  ListPlayerAppValuesNotification(BluetoothAvrcpPlayerAttribute aAttrId)
+  { }
+
+  virtual void
+  GetPlayerAppValueNotification(uint8_t aNumAttrs,
+                                const BluetoothAvrcpPlayerAttribute* aAttrs)
+  { }
+
+  virtual void
+  GetPlayerAppAttrsTextNotification(uint8_t aNumAttrs,
+                                    const BluetoothAvrcpPlayerAttribute* aAttrs)
+  { }
+
+  virtual void
+  GetPlayerAppValuesTextNotification(uint8_t aAttrId, uint8_t aNumVals,
+                                     const uint8_t* aValues)
+  { }
+
+  virtual void
+  SetPlayerAppValueNotification(const BluetoothAvrcpPlayerSettings& aSettings)
+  { }
+
+  virtual void
+  GetElementAttrNotification(uint8_t aNumAttrs,
+                             const BluetoothAvrcpMediaAttribute* aAttrs)
+  { }
+
+  virtual void
+  RegisterNotificationNotification(BluetoothAvrcpEvent aEvent,
+                                   uint32_t aParam)
+  { }
+
+  virtual void
+  RemoteFeatureNotification(const nsAString& aBdAddr, unsigned long aFeatures)
+  { }
+
+  virtual void
+  VolumeChangeNotification(uint8_t aVolume, uint8_t aCType)
+  { }
+
+  virtual void
+  PassthroughCmdNotification(int aId, int aKeyState)
+  { }
+
+protected:
+  BluetoothAvrcpNotificationHandler()
+  { }
+};
+
+class BluetoothAvrcpResultHandler
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothAvrcpResultHandler)
+
+  virtual ~BluetoothAvrcpResultHandler() { }
+
+  virtual void OnError(BluetoothStatus aStatus)
+  {
+    BT_WARNING("Received error code %d", (int)aStatus);
+  }
+
+  virtual void Init() { }
+  virtual void Cleanup() { }
+
+  virtual void GetPlayStatusRsp() { }
+
+  virtual void ListPlayerAppAttrRsp() { }
+  virtual void ListPlayerAppValueRsp() { }
+
+  virtual void GetPlayerAppValueRsp() { }
+  virtual void GetPlayerAppAttrTextRsp() { }
+  virtual void GetPlayerAppValueTextRsp() { }
+
+  virtual void GetElementAttrRsp() { }
+
+  virtual void SetPlayerAppValueRsp() { }
+
+  virtual void RegisterNotificationRsp() { }
+
+  virtual void SetVolume() { }
+};
+
+class BluetoothAvrcpInterface
+{
+public:
+  virtual void Init(BluetoothAvrcpNotificationHandler* aNotificationHandler,
+                    BluetoothAvrcpResultHandler* aRes) = 0;
+  virtual void Cleanup(BluetoothAvrcpResultHandler* aRes) = 0;
+
+  virtual void GetPlayStatusRsp(ControlPlayStatus aPlayStatus,
+                                uint32_t aSongLen, uint32_t aSongPos,
+                                BluetoothAvrcpResultHandler* aRes) = 0;
+
+  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 */
+  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 */
+  virtual void GetPlayerAppAttrTextRsp(int aNumAttr, const uint8_t* aIds,
+                                       const char** aTexts,
+                                       BluetoothAvrcpResultHandler* aRes) = 0;
+  /* TODO: redesign this interface once we actually use it */
+  virtual void GetPlayerAppValueTextRsp(int aNumVal, const uint8_t* aIds,
+                                        const char** aTexts,
+                                        BluetoothAvrcpResultHandler* aRes) = 0;
+
+  virtual void GetElementAttrRsp(uint8_t aNumAttr,
+                                 const BluetoothAvrcpElementAttribute* aAttr,
+                                 BluetoothAvrcpResultHandler* aRes) = 0;
+
+  virtual void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus,
+                                    BluetoothAvrcpResultHandler* aRes) = 0;
+
+  virtual void RegisterNotificationRsp(
+    BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
+    const BluetoothAvrcpNotificationParam& aParam,
+    BluetoothAvrcpResultHandler* aRes) = 0;
+
+  virtual void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes) = 0;
+
+protected:
+  BluetoothAvrcpInterface();
+  virtual ~BluetoothAvrcpInterface();
+};
+
+//
+// Bluetooth Core Interface
+//
+
+class BluetoothNotificationHandler
+{
+public:
+  virtual ~BluetoothNotificationHandler();
+
+  virtual void AdapterStateChangedNotification(bool aState) { }
+  virtual void AdapterPropertiesNotification(
+    BluetoothStatus aStatus, int aNumProperties,
+    const BluetoothProperty* aProperties) { }
+
+  virtual void RemoteDevicePropertiesNotification(
+    BluetoothStatus aStatus, const nsAString& aBdAddr,
+    int aNumProperties, const BluetoothProperty* aProperties) { }
+
+  virtual void DeviceFoundNotification(
+    int aNumProperties, const BluetoothProperty* aProperties) { }
+
+  virtual void DiscoveryStateChangedNotification(bool aState) { }
+
+  virtual void PinRequestNotification(const nsAString& aRemoteBdAddr,
+                                      const nsAString& aBdName, uint32_t aCod) { }
+  virtual void SspRequestNotification(const nsAString& aRemoteBdAddr,
+                                      const nsAString& aBdName,
+                                      uint32_t aCod,
+                                      BluetoothSspVariant aPairingVariant,
+                                      uint32_t aPassKey) { }
+
+  virtual void BondStateChangedNotification(BluetoothStatus aStatus,
+                                            const nsAString& aRemoteBdAddr,
+                                            BluetoothBondState aState) { }
+  virtual void AclStateChangedNotification(BluetoothStatus aStatus,
+                                           const nsAString& aRemoteBdAddr,
+                                           bool aState) { }
+
+  virtual void DutModeRecvNotification(uint16_t aOpcode,
+                                       const uint8_t* aBuf, uint8_t aLen) { }
+  virtual void LeTestModeNotification(BluetoothStatus aStatus,
+                                      uint16_t aNumPackets) { }
+
+protected:
+  BluetoothNotificationHandler()
+  { }
+};
+
+class BluetoothResultHandler
+{
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothResultHandler)
+
+  virtual ~BluetoothResultHandler() { }
+
+  virtual void OnError(BluetoothStatus aStatus)
+  {
+    BT_LOGR("Received error code %d", aStatus);
+  }
+
+  virtual void Init() { }
+  virtual void Cleanup() { }
+  virtual void Enable() { }
+  virtual void Disable() { }
+
+  virtual void GetAdapterProperties() { }
+  virtual void GetAdapterProperty() { }
+  virtual void SetAdapterProperty() { }
+
+  virtual void GetRemoteDeviceProperties() { }
+  virtual void GetRemoteDeviceProperty() { }
+  virtual void SetRemoteDeviceProperty() { }
+
+  virtual void GetRemoteServiceRecord() { }
+  virtual void GetRemoteServices() { }
+
+  virtual void StartDiscovery() { }
+  virtual void CancelDiscovery() { }
+
+  virtual void CreateBond() { }
+  virtual void RemoveBond() { }
+  virtual void CancelBond() { }
+
+  virtual void PinReply() { }
+  virtual void SspReply() { }
+
+  virtual void DutModeConfigure() { }
+  virtual void DutModeSend() { }
+
+  virtual void LeTestMode() { }
+};
+
+class BluetoothInterface
+{
+public:
+  static BluetoothInterface* GetInstance();
+
+  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 */
+
+  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 */
+
+  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 */
+
+  virtual void GetRemoteServiceRecord(const nsAString& aRemoteAddr,
+                                      const uint8_t aUuid[16],
+                                      BluetoothResultHandler* aRes) = 0;
+  virtual void GetRemoteServices(const nsAString& aRemoteAddr,
+                                 BluetoothResultHandler* aRes) = 0;
+
+  /* Discovery */
+
+  virtual void StartDiscovery(BluetoothResultHandler* aRes) = 0;
+  virtual void CancelDiscovery(BluetoothResultHandler* aRes) = 0;
+
+  /* Bonds */
+
+  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 */
+
+  virtual void PinReply(const nsAString& aBdAddr, bool aAccept,
+                        const nsAString& aPinCode,
+                        BluetoothResultHandler* aRes) = 0;
+
+  virtual void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
+                        bool aAccept, uint32_t aPasskey,
+                        BluetoothResultHandler* aRes) = 0;
+
+  /* DUT Mode */
+
+  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 */
+
+  virtual void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+                          BluetoothResultHandler* aRes) = 0;
+
+  /* Profile Interfaces */
+
+  virtual BluetoothSocketInterface* GetBluetoothSocketInterface() = 0;
+  virtual BluetoothHandsfreeInterface* GetBluetoothHandsfreeInterface() = 0;
+  virtual BluetoothA2dpInterface* GetBluetoothA2dpInterface() = 0;
+  virtual BluetoothAvrcpInterface* GetBluetoothAvrcpInterface() = 0;
+
+protected:
+  BluetoothInterface();
+  virtual ~BluetoothInterface();
+};
+
+END_BLUETOOTH_NAMESPACE
+
+#endif
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/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<BluetoothA2dpResultHandler, void>
+  BluetoothA2dpHALResultRunnable;
+
+typedef
+  BluetoothHALInterfaceRunnable1<BluetoothA2dpResultHandler, void,
+                                 BluetoothStatus, BluetoothStatus>
+  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
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/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 <hardware/bluetooth.h>
+#include <hardware/bt_av.h>
+#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
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothAvrcpHALInterface.cpp
@@ -0,0 +1,601 @@
+/* -*- 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<BluetoothAvrcpResultHandler, void>
+  BluetoothAvrcpHALResultRunnable;
+
+typedef
+  BluetoothHALInterfaceRunnable1<BluetoothAvrcpResultHandler, void,
+                                 BluetoothStatus, BluetoothStatus>
+  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<AvrcpNotificationHandlerWrapper,
+                                            void>
+    GetPlayStatusNotification;
+
+  typedef BluetoothNotificationHALRunnable0<AvrcpNotificationHandlerWrapper,
+                                            void>
+    ListPlayerAppAttrNotification;
+
+  typedef BluetoothNotificationHALRunnable1<AvrcpNotificationHandlerWrapper,
+                                            void,
+                                            BluetoothAvrcpPlayerAttribute>
+    ListPlayerAppValuesNotification;
+
+  typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper, void,
+    uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
+    uint8_t, const BluetoothAvrcpPlayerAttribute*>
+    GetPlayerAppValueNotification;
+
+  typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper, void,
+    uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
+    uint8_t, const BluetoothAvrcpPlayerAttribute*>
+    GetPlayerAppAttrsTextNotification;
+
+  typedef BluetoothNotificationHALRunnable3<AvrcpNotificationHandlerWrapper,
+                                            void,
+                                            uint8_t, uint8_t,
+                                            nsAutoArrayPtr<uint8_t>,
+                                            uint8_t, uint8_t, const uint8_t*>
+    GetPlayerAppValuesTextNotification;
+
+  typedef BluetoothNotificationHALRunnable1<AvrcpNotificationHandlerWrapper,
+                                            void,
+                                            BluetoothAvrcpPlayerSettings,
+                                            const BluetoothAvrcpPlayerSettings&>
+    SetPlayerAppValueNotification;
+
+  typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper, void,
+    uint8_t, nsAutoArrayPtr<BluetoothAvrcpMediaAttribute>,
+    uint8_t, const BluetoothAvrcpMediaAttribute*>
+    GetElementAttrNotification;
+
+  typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
+                                            void,
+                                            BluetoothAvrcpEvent, uint32_t>
+    RegisterNotificationNotification;
+
+  typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
+                                            void,
+                                            nsString, unsigned long,
+                                            const nsAString&>
+    RemoteFeatureNotification;
+
+  typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
+                                            void,
+                                            uint8_t, uint8_t>
+    VolumeChangeNotification;
+
+  typedef BluetoothNotificationHALRunnable2<AvrcpNotificationHandlerWrapper,
+                                            void,
+                                            int, int>
+    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<btrc_player_attr_t>(aAttrs, aNumAttrs));
+  }
+
+  static void
+  GetPlayerAppAttrsText(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs)
+  {
+    GetPlayerAppAttrsTextNotification::Dispatch(
+      &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification,
+      aNumAttrs, ConvertArray<btrc_player_attr_t>(aAttrs, aNumAttrs));
+  }
+
+  static void
+  GetPlayerAppValuesText(uint8_t aAttrId, uint8_t aNumVals, uint8_t* aVals)
+  {
+    GetPlayerAppValuesTextNotification::Dispatch(
+      &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification,
+      aAttrId, aNumVals, ConvertArray<uint8_t>(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<btrc_media_attr_t>(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)
+{
+  bt_status_t status;
+
+#if ANDROID_VERSION >= 18
+  mInterface->cleanup();
+
+  status = BT_STATUS_SUCCESS;
+#else
+  status = BT_STATUS_UNSUPPORTED;
+#endif
+
+  if (aRes) {
+    DispatchBluetoothAvrcpHALResult(
+      aRes,
+      &BluetoothAvrcpResultHandler::Cleanup,
+      ConvertDefault(status, STATUS_FAIL));
+  }
+}
+
+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<BluetoothAvrcpPlayerAttribute> pAttrsArray(aPAttrs, aNumAttr);
+  nsAutoArrayPtr<btrc_player_attr_t> 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<BluetoothAvrcpElementAttribute> pAttrsArray(aAttrs, aNumAttr);
+  nsAutoArrayPtr<btrc_element_attr_val_t> 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, &param);
+  } 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
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/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 <hardware/bluetooth.h>
+#if ANDROID_VERSION >= 18
+#include <hardware/bt_rc.h>
+#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
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/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<void*>(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<void*>(static_cast<const void*>(aIn.mStringValue.get()));
+    aOut.len = strlen(static_cast<char*>(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<uint8_t>(strtoul(str, const_cast<char**>(&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<uint8_t>(*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<int>(aIn.address[0]),
+                     static_cast<int>(aIn.address[1]),
+                     static_cast<int>(aIn.address[2]),
+                     static_cast<int>(aIn.address[3]),
+                     static_cast<int>(aIn.address[4]),
+                     static_cast<int>(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<size_t>(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<char*>(aIn.val), aIn.len));
+      }
+      break;
+    case PROPERTY_BDADDR:
+      rv = Convert(*static_cast<bt_bdaddr_t*>(aIn.val), aOut.mString);
+      break;
+    case PROPERTY_UUIDS:
+      {
+        size_t numUuids = aIn.len / MAX_UUID_SIZE;
+        ConvertArray<bt_uuid_t> array(
+          static_cast<bt_uuid_t*>(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<uint32_t*>(aIn.val);
+      break;
+    case PROPERTY_TYPE_OF_DEVICE:
+      rv = Convert(*static_cast<bt_device_type_t*>(aIn.val),
+                   aOut.mTypeOfDevice);
+      break;
+    case PROPERTY_SERVICE_RECORD:
+      rv = Convert(*static_cast<bt_service_record_t*>(aIn.val),
+                   aOut.mServiceRecord);
+      break;
+    case PROPERTY_ADAPTER_SCAN_MODE:
+      rv = Convert(*static_cast<bt_scan_mode_t*>(aIn.val),
+                   aOut.mScanMode);
+      break;
+    case PROPERTY_ADAPTER_BONDED_DEVICES:
+      {
+        size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES;
+        ConvertArray<bt_bdaddr_t> array(
+          static_cast<bt_bdaddr_t*>(aIn.val), numAddresses);
+        aOut.mStringArray.SetLength(numAddresses);
+        rv = Convert(array, aOut.mStringArray);
+      }
+      break;
+    case PROPERTY_REMOTE_RSSI:
+      aOut.mInt32 = *static_cast<int32_t*>(aIn.val);
+      break;
+#if ANDROID_VERSION >= 18
+    case PROPERTY_REMOTE_VERSION_INFO:
+      rv = Convert(*static_cast<bt_remote_version_t*>(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
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothHALHelpers.h
@@ -0,0 +1,1430 @@
+/* -*- 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 <hardware/bluetooth.h>
+#include <hardware/bt_sock.h>
+#include <hardware/bt_hf.h>
+#include <hardware/bt_av.h>
+#if ANDROID_VERSION >= 18
+#include <hardware/bt_rc.h>
+#endif
+#include "BluetoothCommon.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/dom/bluetooth/BluetoothTypes.h"
+#include "nsThreadUtils.h"
+
+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<bt_status_t>(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, BluetoothSspVariant& aOut)
+{
+  static const BluetoothSspVariant sSspVariant[] = {
+    CONVERT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
+      SSP_VARIANT_PASSKEY_CONFIRMATION),
+    CONVERT(BT_SSP_VARIANT_PASSKEY_ENTRY, SSP_VARIANT_PASSKEY_ENTRY),
+    CONVERT(BT_SSP_VARIANT_CONSENT, SSP_VARIANT_CONSENT),
+    CONVERT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION,
+      SSP_VARIANT_PASSKEY_NOTIFICATION)
+  };
+  if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = 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<uint8_t>(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<BluetoothPropertyType>(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<const char*>(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, BluetoothTypeOfDevice& aOut)
+{
+  static const BluetoothTypeOfDevice sTypeOfDevice[] = {
+    CONVERT(0, static_cast<BluetoothTypeOfDevice>(0)), // invalid, required by gcc
+    CONVERT(BT_DEVICE_DEVTYPE_BREDR, TYPE_OF_DEVICE_BREDR),
+    CONVERT(BT_DEVICE_DEVTYPE_BLE, TYPE_OF_DEVICE_BLE),
+    CONVERT(BT_DEVICE_DEVTYPE_DUAL, TYPE_OF_DEVICE_DUAL)
+  };
+  if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sTypeOfDevice)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sTypeOfDevice[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<btsock_type_t>(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<BluetoothAvrcpPlayerAttribute>(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<BluetoothAvrcpEvent>(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<BluetoothAvrcpEvent>(0)), // invalid, [6] required by gcc
+    CONVERT(7, static_cast<BluetoothAvrcpEvent>(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<BluetoothAvrcpMediaAttribute>(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<unsigned long>(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<typename T>
+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<typename Tin, typename Tout>
+inline nsresult
+Convert(const ConvertArray<Tin>& 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<typename Tin, typename Tout>
+inline nsresult
+Convert(const ConvertArray<Tin>& aIn, nsAutoArrayPtr<Tout>& aOut)
+{
+  aOut = new Tout[aIn.mLength];
+  Tout* out = aOut.get();
+
+  return Convert<Tin, Tout*>(aIn, out);
+}
+
+/* |ConvertDefault| is a helper function to return the result of a
+ * conversion or a default value if the conversion fails.
+ */
+template<typename Tin, typename Tout>
+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<typename T>
+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<typename Obj, typename Res>
+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<Obj> mObj;
+  void (Obj::*mMethod)();
+};
+
+template<typename Obj, typename Res, typename Tin1, typename Arg1>
+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<Obj> mObj;
+  Res (Obj::*mMethod)(Arg1);
+  Tin1 mArg1;
+};
+
+template<typename Obj, typename Res,
+         typename Tin1, typename Tin2, typename Tin3,
+         typename Arg1, typename Arg2, typename Arg3>
+class 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<Obj> mObj;
+  Res (Obj::*mMethod)(Arg1, Arg2, Arg3);
+  Tin1 mArg1;
+  Tin2 mArg2;
+  Tin3 mArg3;
+};
+
+//
+// Notification handling
+//
+
+template<typename ObjectWrapper, typename Res>
+class BluetoothNotificationHALRunnable0 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationHALRunnable0<ObjectWrapper, Res> SelfType;
+
+  static already_AddRefed<SelfType> Create(Res (ObjectType::*aMethod)())
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+
+    return runnable.forget();
+  }
+
+  static void
+  Dispatch(Res (ObjectType::*aMethod)())
+  {
+    nsRefPtr<SelfType> 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<typename ObjectWrapper, typename Res,
+         typename Tin1, typename Arg1=Tin1>
+class BluetoothNotificationHALRunnable1 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationHALRunnable1<ObjectWrapper, Res,
+                                            Tin1, Arg1> SelfType;
+
+  template<typename T1>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+
+    if (NS_FAILED(runnable->ConvertAndSet(aIn1))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename T1>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
+  {
+    nsRefPtr<SelfType> 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<typename T1>
+  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<typename ObjectWrapper, typename Res,
+         typename Tin1, typename Tin2,
+         typename Arg1=Tin1, typename Arg2=Tin2>
+class BluetoothNotificationHALRunnable2 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationHALRunnable2<ObjectWrapper, Res,
+                                            Tin1, Tin2,
+                                            Arg1, Arg2> SelfType;
+
+  template<typename T1, typename T2>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2), const T1& aIn1, const T2& aIn2)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+
+    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename T1, typename T2>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2),
+           const T1& aIn1, const T2& aIn2)
+  {
+    nsRefPtr<SelfType> 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<typename T1, typename T2>
+  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<typename ObjectWrapper, typename Res,
+         typename Tin1, typename Tin2, typename Tin3,
+         typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3>
+class BluetoothNotificationHALRunnable3 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationHALRunnable3<ObjectWrapper, Res,
+                                            Tin1, Tin2, Tin3,
+                                            Arg1, Arg2, Arg3> SelfType;
+
+  template<typename T1, typename T2, typename T3>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+    const T1& aIn1, const T2& aIn2, const T3& aIn3)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+
+    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename T1, typename T2, typename T3>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
+           const T1& aIn1, const T2& aIn2, const T3& aIn3)
+  {
+    nsRefPtr<SelfType> 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<typename T1, typename T2, typename T3>
+  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<typename ObjectWrapper, typename Res,
+         typename Tin1, typename Tin2, typename Tin3, typename Tin4,
+         typename Arg1=Tin1, typename Arg2=Tin2,
+         typename Arg3=Tin3, typename Arg4=Tin4>
+class BluetoothNotificationHALRunnable4 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationHALRunnable4<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Arg1, Arg2, Arg3, Arg4> SelfType;
+
+  template<typename T1, typename T2, typename T3, typename T4>
+  static already_AddRefed<SelfType> Create(
+    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+    const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+
+    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename T1, typename T2, typename T3, typename T4>
+  static void
+  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
+           const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
+  {
+    nsRefPtr<SelfType> 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<typename T1, typename T2, typename T3, typename T4>
+  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<typename ObjectWrapper, typename Res,
+         typename Tin1, typename Tin2, typename Tin3,
+         typename Tin4, typename Tin5,
+         typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3,
+         typename Arg4=Tin4, typename Arg5=Tin5>
+class BluetoothNotificationHALRunnable5 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationHALRunnable5<ObjectWrapper, Res,
+    Tin1, Tin2, Tin3, Tin4, Tin5, Arg1, Arg2, Arg3, Arg4, Arg5> SelfType;
+
+  template<typename T1, typename T2, typename T3, typename T4, typename T5>
+  static already_AddRefed<SelfType> 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<SelfType> runnable(new SelfType(aMethod));
+
+    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5))) {
+      return nullptr;
+    }
+    return runnable.forget();
+  }
+
+  template<typename T1, typename T2, typename T3, typename T4, typename T5>
+  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<SelfType> 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<typename T1, typename T2, typename T3, typename T4, typename T5>
+  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
rename from dom/bluetooth2/bluedroid/BluetoothInterface.cpp
rename to dom/bluetooth2/bluedroid/BluetoothHALInterface.cpp
--- a/dom/bluetooth2/bluedroid/BluetoothInterface.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothHALInterface.cpp
@@ -1,3619 +1,107 @@
 /* -*- 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 <errno.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include "base/message_loop.h"
-#include "nsAutoPtr.h"
-#include "nsThreadUtils.h"
-#include "nsXULAppAPI.h"
-
-#define MAX_UUID_SIZE 16
+#include "BluetoothHALInterface.h"
+#include "BluetoothHALHelpers.h"
+#include "BluetoothA2dpHALInterface.h"
+#include "BluetoothAvrcpHALInterface.h"
+#include "BluetoothHandsfreeHALInterface.h"
+#include "BluetoothSocketHALInterface.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 template<class T>
 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<bt_status_t>(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<void*>(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<void*>(static_cast<const void*>(aIn.mStringValue.get()));
-    aOut.len = strlen(static_cast<char*>(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<uint8_t>(strtoul(str, const_cast<char**>(&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, BluetoothSspVariant& aOut)
-{
-  static const BluetoothSspVariant sSspVariant[] = {
-    CONVERT(BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
-      SSP_VARIANT_PASSKEY_CONFIRMATION),
-    CONVERT(BT_SSP_VARIANT_PASSKEY_ENTRY, SSP_VARIANT_PASSKEY_ENTRY),
-    CONVERT(BT_SSP_VARIANT_CONSENT, SSP_VARIANT_CONSENT),
-    CONVERT(BT_SSP_VARIANT_PASSKEY_NOTIFICATION,
-      SSP_VARIANT_PASSKEY_NOTIFICATION)
-  };
-  if (aIn >= MOZ_ARRAY_LENGTH(sSspVariant)) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-  aOut = 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<uint8_t>(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<uint8_t>(*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<int>(aIn.address[0]),
-                     static_cast<int>(aIn.address[1]),
-                     static_cast<int>(aIn.address[2]),
-                     static_cast<int>(aIn.address[3]),
-                     static_cast<int>(aIn.address[4]),
-                     static_cast<int>(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<BluetoothPropertyType>(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<const char*>(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, BluetoothTypeOfDevice& aOut)
-{
-  static const BluetoothTypeOfDevice sTypeOfDevice[] = {
-    CONVERT(0, static_cast<BluetoothTypeOfDevice>(0)), // invalid, required by gcc
-    CONVERT(BT_DEVICE_DEVTYPE_BREDR, TYPE_OF_DEVICE_BREDR),
-    CONVERT(BT_DEVICE_DEVTYPE_BLE, TYPE_OF_DEVICE_BLE),
-    CONVERT(BT_DEVICE_DEVTYPE_DUAL, TYPE_OF_DEVICE_DUAL)
-  };
-  if (!aIn || aIn >= MOZ_ARRAY_LENGTH(sTypeOfDevice)) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-  aOut = sTypeOfDevice[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<btsock_type_t>(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<BluetoothAvrcpPlayerAttribute>(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<BluetoothAvrcpEvent>(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<BluetoothAvrcpEvent>(0)), // invalid, [6] required by gcc
-    CONVERT(7, static_cast<BluetoothAvrcpEvent>(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<BluetoothAvrcpMediaAttribute>(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<size_t>(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<unsigned long>(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 <typename T>
-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<typename Tin, typename Tout>
-static nsresult
-Convert(const ConvertArray<Tin>& 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<typename Tin, typename Tout>
-static nsresult
-Convert(const ConvertArray<Tin>& aIn, nsAutoArrayPtr<Tout>& aOut)
-{
-  aOut = new Tout[aIn.mLength];
-  Tout* out = aOut.get();
-
-  return Convert<Tin, Tout*>(aIn, out);
-}
-
-/* |ConvertDefault| is a helper function to return the result of a
- * conversion or a default value if the conversion fails.
- */
-template<typename Tin, typename Tout>
-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<typename T>
-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<char*>(aIn.val), aIn.len));
-      }
-      break;
-    case PROPERTY_BDADDR:
-      rv = Convert(*static_cast<bt_bdaddr_t*>(aIn.val), aOut.mString);
-      break;
-    case PROPERTY_UUIDS:
-      {
-        size_t numUuids = aIn.len / MAX_UUID_SIZE;
-        ConvertArray<bt_uuid_t> array(
-          static_cast<bt_uuid_t*>(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<uint32_t*>(aIn.val);
-      break;
-    case PROPERTY_TYPE_OF_DEVICE:
-      rv = Convert(*static_cast<bt_device_type_t*>(aIn.val),
-                   aOut.mTypeOfDevice);
-      break;
-    case PROPERTY_SERVICE_RECORD:
-      rv = Convert(*static_cast<bt_service_record_t*>(aIn.val),
-                   aOut.mServiceRecord);
-      break;
-    case PROPERTY_ADAPTER_SCAN_MODE:
-      rv = Convert(*static_cast<bt_scan_mode_t*>(aIn.val),
-                   aOut.mScanMode);
-      break;
-    case PROPERTY_ADAPTER_BONDED_DEVICES:
-      {
-        size_t numAddresses = aIn.len / BLUETOOTH_ADDRESS_BYTES;
-        ConvertArray<bt_bdaddr_t> array(
-          static_cast<bt_bdaddr_t*>(aIn.val), numAddresses);
-        aOut.mStringArray.SetLength(numAddresses);
-        rv = Convert(array, aOut.mStringArray);
-      }
-      break;
-    case PROPERTY_REMOTE_RSSI:
-      aOut.mInt32 = *static_cast<int32_t*>(aIn.val);
-      break;
-    case PROPERTY_REMOTE_VERSION_INFO:
-      rv = Convert(*static_cast<bt_remote_version_t*>(aIn.val),
-                   aOut.mRemoteInfo);
-      break;
-    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 <typename Obj, typename Res>
-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<Obj> mObj;
-  void (Obj::*mMethod)();
-};
-
-template <typename Obj, typename Res, typename Tin1, typename Arg1>
-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<Obj> mObj;
-  Res (Obj::*mMethod)(Arg1);
-  Tin1 mArg1;
-};
-
-template <typename Obj, typename Res,
-          typename Tin1, typename Tin2, typename Tin3,
-          typename Arg1, typename Arg2, typename Arg3>
-class 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<Obj> mObj;
-  Res (Obj::*mMethod)(Arg1, Arg2, Arg3);
-  Tin1 mArg1;
-  Tin2 mArg2;
-  Tin3 mArg3;
-};
-
-//
-// Notification handling
-//
-
-template <typename ObjectWrapper, typename Res>
-class BluetoothNotificationRunnable0 : public nsRunnable
-{
-public:
-  typedef typename ObjectWrapper::ObjectType  ObjectType;
-  typedef BluetoothNotificationRunnable0<ObjectWrapper, Res> SelfType;
-
-  static already_AddRefed<SelfType> Create(Res (ObjectType::*aMethod)())
-  {
-    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
-
-    return runnable.forget();
-  }
-
-  static void
-  Dispatch(Res (ObjectType::*aMethod)())
-  {
-    nsRefPtr<SelfType> 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 <typename ObjectWrapper, typename Res,
-          typename Tin1, typename Arg1=Tin1>
-class BluetoothNotificationRunnable1 : public nsRunnable
-{
-public:
-  typedef typename ObjectWrapper::ObjectType  ObjectType;
-  typedef BluetoothNotificationRunnable1<ObjectWrapper, Res,
-                                         Tin1, Arg1> SelfType;
-
-  template <typename T1>
-  static already_AddRefed<SelfType> Create(
-    Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
-  {
-    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
-
-    if (NS_FAILED(runnable->ConvertAndSet(aIn1))) {
-      return nullptr;
-    }
-    return runnable.forget();
-  }
-
-  template <typename T1>
-  static void
-  Dispatch(Res (ObjectType::*aMethod)(Arg1), const T1& aIn1)
-  {
-    nsRefPtr<SelfType> 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<typename T1>
-  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 <typename ObjectWrapper, typename Res,
-          typename Tin1, typename Tin2,
-          typename Arg1=Tin1, typename Arg2=Tin2>
-class BluetoothNotificationRunnable2 : public nsRunnable
-{
-public:
-  typedef typename ObjectWrapper::ObjectType  ObjectType;
-  typedef BluetoothNotificationRunnable2<ObjectWrapper, Res,
-                                         Tin1, Tin2, Arg1, Arg2> SelfType;
-
-  template <typename T1, typename T2>
-  static already_AddRefed<SelfType> Create(
-    Res (ObjectType::*aMethod)(Arg1, Arg2), const T1& aIn1, const T2& aIn2)
-  {
-    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
-
-    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2))) {
-      return nullptr;
-    }
-    return runnable.forget();
-  }
-
-  template <typename T1, typename T2>
-  static void
-  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2),
-           const T1& aIn1, const T2& aIn2)
-  {
-    nsRefPtr<SelfType> runnable = Create(aMethod, aIn1, aIn2);
-
-    if (!runnable) {
-      BT_WARNING("BluetoothNotificationRunnable2::Create failed");
-      return;
-    }
-    nsresult rv = NS_DispatchToMainThread(runnable);
-    if (NS_FAILED(rv)) {
-      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-    }
-  }
-
-  NS_METHOD
-  Run() 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:
-  BluetoothNotificationRunnable2(Res (ObjectType::*aMethod)(Arg1, Arg2))
-  : mMethod(aMethod)
-  {
-    MOZ_ASSERT(mMethod);
-  }
-
-  template<typename T1, typename T2>
-  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 <typename ObjectWrapper, typename Res,
-          typename Tin1, typename Tin2, typename Tin3,
-          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3>
-class BluetoothNotificationRunnable3 : public nsRunnable
-{
-public:
-  typedef typename ObjectWrapper::ObjectType  ObjectType;
-  typedef BluetoothNotificationRunnable3<ObjectWrapper, Res,
-                                         Tin1, Tin2, Tin3,
-                                         Arg1, Arg2, Arg3> SelfType;
-
-  template <typename T1, typename T2, typename T3>
-  static already_AddRefed<SelfType> Create(
-    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
-    const T1& aIn1, const T2& aIn2, const T3& aIn3)
-  {
-    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
-
-    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3))) {
-      return nullptr;
-    }
-    return runnable.forget();
-  }
-
-  template <typename T1, typename T2, typename T3>
-  static void
-  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3),
-           const T1& aIn1, const T2& aIn2, const T3& aIn3)
-  {
-    nsRefPtr<SelfType> runnable = Create(aMethod, aIn1, aIn2, aIn3);
-
-    if (!runnable) {
-      BT_WARNING("BluetoothNotificationRunnable3::Create failed");
-      return;
-    }
-    nsresult rv = NS_DispatchToMainThread(runnable);
-    if (NS_FAILED(rv)) {
-      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-    }
-  }
-
-  NS_METHOD
-  Run() 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:
-  BluetoothNotificationRunnable3(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3))
-  : mMethod(aMethod)
-  {
-    MOZ_ASSERT(mMethod);
-  }
-
-  template<typename T1, typename T2, typename T3>
-  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 <typename ObjectWrapper, typename Res,
-          typename Tin1, typename Tin2, typename Tin3, typename Tin4,
-          typename Arg1=Tin1, typename Arg2=Tin2,
-          typename Arg3=Tin3, typename Arg4=Tin4>
-class BluetoothNotificationRunnable4 : public nsRunnable
-{
-public:
-  typedef typename ObjectWrapper::ObjectType  ObjectType;
-  typedef BluetoothNotificationRunnable4<ObjectWrapper, Res,
-    Tin1, Tin2, Tin3, Tin4, Arg1, Arg2, Arg3, Arg4> SelfType;
-
-  template <typename T1, typename T2, typename T3, typename T4>
-  static already_AddRefed<SelfType> Create(
-    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
-    const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
-  {
-    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
-
-    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4))) {
-      return nullptr;
-    }
-    return runnable.forget();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4>
-  static void
-  Dispatch(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4),
-           const T1& aIn1, const T2& aIn2, const T3& aIn3, const T4& aIn4)
-  {
-    nsRefPtr<SelfType> runnable = Create(aMethod, aIn1, aIn2, aIn3, aIn4);
-
-    if (!runnable) {
-      BT_WARNING("BluetoothNotificationRunnable4::Create failed");
-      return;
-    }
-    nsresult rv = NS_DispatchToMainThread(runnable);
-    if (NS_FAILED(rv)) {
-      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-    }
-  }
-
-  NS_METHOD
-  Run() 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:
-  BluetoothNotificationRunnable4(
-    Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3, Arg4))
-  : mMethod(aMethod)
-  {
-    MOZ_ASSERT(mMethod);
-  }
-
-  template<typename T1,typename T2, typename T3, typename T4>
-  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 <typename ObjectWrapper, typename Res,
-          typename Tin1, typename Tin2, typename Tin3,
-          typename Tin4, typename Tin5,
-          typename Arg1=Tin1, typename Arg2=Tin2, typename Arg3=Tin3,
-          typename Arg4=Tin4, typename Arg5=Tin5>
-class BluetoothNotificationRunnable5 : public nsRunnable
-{
-public:
-  typedef typename ObjectWrapper::ObjectType  ObjectType;
-  typedef BluetoothNotificationRunnable5<ObjectWrapper, Res,
-    Tin1, Tin2, Tin3, Tin4, Tin5, Arg1, Arg2, Arg3, Arg4, Arg5> SelfType;
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  static already_AddRefed<SelfType> 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<SelfType> runnable(new SelfType(aMethod));
-
-    if (NS_FAILED(runnable->ConvertAndSet(aIn1, aIn2, aIn3, aIn4, aIn5))) {
-      return nullptr;
-    }
-    return runnable.forget();
-  }
-
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  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<SelfType> runnable = Create(aMethod,
-                                         aIn1, aIn2, aIn3, aIn4, aIn5);
-    if (!runnable) {
-      BT_WARNING("BluetoothNotificationRunnable5::Create failed");
-      return;
-    }
-    nsresult rv = NS_DispatchToMainThread(runnable);
-    if (NS_FAILED(rv)) {
-      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-    }
-  }
-
-  NS_METHOD
-  Run() 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:
-  BluetoothNotificationRunnable5(Res (ObjectType::*aMethod)(Arg1, Arg2, Arg3,
-                                                            Arg4, Arg5))
-  : mMethod(aMethod)
-  {
-    MOZ_ASSERT(mMethod);
-  }
-
-  template<typename T1, typename T2, typename T3, typename T4, typename T5>
-  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;
-};
-
-//
-// Socket Interface
-//
-
 template<>
-struct interface_traits<BluetoothSocketInterface>
+struct interface_traits<BluetoothSocketHALInterface>
 {
   typedef const btsock_interface_t const_interface_type;
 
   static const char* profile_id()
   {
     return BT_PROFILE_SOCKETS_ID;
   }
 };
 
-typedef
-  BluetoothInterfaceRunnable1<BluetoothSocketResultHandler, void, int, int>
-  BluetoothSocketIntResultRunnable;
-
-typedef
-  BluetoothInterfaceRunnable3<BluetoothSocketResultHandler, void,
-                              int, const nsString, int,
-                              int, const nsAString_internal&, int>
-  BluetoothSocketIntStringIntResultRunnable;
-
-typedef
-  BluetoothInterfaceRunnable1<BluetoothSocketResultHandler, void,
-                              BluetoothStatus, BluetoothStatus>
-  BluetoothSocketErrorRunnable;
-
-static nsresult
-DispatchBluetoothSocketResult(BluetoothSocketResultHandler* aRes,
-                              void (BluetoothSocketResultHandler::*aMethod)(int),
-                              int aArg, BluetoothStatus aStatus)
-{
-  MOZ_ASSERT(aRes);
-
-  nsRunnable* runnable;
-
-  if (aStatus == STATUS_SUCCESS) {
-    runnable = new BluetoothSocketIntResultRunnable(aRes, aMethod, aArg);
-  } else {
-    runnable = new BluetoothSocketErrorRunnable(aRes,
-      &BluetoothSocketResultHandler::OnError, aStatus);
-  }
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-  }
-  return rv;
-}
-
-static nsresult
-DispatchBluetoothSocketResult(
-  BluetoothSocketResultHandler* aRes,
-  void (BluetoothSocketResultHandler::*aMethod)(int, const nsAString&, int),
-  int aArg1, const nsAString& aArg2, int aArg3, BluetoothStatus aStatus)
-{
-  MOZ_ASSERT(aRes);
-
-  nsRunnable* runnable;
-
-  if (aStatus == STATUS_SUCCESS) {
-    runnable = new BluetoothSocketIntStringIntResultRunnable(aRes, aMethod,
-                                                             aArg1, aArg2,
-                                                             aArg3);
-  } else {
-    runnable = new BluetoothSocketErrorRunnable(aRes,
-      &BluetoothSocketResultHandler::OnError, aStatus);
-  }
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-  }
-  return rv;
-}
-
-void
-BluetoothSocketInterface::Listen(BluetoothSocketType aType,
-                                 const nsAString& aServiceName,
-                                 const uint8_t aServiceUuid[16],
-                                 int aChannel, bool aEncrypt, bool aAuth,
-                                 BluetoothSocketResultHandler* aRes)
-{
-  int fd;
-  bt_status_t status;
-  btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning
-
-  if (NS_SUCCEEDED(Convert(aType, type))) {
-    status = mInterface->listen(type,
-                                NS_ConvertUTF16toUTF8(aServiceName).get(),
-                                aServiceUuid, aChannel, &fd,
-                                (BTSOCK_FLAG_ENCRYPT * aEncrypt) |
-                                (BTSOCK_FLAG_AUTH * aAuth));
-  } else {
-    status = BT_STATUS_PARM_INVALID;
-  }
-
-  if (aRes) {
-    DispatchBluetoothSocketResult(aRes, &BluetoothSocketResultHandler::Listen,
-                                  fd, ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-#define CMSGHDR_CONTAINS_FD(_cmsghdr) \
-    ( ((_cmsghdr)->cmsg_level == SOL_SOCKET) && \
-      ((_cmsghdr)->cmsg_type == SCM_RIGHTS) )
-
-/* |SocketMessageWatcher| receives Bluedroid's socket setup
- * messages on the I/O thread. You need to inherit from this
- * class to make use of it.
- *
- * Bluedroid sends two socket info messages (20 bytes) at
- * the beginning of a connection to both peers.
- *
- *   - 1st message: [channel:4]
- *   - 2nd message: [size:2][bd address:6][channel:4][connection status:4]
- *
- * On the server side, the second message will contain a
- * socket file descriptor for the connection. The client
- * uses the original file descriptor.
- */
-class SocketMessageWatcher : public MessageLoopForIO::Watcher
-{
-public:
-  static const unsigned char MSG1_SIZE = 4;
-  static const unsigned char MSG2_SIZE = 16;
-
-  static const unsigned char OFF_CHANNEL1 = 0;
-  static const unsigned char OFF_SIZE = 4;
-  static const unsigned char OFF_BDADDRESS = 6;
-  static const unsigned char OFF_CHANNEL2 = 12;
-  static const unsigned char OFF_STATUS = 16;
-
-  SocketMessageWatcher(int aFd)
-  : mFd(aFd)
-  , mClientFd(-1)
-  , mLen(0)
-  { }
-
-  virtual ~SocketMessageWatcher()
-  { }
-
-  virtual void Proceed(BluetoothStatus aStatus) = 0;
-
-  void OnFileCanReadWithoutBlocking(int aFd) MOZ_OVERRIDE
-  {
-    BluetoothStatus status;
-
-    switch (mLen) {
-      case 0:
-        status = RecvMsg1();
-        break;
-      case MSG1_SIZE:
-        status = RecvMsg2();
-        break;
-      default:
-        /* message-size error */
-        status = STATUS_FAIL;
-        break;
-    }
-
-    if (IsComplete() || status != STATUS_SUCCESS) {
-      mWatcher.StopWatchingFileDescriptor();
-      Proceed(status);
-    }
-  }
-
-  void OnFileCanWriteWithoutBlocking(int aFd) MOZ_OVERRIDE
-  { }
-
-  void Watch()
-  {
-    MessageLoopForIO::current()->WatchFileDescriptor(
-      mFd,
-      true,
-      MessageLoopForIO::WATCH_READ,
-      &mWatcher,
-      this);
-  }
-
-  bool IsComplete() const
-  {
-    return mLen == (MSG1_SIZE + MSG2_SIZE);
-  }
-
-  int GetFd() const
-  {
-    return mFd;
-  }
-
-  int32_t GetChannel1() const
-  {
-    return ReadInt32(OFF_CHANNEL1);
-  }
-
-  int32_t GetSize() const
-  {
-    return ReadInt16(OFF_SIZE);
-  }
-
-  nsString GetBdAddress() const
-  {
-    nsString bdAddress;
-    ReadBdAddress(OFF_BDADDRESS, bdAddress);
-    return bdAddress;
-  }
-
-  int32_t GetChannel2() const
-  {
-    return ReadInt32(OFF_CHANNEL2);
-  }
-
-  int32_t GetConnectionStatus() const
-  {
-    return ReadInt32(OFF_STATUS);
-  }
-
-  int GetClientFd() const
-  {
-    return mClientFd;
-  }
-
-private:
-  BluetoothStatus RecvMsg1()
-  {
-    struct iovec iv;
-    memset(&iv, 0, sizeof(iv));
-    iv.iov_base = mBuf;
-    iv.iov_len = MSG1_SIZE;
-
-    struct msghdr msg;
-    memset(&msg, 0, sizeof(msg));
-    msg.msg_iov = &iv;
-    msg.msg_iovlen = 1;
-
-    ssize_t res = TEMP_FAILURE_RETRY(recvmsg(mFd, &msg, MSG_NOSIGNAL));
-    if (res < 0) {
-      return STATUS_FAIL;
-    }
-
-    mLen += res;
-
-    return STATUS_SUCCESS;
-  }
-
-  BluetoothStatus RecvMsg2()
-  {
-    struct iovec iv;
-    memset(&iv, 0, sizeof(iv));
-    iv.iov_base = mBuf + MSG1_SIZE;
-    iv.iov_len = MSG2_SIZE;
-
-    struct msghdr msg;
-    struct cmsghdr cmsgbuf[2 * sizeof(cmsghdr) + 0x100];
-    memset(&msg, 0, sizeof(msg));
-    msg.msg_iov = &iv;
-    msg.msg_iovlen = 1;
-    msg.msg_control = cmsgbuf;
-    msg.msg_controllen = sizeof(cmsgbuf);
-
-    ssize_t res = TEMP_FAILURE_RETRY(recvmsg(mFd, &msg, MSG_NOSIGNAL));
-    if (res < 0) {
-      return STATUS_FAIL;
-    }
-
-    mLen += res;
-
-    if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) {
-      return STATUS_FAIL;
-    }
-
-    struct cmsghdr *cmsgptr = CMSG_FIRSTHDR(&msg);
-
-    // Extract client fd from message header
-    for (; cmsgptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
-      if (CMSGHDR_CONTAINS_FD(cmsgptr)) {
-        // if multiple file descriptors have been sent, we close
-        // all but the final one.
-        if (mClientFd != -1) {
-          TEMP_FAILURE_RETRY(close(mClientFd));
-        }
-        // retrieve sent client fd
-        mClientFd = *(static_cast<int*>(CMSG_DATA(cmsgptr)));
-      }
-    }
-
-    return STATUS_SUCCESS;
-  }
-
-  int16_t ReadInt16(unsigned long aOffset) const
-  {
-    /* little-endian buffer */
-    return (static_cast<int16_t>(mBuf[aOffset + 1]) << 8) |
-            static_cast<int16_t>(mBuf[aOffset]);
-  }
-
-  int32_t ReadInt32(unsigned long aOffset) const
-  {
-    /* little-endian buffer */
-    return (static_cast<int32_t>(mBuf[aOffset + 3]) << 24) |
-           (static_cast<int32_t>(mBuf[aOffset + 2]) << 16) |
-           (static_cast<int32_t>(mBuf[aOffset + 1]) << 8) |
-            static_cast<int32_t>(mBuf[aOffset]);
-  }
-
-  void ReadBdAddress(unsigned long aOffset, nsAString& aBdAddress) const
-  {
-    const bt_bdaddr_t* bdAddress =
-      reinterpret_cast<const bt_bdaddr_t*>(mBuf+aOffset);
-
-    if (NS_FAILED(Convert(*bdAddress, aBdAddress))) {
-      aBdAddress.AssignLiteral(BLUETOOTH_ADDRESS_NONE);
-    }
-  }
-
-  MessageLoopForIO::FileDescriptorWatcher mWatcher;
-  int mFd;
-  int mClientFd;
-  unsigned char mLen;
-  uint8_t mBuf[MSG1_SIZE + MSG2_SIZE];
-};
-
-/* |SocketMessageWatcherTask| starts a SocketMessageWatcher
- * on the I/O task
- */
-class SocketMessageWatcherTask MOZ_FINAL : public Task
-{
-public:
-  SocketMessageWatcherTask(SocketMessageWatcher* aWatcher)
-  : mWatcher(aWatcher)
-  {
-    MOZ_ASSERT(mWatcher);
-  }
-
-  void Run() MOZ_OVERRIDE
-  {
-    mWatcher->Watch();
-  }
-
-private:
-  SocketMessageWatcher* mWatcher;
-};
-
-/* |DeleteTask| deletes a class instance on the I/O thread
- */
-template <typename T>
-class DeleteTask MOZ_FINAL : public Task
-{
-public:
-  DeleteTask(T* aPtr)
-  : mPtr(aPtr)
-  { }
-
-  void Run() MOZ_OVERRIDE
-  {
-    mPtr = nullptr;
-  }
-
-private:
-  nsAutoPtr<T> mPtr;
-};
-
-/* |ConnectWatcher| specializes SocketMessageWatcher for
- * connect operations by reading the socket messages from
- * Bluedroid and forwarding the connected socket to the
- * resource handler.
- */
-class ConnectWatcher MOZ_FINAL : public SocketMessageWatcher
-{
-public:
-  ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes)
-  : SocketMessageWatcher(aFd)
-  , mRes(aRes)
-  { }
-
-  void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE
-  {
-    if (mRes) {
-      DispatchBluetoothSocketResult(mRes,
-                                   &BluetoothSocketResultHandler::Connect,
-                                    GetFd(), GetBdAddress(),
-                                    GetConnectionStatus(), aStatus);
-    }
-    MessageLoopForIO::current()->PostTask(
-      FROM_HERE, new DeleteTask<ConnectWatcher>(this));
-  }
-
-private:
-  nsRefPtr<BluetoothSocketResultHandler> mRes;
-};
-
-void
-BluetoothSocketInterface::Connect(const nsAString& aBdAddr,
-                                  BluetoothSocketType aType,
-                                  const uint8_t aUuid[16],
-                                  int aChannel, bool aEncrypt, bool aAuth,
-                                  BluetoothSocketResultHandler* aRes)
-{
-  int fd;
-  bt_status_t status;
-  bt_bdaddr_t bdAddr;
-  btsock_type_t type = BTSOCK_RFCOMM; // silences compiler warning
-
-  if (NS_SUCCEEDED(Convert(aBdAddr, bdAddr)) &&
-      NS_SUCCEEDED(Convert(aType, type))) {
-    status = mInterface->connect(&bdAddr, type, aUuid, aChannel, &fd,
-                                 (BTSOCK_FLAG_ENCRYPT * aEncrypt) |
-                                 (BTSOCK_FLAG_AUTH * aAuth));
-  } else {
-    status = BT_STATUS_PARM_INVALID;
-  }
-
-  if (status == BT_STATUS_SUCCESS) {
-    /* receive Bluedroid's socket-setup messages */
-    Task* t = new SocketMessageWatcherTask(new ConnectWatcher(fd, aRes));
-    XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
-  } else if (aRes) {
-    DispatchBluetoothSocketResult(aRes,
-                                  &BluetoothSocketResultHandler::Connect,
-                                  -1, EmptyString(), 0,
-                                  ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-/* |AcceptWatcher| specializes |SocketMessageWatcher| for accept
- * operations by reading the socket messages from Bluedroid and
- * forwarding the received client socket to the resource handler.
- * The first message is received immediately. When there's a new
- * connection, Bluedroid sends the 2nd message with the socket
- * info and socket file descriptor.
- */
-class AcceptWatcher MOZ_FINAL : public SocketMessageWatcher
-{
-public:
-  AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes)
-  : SocketMessageWatcher(aFd)
-  , mRes(aRes)
-  {
-    /* not supplying a result handler leaks received file descriptor */
-    MOZ_ASSERT(mRes);
-  }
-
-  void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE
-  {
-    if (mRes) {
-      DispatchBluetoothSocketResult(mRes,
-                                    &BluetoothSocketResultHandler::Accept,
-                                    GetClientFd(), GetBdAddress(),
-                                    GetConnectionStatus(),
-                                    aStatus);
-    }
-    MessageLoopForIO::current()->PostTask(
-      FROM_HERE, new DeleteTask<AcceptWatcher>(this));
-  }
-
-private:
-  nsRefPtr<BluetoothSocketResultHandler> mRes;
-};
-
-void
-BluetoothSocketInterface::Accept(int aFd, BluetoothSocketResultHandler* aRes)
-{
-  /* receive Bluedroid's socket-setup messages and client fd */
-  Task* t = new SocketMessageWatcherTask(new AcceptWatcher(aFd, aRes));
-  XRE_GetIOMessageLoop()->PostTask(FROM_HERE, t);
-}
-
-BluetoothSocketInterface::BluetoothSocketInterface(
-  const btsock_interface_t* aInterface)
-: mInterface(aInterface)
-{
-  MOZ_ASSERT(mInterface);
-}
-
-BluetoothSocketInterface::~BluetoothSocketInterface()
-{ }
-
-//
-// Handsfree Interface
-//
-
 template<>
-struct interface_traits<BluetoothHandsfreeInterface>
+struct interface_traits<BluetoothHandsfreeHALInterface>
 {
   typedef const bthf_interface_t const_interface_type;
 
   static const char* profile_id()
   {
     return BT_PROFILE_HANDSFREE_ID;
   }
 };
 
-typedef
-  BluetoothInterfaceRunnable0<BluetoothHandsfreeResultHandler, void>
-  BluetoothHandsfreeResultRunnable;
-
-typedef
-  BluetoothInterfaceRunnable1<BluetoothHandsfreeResultHandler, void,
-                              BluetoothStatus, BluetoothStatus>
-  BluetoothHandsfreeErrorRunnable;
-
-static nsresult
-DispatchBluetoothHandsfreeResult(
-  BluetoothHandsfreeResultHandler* aRes,
-  void (BluetoothHandsfreeResultHandler::*aMethod)(),
-  BluetoothStatus aStatus)
-{
-  MOZ_ASSERT(aRes);
-
-  nsRunnable* runnable;
-
-  if (aStatus == STATUS_SUCCESS) {
-    runnable = new BluetoothHandsfreeResultRunnable(aRes, aMethod);
-  } else {
-    runnable = new BluetoothHandsfreeErrorRunnable(aRes,
-      &BluetoothHandsfreeResultHandler::OnError, aStatus);
-  }
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-  }
-  return rv;
-}
-
-// Notification handling
-//
-
-BluetoothHandsfreeNotificationHandler::
-  ~BluetoothHandsfreeNotificationHandler()
-{ }
-
-static BluetoothHandsfreeNotificationHandler* sHandsfreeNotificationHandler;
-
-struct BluetoothHandsfreeCallback
-{
-  class HandsfreeNotificationHandlerWrapper
-  {
-  public:
-    typedef BluetoothHandsfreeNotificationHandler ObjectType;
-
-    static ObjectType* GetInstance()
-    {
-      MOZ_ASSERT(NS_IsMainThread());
-
-      return sHandsfreeNotificationHandler;
-    }
-  };
-
-  // Notifications
-
-  typedef BluetoothNotificationRunnable2<HandsfreeNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothHandsfreeConnectionState,
-                                         nsString,
-                                         BluetoothHandsfreeConnectionState,
-                                         const nsAString&>
-    ConnectionStateNotification;
-
-  typedef BluetoothNotificationRunnable2<HandsfreeNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothHandsfreeAudioState,
-                                         nsString,
-                                         BluetoothHandsfreeAudioState,
-                                         const nsAString&>
-    AudioStateNotification;
-
-  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothHandsfreeVoiceRecognitionState>
-    VoiceRecognitionNotification;
-
-  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
-                                         void>
-    AnswerCallNotification;
-
-  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
-                                         void>
-    HangupCallNotification;
-
-  typedef BluetoothNotificationRunnable2<HandsfreeNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothHandsfreeVolumeType, int>
-    VolumeNotification;
-
-  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
-                                         void, nsString, const nsAString&>
-    DialCallNotification;
-
-  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
-                                         void, char>
-    DtmfNotification;
-
-  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothHandsfreeNRECState>
-    NRECNotification;
-
-  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothHandsfreeCallHoldType>
-    CallHoldNotification;
-
-  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
-                                         void>
-    CnumNotification;
-
-  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
-                                         void>
-    CindNotification;
-
-  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
-                                         void>
-    CopsNotification;
-
-  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
-                                         void>
-    ClccNotification;
-
-  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
-                                         void, nsCString, const nsACString&>
-    UnknownAtNotification;
-
-  typedef BluetoothNotificationRunnable0<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
-//
-
-BluetoothHandsfreeInterface::BluetoothHandsfreeInterface(
-  const bthf_interface_t* aInterface)
-: mInterface(aInterface)
-{
-  MOZ_ASSERT(mInterface);
-}
-
-BluetoothHandsfreeInterface::~BluetoothHandsfreeInterface()
-{ }
-
-void
-BluetoothHandsfreeInterface::Init(
-  BluetoothHandsfreeNotificationHandler* aNotificationHandler,
-  BluetoothHandsfreeResultHandler* aRes)
-{
-  static bthf_callbacks_t sCallbacks = {
-    .size = sizeof(sCallbacks),
-    .connection_state_cb = BluetoothHandsfreeCallback::ConnectionState,
-    .audio_state_cb = BluetoothHandsfreeCallback::AudioState,
-    .vr_cmd_cb = BluetoothHandsfreeCallback::VoiceRecognition,
-    .answer_call_cmd_cb = BluetoothHandsfreeCallback::AnswerCall,
-    .hangup_call_cmd_cb = BluetoothHandsfreeCallback::HangupCall,
-    .volume_cmd_cb = BluetoothHandsfreeCallback::Volume,
-    .dial_call_cmd_cb = BluetoothHandsfreeCallback::DialCall,
-    .dtmf_cmd_cb = BluetoothHandsfreeCallback::Dtmf,
-    .nrec_cmd_cb = BluetoothHandsfreeCallback::NoiseReductionEchoCancellation,
-    .chld_cmd_cb = BluetoothHandsfreeCallback::CallHold,
-    .cnum_cmd_cb = BluetoothHandsfreeCallback::Cnum,
-    .cind_cmd_cb = BluetoothHandsfreeCallback::Cind,
-    .cops_cmd_cb = BluetoothHandsfreeCallback::Cops,
-    .clcc_cmd_cb = BluetoothHandsfreeCallback::Clcc,
-    .unknown_at_cmd_cb = BluetoothHandsfreeCallback::UnknownAt,
-    .key_pressed_cmd_cb = BluetoothHandsfreeCallback::KeyPressed
-  };
-
-  sHandsfreeNotificationHandler = aNotificationHandler;
-
-  bt_status_t status = mInterface->init(&sCallbacks);
-
-  if (aRes) {
-    DispatchBluetoothHandsfreeResult(aRes,
-                                     &BluetoothHandsfreeResultHandler::Init,
-                                     ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::Cleanup(BluetoothHandsfreeResultHandler* aRes)
-{
-  mInterface->cleanup();
-
-  if (aRes) {
-    DispatchBluetoothHandsfreeResult(aRes,
-                                     &BluetoothHandsfreeResultHandler::Cleanup,
-                                     STATUS_SUCCESS);
-  }
-}
-
-/* Connect / Disconnect */
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::Connect,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::Disconnect,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::ConnectAudio,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::DisconnectAudio,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-/* Voice Recognition */
-
-void
-BluetoothHandsfreeInterface::StartVoiceRecognition(
-  BluetoothHandsfreeResultHandler* aRes)
-{
-  bt_status_t status = mInterface->start_voice_recognition();
-
-  if (aRes) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::StartVoiceRecognition,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::StopVoiceRecognition(
-  BluetoothHandsfreeResultHandler* aRes)
-{
-  bt_status_t status = mInterface->stop_voice_recognition();
-
-  if (aRes) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-/* Volume */
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::VolumeControl,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-/* Device status */
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::DeviceStatusNotification,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-/* Responses */
-
-void
-BluetoothHandsfreeInterface::CopsResponse(
-  const char* aCops, BluetoothHandsfreeResultHandler* aRes)
-{
-  bt_status_t status = mInterface->cops_response(aCops);
-
-  if (aRes) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::CopsResponse,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::CindResponse,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::FormattedAtResponse(
-  const char* aRsp, BluetoothHandsfreeResultHandler* aRes)
-{
-  bt_status_t status = mInterface->formatted_at_response(aRsp);
-
-  if (aRes) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::AtResponse,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::ClccResponse,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-/* Phone State */
-
-void
-BluetoothHandsfreeInterface::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) {
-    DispatchBluetoothHandsfreeResult(
-      aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-//
-// Bluetooth Advanced Audio Interface
-//
-
 template<>
-struct interface_traits<BluetoothA2dpInterface>
+struct interface_traits<BluetoothA2dpHALInterface>
 {
   typedef const btav_interface_t const_interface_type;
 
   static const char* profile_id()
   {
     return BT_PROFILE_ADVANCED_AUDIO_ID;
   }
 };
 
-typedef
-  BluetoothInterfaceRunnable0<BluetoothA2dpResultHandler, void>
-  BluetoothA2dpResultRunnable;
-
-typedef
-  BluetoothInterfaceRunnable1<BluetoothA2dpResultHandler, void,
-                              BluetoothStatus, BluetoothStatus>
-  BluetoothA2dpErrorRunnable;
-
-static nsresult
-DispatchBluetoothA2dpResult(
-  BluetoothA2dpResultHandler* aRes,
-  void (BluetoothA2dpResultHandler::*aMethod)(),
-  BluetoothStatus aStatus)
-{
-  MOZ_ASSERT(aRes);
-
-  nsRunnable* runnable;
-
-  if (aStatus == STATUS_SUCCESS) {
-    runnable = new BluetoothA2dpResultRunnable(aRes, aMethod);
-  } else {
-    runnable = new BluetoothA2dpErrorRunnable(aRes,
-      &BluetoothA2dpResultHandler::OnError, aStatus);
-  }
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-  }
-  return rv;
-}
-
-// Notification handling
-//
-
-BluetoothA2dpNotificationHandler::~BluetoothA2dpNotificationHandler()
-{ }
-
-static BluetoothA2dpNotificationHandler* sA2dpNotificationHandler;
-
-struct BluetoothA2dpCallback
-{
-  class A2dpNotificationHandlerWrapper
-  {
-  public:
-    typedef BluetoothA2dpNotificationHandler ObjectType;
-
-    static ObjectType* GetInstance()
-    {
-      MOZ_ASSERT(NS_IsMainThread());
-
-      return sA2dpNotificationHandler;
-    }
-  };
-
-  // Notifications
-
-  typedef BluetoothNotificationRunnable2<A2dpNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothA2dpConnectionState,
-                                         nsString,
-                                         BluetoothA2dpConnectionState,
-                                         const nsAString&>
-    ConnectionStateNotification;
-
-  typedef BluetoothNotificationRunnable2<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
-//
-
-BluetoothA2dpInterface::BluetoothA2dpInterface(
-  const btav_interface_t* aInterface)
-: mInterface(aInterface)
-{
-  MOZ_ASSERT(mInterface);
-}
-
-BluetoothA2dpInterface::~BluetoothA2dpInterface()
-{ }
-
-void
-BluetoothA2dpInterface::Init(
-  BluetoothA2dpNotificationHandler* aNotificationHandler,
-  BluetoothA2dpResultHandler* aRes)
-{
-  static btav_callbacks_t sCallbacks = {
-    sizeof(sCallbacks),
-    BluetoothA2dpCallback::ConnectionState,
-    BluetoothA2dpCallback::AudioState
-  };
-
-  sA2dpNotificationHandler = aNotificationHandler;
-
-  bt_status_t status = mInterface->init(&sCallbacks);
-
-  if (aRes) {
-    DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Init,
-                                ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothA2dpInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
-{
-  mInterface->cleanup();
-
-  if (aRes) {
-    DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Cleanup,
-                                STATUS_SUCCESS);
-  }
-}
-
-void
-BluetoothA2dpInterface::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) {
-    DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Connect,
-                                ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothA2dpInterface::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) {
-    DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Disconnect,
-                                ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-//
-// Bluetooth AVRCP Interface
-//
-
 #if ANDROID_VERSION >= 18
 template<>
-struct interface_traits<BluetoothAvrcpInterface>
+struct interface_traits<BluetoothAvrcpHALInterface>
 {
   typedef const btrc_interface_t const_interface_type;
 
   static const char* profile_id()
   {
     return BT_PROFILE_AV_RC_ID;
   }
 };
 #endif
 
 typedef
-  BluetoothInterfaceRunnable0<BluetoothAvrcpResultHandler, void>
-  BluetoothAvrcpResultRunnable;
+  BluetoothHALInterfaceRunnable0<BluetoothResultHandler, void>
+  BluetoothHALResultRunnable;
 
 typedef
-  BluetoothInterfaceRunnable1<BluetoothAvrcpResultHandler, void,
-                              BluetoothStatus, BluetoothStatus>
-  BluetoothAvrcpErrorRunnable;
+  BluetoothHALInterfaceRunnable1<BluetoothResultHandler, void,
+                                 BluetoothStatus, BluetoothStatus>
+  BluetoothHALErrorRunnable;
 
 static nsresult
-DispatchBluetoothAvrcpResult(
-  BluetoothAvrcpResultHandler* aRes,
-  void (BluetoothAvrcpResultHandler::*aMethod)(),
-  BluetoothStatus aStatus)
+DispatchBluetoothHALResult(BluetoothResultHandler* aRes,
+                           void (BluetoothResultHandler::*aMethod)(),
+                           BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
   nsRunnable* runnable;
 
   if (aStatus == STATUS_SUCCESS) {
-    runnable = new BluetoothAvrcpResultRunnable(aRes, aMethod);
-  } else {
-    runnable = new BluetoothAvrcpErrorRunnable(aRes,
-      &BluetoothAvrcpResultHandler::OnError, aStatus);
-  }
-  nsresult rv = NS_DispatchToMainThread(runnable);
-  if (NS_FAILED(rv)) {
-    BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
-  }
-  return rv;
-}
-
-// Notification handling
-//
-
-BluetoothAvrcpNotificationHandler::~BluetoothAvrcpNotificationHandler()
-{ }
-
-static BluetoothAvrcpNotificationHandler* sAvrcpNotificationHandler;
-
-struct BluetoothAvrcpCallback
-{
-  class AvrcpNotificationHandlerWrapper
-  {
-  public:
-    typedef BluetoothAvrcpNotificationHandler ObjectType;
-
-    static ObjectType* GetInstance()
-    {
-      MOZ_ASSERT(NS_IsMainThread());
-
-      return sAvrcpNotificationHandler;
-    }
-  };
-
-  // Notifications
-
-  typedef BluetoothNotificationRunnable0<AvrcpNotificationHandlerWrapper,
-                                         void>
-    GetPlayStatusNotification;
-
-  typedef BluetoothNotificationRunnable0<AvrcpNotificationHandlerWrapper,
-                                         void>
-    ListPlayerAppAttrNotification;
-
-  typedef BluetoothNotificationRunnable1<AvrcpNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothAvrcpPlayerAttribute>
-    ListPlayerAppValuesNotification;
-
-  typedef BluetoothNotificationRunnable2<AvrcpNotificationHandlerWrapper, void,
-    uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
-    uint8_t, const BluetoothAvrcpPlayerAttribute*>
-    GetPlayerAppValueNotification;
-
-  typedef BluetoothNotificationRunnable2<AvrcpNotificationHandlerWrapper, void,
-    uint8_t, nsAutoArrayPtr<BluetoothAvrcpPlayerAttribute>,
-    uint8_t, const BluetoothAvrcpPlayerAttribute*>
-    GetPlayerAppAttrsTextNotification;
-
-  typedef BluetoothNotificationRunnable3<AvrcpNotificationHandlerWrapper,
-                                         void,
-                                         uint8_t, uint8_t,
-                                         nsAutoArrayPtr<uint8_t>,
-                                         uint8_t, uint8_t, const uint8_t*>
-    GetPlayerAppValuesTextNotification;
-
-  typedef BluetoothNotificationRunnable1<AvrcpNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothAvrcpPlayerSettings,
-                                         const BluetoothAvrcpPlayerSettings&>
-    SetPlayerAppValueNotification;
-
-  typedef BluetoothNotificationRunnable2<AvrcpNotificationHandlerWrapper, void,
-    uint8_t, nsAutoArrayPtr<BluetoothAvrcpMediaAttribute>,
-    uint8_t, const BluetoothAvrcpMediaAttribute*>
-    GetElementAttrNotification;
-
-  typedef BluetoothNotificationRunnable2<AvrcpNotificationHandlerWrapper,
-                                         void,
-                                         BluetoothAvrcpEvent, uint32_t>
-    RegisterNotificationNotification;
-
-  typedef BluetoothNotificationRunnable2<AvrcpNotificationHandlerWrapper,
-                                         void,
-                                         nsString, unsigned long,
-                                         const nsAString&>
-    RemoteFeatureNotification;
-
-  typedef BluetoothNotificationRunnable2<AvrcpNotificationHandlerWrapper,
-                                         void,
-                                         uint8_t, uint8_t>
-    VolumeChangeNotification;
-
-  typedef BluetoothNotificationRunnable2<AvrcpNotificationHandlerWrapper,
-                                         void,
-                                         int, int>
-    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<btrc_player_attr_t>(aAttrs, aNumAttrs));
-  }
-
-  static void
-  GetPlayerAppAttrsText(uint8_t aNumAttrs, btrc_player_attr_t* aAttrs)
-  {
-    GetPlayerAppAttrsTextNotification::Dispatch(
-      &BluetoothAvrcpNotificationHandler::GetPlayerAppAttrsTextNotification,
-      aNumAttrs, ConvertArray<btrc_player_attr_t>(aAttrs, aNumAttrs));
-  }
-
-  static void
-  GetPlayerAppValuesText(uint8_t aAttrId, uint8_t aNumVals, uint8_t* aVals)
-  {
-    GetPlayerAppValuesTextNotification::Dispatch(
-      &BluetoothAvrcpNotificationHandler::GetPlayerAppValuesTextNotification,
-      aAttrId, aNumVals, ConvertArray<uint8_t>(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<btrc_media_attr_t>(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
-//
-
-BluetoothAvrcpInterface::BluetoothAvrcpInterface(
-#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
-}
-
-BluetoothAvrcpInterface::~BluetoothAvrcpInterface()
-{ }
-
-void
-BluetoothAvrcpInterface::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) {
-    DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Init,
-                                 ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
-{
-  bt_status_t status;
-
-#if ANDROID_VERSION >= 18
-  mInterface->cleanup();
-
-  status = BT_STATUS_SUCCESS;
-#else
-  status = BT_STATUS_UNSUPPORTED;
-#endif
-
-  if (aRes) {
-    DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Cleanup,
-                                 ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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);
+    runnable = new BluetoothHALResultRunnable(aRes, aMethod);
   } else {
-    status = BT_STATUS_PARM_INVALID;
-  }
-#else
-  status = BT_STATUS_UNSUPPORTED;
-#endif
-
-  if (aRes) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::ListPlayerAppAttrRsp(
-  int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
-  BluetoothAvrcpResultHandler* aRes)
-{
-  bt_status_t status;
-
-#if ANDROID_VERSION >= 18
-  ConvertArray<BluetoothAvrcpPlayerAttribute> pAttrsArray(aPAttrs, aNumAttr);
-  nsAutoArrayPtr<btrc_player_attr_t> 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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::GetElementAttrRsp(
-  uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttrs,
-  BluetoothAvrcpResultHandler* aRes)
-{
-  bt_status_t status;
-
-#if ANDROID_VERSION >= 18
-  ConvertArray<BluetoothAvrcpElementAttribute> pAttrsArray(aAttrs, aNumAttr);
-  nsAutoArrayPtr<btrc_element_attr_val_t> 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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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, &param);
-  } else {
-    status = BT_STATUS_PARM_INVALID;
-  }
-#else
-  status = BT_STATUS_UNSUPPORTED;
-#endif
-
-  if (aRes) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-void
-BluetoothAvrcpInterface::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) {
-    DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::SetVolume,
-      ConvertDefault(status, STATUS_FAIL));
-  }
-}
-
-//
-// Bluetooth Core Interface
-//
-
-typedef
-  BluetoothInterfaceRunnable0<BluetoothResultHandler, void>
-  BluetoothResultRunnable;
-
-typedef
-  BluetoothInterfaceRunnable1<BluetoothResultHandler, void,
-                              BluetoothStatus, BluetoothStatus>
-  BluetoothErrorRunnable;
-
-static nsresult
-DispatchBluetoothResult(BluetoothResultHandler* aRes,
-                        void (BluetoothResultHandler::*aMethod)(),
-                        BluetoothStatus aStatus)
-{
-  MOZ_ASSERT(aRes);
-
-  nsRunnable* runnable;
-
-  if (aStatus == STATUS_SUCCESS) {
-    runnable = new BluetoothResultRunnable(aRes, aMethod);
-  } else {
-    runnable = new
-      BluetoothErrorRunnable(aRes, &BluetoothResultHandler::OnError, aStatus);
+    runnable = new BluetoothHALErrorRunnable(
+      aRes, &BluetoothResultHandler::OnError, aStatus);
   }
   nsresult rv = NS_DispatchToMainThread(runnable);
   if (NS_FAILED(rv)) {
     BT_LOGR("NS_DispatchToMainThread failed: %X", rv);
   }
   return rv;
 }
 
 // Notification handling
 //
 
-BluetoothNotificationHandler::~BluetoothNotificationHandler()
-{ }
-
 static BluetoothNotificationHandler* sNotificationHandler;
 
 struct BluetoothCallback
 {
   class NotificationHandlerWrapper
   {
   public:
     typedef BluetoothNotificationHandler  ObjectType;
@@ -3623,73 +111,73 @@ struct BluetoothCallback
       MOZ_ASSERT(NS_IsMainThread());
 
       return sNotificationHandler;
     }
   };
 
   // Notifications
 
-  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
-                                         bool>
+  typedef BluetoothNotificationHALRunnable1<NotificationHandlerWrapper, void,
+                                            bool>
     AdapterStateChangedNotification;
 
-  typedef BluetoothNotificationRunnable3<NotificationHandlerWrapper, void,
-                                         BluetoothStatus, int,
-                                         nsAutoArrayPtr<BluetoothProperty>,
-                                         BluetoothStatus, int,
-                                         const BluetoothProperty*>
+  typedef BluetoothNotificationHALRunnable3<NotificationHandlerWrapper, void,
+                                            BluetoothStatus, int,
+                                            nsAutoArrayPtr<BluetoothProperty>,
+                                            BluetoothStatus, int,
+                                            const BluetoothProperty*>
     AdapterPropertiesNotification;
 
-  typedef BluetoothNotificationRunnable4<NotificationHandlerWrapper, void,
-                                         BluetoothStatus, nsString, int,
-                                         nsAutoArrayPtr<BluetoothProperty>,
-                                         BluetoothStatus, const nsAString&,
-                                         int, const BluetoothProperty*>
+  typedef BluetoothNotificationHALRunnable4<NotificationHandlerWrapper, void,
+                                            BluetoothStatus, nsString, int,
+                                            nsAutoArrayPtr<BluetoothProperty>,
+                                            BluetoothStatus, const nsAString&,
+                                            int, const BluetoothProperty*>
     RemoteDevicePropertiesNotification;
 
-  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
-                                         int,
-                                         nsAutoArrayPtr<BluetoothProperty>,
-                                         int, const BluetoothProperty*>
+  typedef BluetoothNotificationHALRunnable2<NotificationHandlerWrapper, void,
+                                            int,
+                                            nsAutoArrayPtr<BluetoothProperty>,
+                                            int, const BluetoothProperty*>
     DeviceFoundNotification;
 
-  typedef BluetoothNotificationRunnable1<NotificationHandlerWrapper, void,
+  typedef BluetoothNotificationHALRunnable1<NotificationHandlerWrapper, void,
                                          bool>
     DiscoveryStateChangedNotification;
 
-  typedef BluetoothNotificationRunnable3<NotificationHandlerWrapper, void,
-                                         nsString, nsString, uint32_t,
-                                         const nsAString&, const nsAString&>
+  typedef BluetoothNotificationHALRunnable3<NotificationHandlerWrapper, void,
+                                            nsString, nsString, uint32_t,
+                                            const nsAString&, const nsAString&>
     PinRequestNotification;
 
-  typedef BluetoothNotificationRunnable5<NotificationHandlerWrapper, void,
-                                         nsString, nsString, uint32_t,
-                                         BluetoothSspVariant, uint32_t,
-                                         const nsAString&, const nsAString&>
+  typedef BluetoothNotificationHALRunnable5<NotificationHandlerWrapper, void,
+                                            nsString, nsString, uint32_t,
+                                            BluetoothSspVariant, uint32_t,
+                                            const nsAString&, const nsAString&>
     SspRequestNotification;
 
-  typedef BluetoothNotificationRunnable3<NotificationHandlerWrapper, void,
-                                         BluetoothStatus, nsString,
-                                         BluetoothBondState,
-                                         BluetoothStatus, const nsAString&>
+  typedef BluetoothNotificationHALRunnable3<NotificationHandlerWrapper, void,
+                                            BluetoothStatus, nsString,
+                                            BluetoothBondState,
+                                            BluetoothStatus, const nsAString&>
     BondStateChangedNotification;
 
-  typedef BluetoothNotificationRunnable3<NotificationHandlerWrapper, void,
-                                         BluetoothStatus, nsString, bool,
-                                         BluetoothStatus, const nsAString&>
+  typedef BluetoothNotificationHALRunnable3<NotificationHandlerWrapper, void,
+                                            BluetoothStatus, nsString, bool,
+                                            BluetoothStatus, const nsAString&>
     AclStateChangedNotification;
 
-  typedef BluetoothNotificationRunnable3<NotificationHandlerWrapper, void,
-                                         uint16_t, nsAutoArrayPtr<uint8_t>,
-                                         uint8_t, uint16_t, const uint8_t*>
+  typedef BluetoothNotificationHALRunnable3<NotificationHandlerWrapper, void,
+                                            uint16_t, nsAutoArrayPtr<uint8_t>,
+                                            uint8_t, uint16_t, const uint8_t*>
     DutModeRecvNotification;
 
-  typedef BluetoothNotificationRunnable2<NotificationHandlerWrapper, void,
-                                         BluetoothStatus, uint16_t>
+  typedef BluetoothNotificationHALRunnable2<NotificationHandlerWrapper, void,
+                                            BluetoothStatus, uint16_t>
     LeTestModeNotification;
 
   // Bluedroid callbacks
 
   static const bt_property_t*
   AlignedProperties(bt_property_t* aProperties, size_t aNumProperties,
                     nsAutoArrayPtr<bt_property_t>& aPropertiesArray)
   {
@@ -3832,20 +320,20 @@ struct BluetoothCallback
 //
 
 /* 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) ) )
 
-BluetoothInterface*
-BluetoothInterface::GetInstance()
+BluetoothHALInterface*
+BluetoothHALInterface::GetInstance()
 {
-  static BluetoothInterface* sBluetoothInterface;
+  static BluetoothHALInterface* sBluetoothInterface;
 
   if (sBluetoothInterface) {
     return sBluetoothInterface;
   }
 
   /* get driver module */
 
   const hw_module_t* module;
@@ -3875,41 +363,43 @@ BluetoothInterface::GetInstance()
     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 BluetoothInterface(bt_interface);
+  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;
 }
 
-BluetoothInterface::BluetoothInterface(const bt_interface_t* aInterface)
+BluetoothHALInterface::BluetoothHALInterface(
+  const bt_interface_t* aInterface)
 : mInterface(aInterface)
 {
   MOZ_ASSERT(mInterface);
 }
 
-BluetoothInterface::~BluetoothInterface()
+BluetoothHALInterface::~BluetoothHALInterface()
 { }
 
 void
-BluetoothInterface::Init(BluetoothNotificationHandler* aNotificationHandler,
-                         BluetoothResultHandler* aRes)
+BluetoothHALInterface::Init(
+  BluetoothNotificationHandler* aNotificationHandler,
+  BluetoothResultHandler* aRes)
 {
   static bt_callbacks_t sBluetoothCallbacks = {
     sizeof(sBluetoothCallbacks),
     BluetoothCallback::AdapterStateChanged,
     BluetoothCallback::AdapterProperties,
     BluetoothCallback::RemoteDeviceProperties,
     BluetoothCallback::DeviceFound,
     BluetoothCallback::DiscoveryStateChanged,
@@ -3925,434 +415,434 @@ BluetoothInterface::Init(BluetoothNotifi
 #endif
   };
 
   sNotificationHandler = aNotificationHandler;
 
   int status = mInterface->init(&sBluetoothCallbacks);
 
   if (aRes) {
-    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Init,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Init,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::Cleanup(BluetoothResultHandler* aRes)
+BluetoothHALInterface::Cleanup(BluetoothResultHandler* aRes)
 {
   mInterface->cleanup();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Cleanup,
-                            STATUS_SUCCESS);
+    DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Cleanup,
+                               STATUS_SUCCESS);
   }
 
   sNotificationHandler = nullptr;
 }
 
 void
-BluetoothInterface::Enable(BluetoothResultHandler* aRes)
+BluetoothHALInterface::Enable(BluetoothResultHandler* aRes)
 {
   int status = mInterface->enable();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Enable,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Enable,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::Disable(BluetoothResultHandler* aRes)
+BluetoothHALInterface::Disable(BluetoothResultHandler* aRes)
 {
   int status = mInterface->disable();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Disable,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes, &BluetoothResultHandler::Disable,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Adapter Properties */
 
 void
-BluetoothInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
+BluetoothHALInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
 {
   int status = mInterface->get_adapter_properties();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::GetAdapterProperties,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::GetAdapterProperties,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::GetAdapterProperty(const nsAString& aName,
-                                       BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::GetAdapterProperties,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::GetAdapterProperties,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::SetAdapterProperty(const BluetoothNamedValue& aProperty,
-                                       BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::SetAdapterProperty,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::SetAdapterProperty,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Remote Device Properties */
 
 void
-BluetoothInterface::GetRemoteDeviceProperties(const nsAString& aRemoteAddr,
-                                              BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::GetRemoteDeviceProperties,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::GetRemoteDeviceProperties,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::GetRemoteDeviceProperty(const nsAString& aRemoteAddr,
-                                            const nsAString& aName,
-                                            BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::GetRemoteDeviceProperty,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::GetRemoteDeviceProperty,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::SetRemoteDeviceProperty(const nsAString& aRemoteAddr,
-                                            const BluetoothNamedValue& aProperty,
-                                            BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::SetRemoteDeviceProperty,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::SetRemoteDeviceProperty,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Remote Services */
 
 void
-BluetoothInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr,
-                                           const uint8_t aUuid[16],
-                                           BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::GetRemoteServiceRecord,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::GetRemoteServiceRecord,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::GetRemoteServices(const nsAString& aRemoteAddr,
-                                      BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::GetRemoteServices,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::GetRemoteServices,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Discovery */
 
 void
-BluetoothInterface::StartDiscovery(BluetoothResultHandler* aRes)
+BluetoothHALInterface::StartDiscovery(BluetoothResultHandler* aRes)
 {
   int status = mInterface->start_discovery();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::StartDiscovery,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::StartDiscovery,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::CancelDiscovery(BluetoothResultHandler* aRes)
+BluetoothHALInterface::CancelDiscovery(BluetoothResultHandler* aRes)
 {
   int status = mInterface->cancel_discovery();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::CancelDiscovery,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::CancelDiscovery,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Bonds */
 
 void
-BluetoothInterface::CreateBond(const nsAString& aBdAddr,
-                               BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::CreateBond,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::CreateBond,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::RemoveBond(const nsAString& aBdAddr,
-                               BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::RemoveBond,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::RemoveBond,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::CancelBond(const nsAString& aBdAddr,
-                               BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::CancelBond,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::CancelBond,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Authentication */
 
 void
-BluetoothInterface::PinReply(const nsAString& aBdAddr, bool aAccept,
-                             const nsAString& aPinCode,
-                             BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::PinReply,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::PinReply,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::SspReply(const nsAString& aBdAddr,
-                             const nsAString& aVariant,
-                             bool aAccept, uint32_t aPasskey,
-                             BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::SspReply,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::SspReply,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* DUT Mode */
 
 void
-BluetoothInterface::DutModeConfigure(bool aEnable,
-                                     BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::DutModeConfigure,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::DutModeConfigure,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
-                                BluetoothResultHandler* aRes)
+BluetoothHALInterface::DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
+                                   BluetoothResultHandler* aRes)
 {
   int status = mInterface->dut_mode_send(aOpcode, aBuf, aLen);
 
   if (aRes) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::DutModeSend,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::DutModeSend,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* LE Mode */
 
 void
-BluetoothInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
-                               BluetoothResultHandler* aRes)
+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) {
-    DispatchBluetoothResult(aRes,
-                            &BluetoothResultHandler::LeTestMode,
-                            ConvertDefault(status, STATUS_FAIL));
+    DispatchBluetoothHALResult(aRes,
+                               &BluetoothResultHandler::LeTestMode,
+                               ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Profile Interfaces */
 
 template <class T>
 T*
-BluetoothInterface::CreateProfileInterface()
+BluetoothHALInterface::CreateProfileInterface()
 {
   typename interface_traits<T>::const_interface_type* interface =
     reinterpret_cast<typename interface_traits<T>::const_interface_type*>(
       mInterface->get_profile_interface(interface_traits<T>::profile_id()));
 
   if (!interface) {
     BT_WARNING("Bluetooth profile '%s' is not supported",
                interface_traits<T>::profile_id());
@@ -4369,57 +859,57 @@ BluetoothInterface::CreateProfileInterfa
 
 #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 <>
-BluetoothAvrcpInterface*
-BluetoothInterface::CreateProfileInterface<BluetoothAvrcpInterface>()
+BluetoothAvrcpHALInterface*
+BluetoothHALInterface::CreateProfileInterface<BluetoothAvrcpHALInterface>()
 {
   BT_WARNING("Bluetooth profile 'avrcp' is not supported");
 
-  return new BluetoothAvrcpInterface();
+  return new BluetoothAvrcpHALInterface();
 }
 #endif
 
 template <class T>
 T*
-BluetoothInterface::GetProfileInterface()
+BluetoothHALInterface::GetProfileInterface()
 {
   static T* sBluetoothProfileInterface;
 
   if (sBluetoothProfileInterface) {
     return sBluetoothProfileInterface;
   }
 
   sBluetoothProfileInterface = CreateProfileInterface<T>();
 
   return sBluetoothProfileInterface;
 }
 
 BluetoothSocketInterface*
-BluetoothInterface::GetBluetoothSocketInterface()
+BluetoothHALInterface::GetBluetoothSocketInterface()
 {
-  return GetProfileInterface<BluetoothSocketInterface>();
+  return GetProfileInterface<BluetoothSocketHALInterface>();
 }
 
 BluetoothHandsfreeInterface*
-BluetoothInterface::GetBluetoothHandsfreeInterface()
+BluetoothHALInterface::GetBluetoothHandsfreeInterface()
 {
-  return GetProfileInterface<BluetoothHandsfreeInterface>();
+  return GetProfileInterface<BluetoothHandsfreeHALInterface>();
 }
 
 BluetoothA2dpInterface*
-BluetoothInterface::GetBluetoothA2dpInterface()
+BluetoothHALInterface::GetBluetoothA2dpInterface()
 {
-  return GetProfileInterface<BluetoothA2dpInterface>();
+  return GetProfileInterface<BluetoothA2dpHALInterface>();
 }
 
 BluetoothAvrcpInterface*
-BluetoothInterface::GetBluetoothAvrcpInterface()
+BluetoothHALInterface::GetBluetoothAvrcpInterface()
 {
-  return GetProfileInterface<BluetoothAvrcpInterface>();
+  return GetProfileInterface<BluetoothAvrcpHALInterface>();
 }
 
 END_BLUETOOTH_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/bluetooth2/bluedroid/BluetoothHALInterface.h
@@ -0,0 +1,110 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */