Merge mozilla-central and b2g-inbound
authorEd Morley <emorley@mozilla.com>
Wed, 06 Aug 2014 13:55:47 +0100
changeset 198226 370abdb1871e2b08afba3b18f4c24af111246e85
parent 198105 bdf301b20cabe5b401b6aeef661b80067c3c5ef1 (current diff)
parent 198225 e78d7dd435a2c966a9df29428362b08fffb6cd39 (diff)
child 198227 67c1ef0c1f95c85eaa2f400487717e042e365ad1
push id47332
push userkwierso@gmail.com
push dateThu, 07 Aug 2014 01:18:56 +0000
treeherdermozilla-inbound@118d2e5256e5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central and b2g-inbound
configure.in
content/media/fmp4/moz.build
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -304,17 +304,20 @@ pref("notification.feature.enabled", tru
 
 // IndexedDB
 pref("dom.indexedDB.warningQuota", 5);
 
 // prevent video elements from preloading too much data
 pref("media.preload.default", 1); // default to preload none
 pref("media.preload.auto", 2);    // preload metadata if preload=auto
 pref("media.cache_size", 4096);    // 4MB media cache
-
+#ifdef MOZ_FMP4
+// Enable/Disable Gonk Decoder Module
+pref("media.fragmented-mp4.gonk.enabled", false);
+#endif
 // The default number of decoded video frames that are enqueued in
 // MediaDecoderReader's mVideoQueue.
 pref("media.video-queue.default-size", 3);
 
 // optimize images' memory usage
 pref("image.mem.decodeondraw", true);
 pref("image.mem.allow_locking_in_content_processes", false); /* don't allow image locking */
 pref("image.mem.min_discard_timeout_ms", 86400000); /* 24h, we rely on the out of memory hook */
--- 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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <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="227354333a185180b85471f2cc6abfb029e44718"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <!-- 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="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <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"/>
@@ -128,12 +128,12 @@
   <!-- Emulator specific things -->
   <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="platform_external_qemu" path="external/qemu" remote="b2g" revision="683623c76338dccd65e698bfb5c4cfee8808d799"/>
   <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="b6f025acd8ead1c3531e1ad62e70849161ed9340"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="02104803f873a4d5cf9fb611a211b83450e9dfba"/>
   <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
@@ -10,17 +10,17 @@
   <!--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="999e945b85c578c503ad445c2285940f16aacdae">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <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="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
--- 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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <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="227354333a185180b85471f2cc6abfb029e44718"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- 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="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <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"/>
@@ -117,17 +117,17 @@
   <project name="platform/system/security" path="system/security" revision="360f51f7af191316cd739f229db1c5f7233be063"/>
   <project name="platform/system/vold" path="system/vold" revision="153df4d067a4149c7d78f1c92fed2ce2bd6a272e"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="jb_3.2" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="878804e0becfe5635bb8ccbf2671333d546c6fb6"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="d7e5ed0a081a39419932b8b9fdefc9b2d903850d"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="7edb4681617cd572a590d7f4c94d548d52679821"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="ebb14165369f5edc3f335d5bde6eef8439073589"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="2b1d8b5b7a760230f4c94c02e733e3929f44253a"/>
   <project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="e81502511cda303c803e63f049574634bc96f9f2"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="81c4a859d75d413ad688067829d21b7ba9205f81"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="f0689ac1914cdbc59e53bdc9edd9013dc157c299"/>
   <project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="dd925f76e4f149c3d5571b80e12f7e24bbe89c59"/>
   <project name="platform/external/dbus" path="external/dbus" revision="ea87119c843116340f5df1d94eaf8275e1055ae8"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
@@ -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="5dc48bd46f9589653f8bf297be5d73676f2e2867"/>
   <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="b33c9a7b8eefbeaf480f0b8f9af2c6a8a35b0aee"/>
-  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="b6f025acd8ead1c3531e1ad62e70849161ed9340"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="02104803f873a4d5cf9fb611a211b83450e9dfba"/>
   <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": "1b07481115b939288cd034a592faef63395fdae9", 
+    "revision": "d3338ca9a7f9ac85c699b012a6fa1f75607355ae", 
     "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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <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="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <!-- 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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <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="3aa6abd313f965a84aa86c6b213dc154e4875139">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <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="b6f025acd8ead1c3531e1ad62e70849161ed9340"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="02104803f873a4d5cf9fb611a211b83450e9dfba"/>
   <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="0d616942c300d9fb142483210f1dda9096c9a9fc">
     <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="5e6ef81cb9e917657ce050f598229dfc83c58b8f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="09365cfc38e1381c81a0a86b4ef22bcd16babe98"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cff8f990433810780088c545641c3110d956949f"/>
   <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="71f5a35e3bc1801847413cff1f14fc3b5cd991ca"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/configure.in
+++ b/configure.in
@@ -256,31 +256,32 @@ if test -n "$gonkdir" ; then
         MOZ_RTSP=1
         MOZ_NFC=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_OMX_ENCODER=1
         AC_SUBST(MOZ_OMX_ENCODER)
         AC_DEFINE(MOZ_OMX_ENCODER)
+	MOZ_FMP4=1
         ;;
     19)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
         MOZ_B2G_CAMERA=1
         MOZ_B2G_BT=1
         MOZ_B2G_BT_BLUEDROID=1
         MOZ_NFC=1
         MOZ_RTSP=1
         MOZ_OMX_DECODER=1
         MOZ_OMX_ENCODER=1
         AC_DEFINE(MOZ_OMX_ENCODER)
         MOZ_AUDIO_OFFLOAD=1
         AC_SUBST(MOZ_AUDIO_OFFLOAD)
         AC_DEFINE(MOZ_AUDIO_OFFLOAD)
-
+	MOZ_FMP4=1
         ;;
     *)
         AC_MSG_ERROR([Unsupported platform version: $ANDROID_VERSION])
         ;;
     esac
     CPPFLAGS="-DANDROID -isystem $gonkdir/bionic/libc/$ARCH_DIR/include -isystem $gonkdir/bionic/libc/include/ -isystem $gonkdir/bionic/libc/kernel/common -isystem $gonkdir/bionic/libc/kernel/$ARCH_DIR -isystem $gonkdir/bionic/libm/include -I$gonkdir/system -I$gonkdir/system/core/include -isystem $gonkdir/bionic -I$gonkdir/hardware/libhardware/include -I$gonkdir/external/valgrind/fxos-include $GONK_INCLUDES $CPPFLAGS"
     CFLAGS="-mandroid -fno-short-enums -fno-exceptions $CFLAGS"
     CXXFLAGS="-mandroid -fno-short-enums -fno-exceptions -Wno-psabi $CXXFLAGS $STLPORT_CPPFLAGS"
@@ -3770,17 +3771,21 @@ MOZ_TREMOR=
 MOZ_WAVE=1
 MOZ_SAMPLE_TYPE_FLOAT32=
 MOZ_SAMPLE_TYPE_S16=
 MOZ_OPUS=1
 MOZ_WEBM=1
 MOZ_GSTREAMER=
 MOZ_DIRECTSHOW=
 MOZ_WMF=
-MOZ_FMP4=
+if test -n "$MOZ_FMP4"; then
+  MOZ_FMP4=1
+else
+  MOZ_FMP4 =
+fi
 MOZ_EME=1
 MOZ_FFMPEG=
 MOZ_WEBRTC=1
 MOZ_PEERCONNECTION=
 MOZ_SRTP=
 MOZ_WEBRTC_SIGNALING=
 MOZ_WEBRTC_ASSERT_ALWAYS=1
 MOZ_SCTP=
--- a/content/media/fmp4/MP4Decoder.cpp
+++ b/content/media/fmp4/MP4Decoder.cpp
@@ -127,25 +127,32 @@ IsAppleAvailable()
     return false;
   }
   // All hurdles cleared!
   return true;
 #endif
 }
 
 static bool
+IsGonkMP4DecoderAvailable()
+{
+  return Preferences::GetBool("media.fragmented-mp4.gonk.enabled", false);
+}
+
+static bool
 HavePlatformMPEGDecoders()
 {
   return Preferences::GetBool("media.fragmented-mp4.use-blank-decoder") ||
 #ifdef XP_WIN
          // We have H.264/AAC platform decoders on Windows Vista and up.
          IsVistaOrLater() ||
 #endif
          IsFFmpegAvailable() ||
          IsAppleAvailable() ||
+	 IsGonkMP4DecoderAvailable() ||
          // TODO: Other platforms...
          false;
 }
 
 /* static */
 bool
 MP4Decoder::IsEnabled()
 {
--- a/content/media/fmp4/MP4Reader.cpp
+++ b/content/media/fmp4/MP4Reader.cpp
@@ -225,18 +225,24 @@ public:
     return NS_OK;
   }
 private:
   nsRefPtr<AbstractMediaDecoder> mDecoder;
   nsTArray<uint8_t> mInitData;
   nsString mInitDataType;
 };
 
-bool MP4Reader::IsWaitingMediaResources()
-{
+bool MP4Reader::IsWaitingOnCodecResource() {
+#ifdef MOZ_GONK_MEDIACODEC
+  return mVideo.mDecoder && mVideo.mDecoder->IsWaitingMediaResources();
+#endif
+  return false;
+}
+
+bool MP4Reader::IsWaitingOnCDMResource() {
   nsRefPtr<CDMProxy> proxy;
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     if (!mIsEncrypted) {
       // Not encrypted, no need to wait for CDMProxy.
       return false;
     }
     proxy = mDecoder->GetCDMProxy();
@@ -248,16 +254,25 @@ bool MP4Reader::IsWaitingMediaResources(
   // We'll keep waiting if the CDM hasn't informed Gecko of its capabilities.
   {
     CDMCaps::AutoLock caps(proxy->Capabilites());
     LOG("MP4Reader::IsWaitingMediaResources() capsKnown=%d", caps.AreCapsKnown());
     return !caps.AreCapsKnown();
   }
 }
 
+bool MP4Reader::IsWaitingMediaResources()
+{
+  // IsWaitingOnCDMResource() *must* come first, because we don't know whether
+  // we can create a decoder until the CDM is initialized and it has told us
+  // whether *it* will decode, or whether we need to create a PDM to do the
+  // decoding
+  return IsWaitingOnCDMResource() || IsWaitingOnCodecResource();
+}
+
 void
 MP4Reader::ExtractCryptoInitData(nsTArray<uint8_t>& aInitData)
 {
   MOZ_ASSERT(mDemuxer->Crypto().valid);
   const nsTArray<mp4_demuxer::PsshInfo>& psshs = mDemuxer->Crypto().pssh;
   for (uint32_t i = 0; i < psshs.Length(); i++) {
     aInitData.AppendElements(psshs[i].data);
   }
@@ -289,17 +304,22 @@ MP4Reader::ReadMetadata(MediaInfo* aInfo
       ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
       mIsEncrypted = mDemuxer->Crypto().valid;
     }
 
     // Remember that we've initialized the demuxer, so that if we're decoding
     // an encrypted stream and we need to wait for a CDM to be set, we don't
     // need to reinit the demuxer.
     mDemuxerInitialized = true;
+  } else if (mPlatform && !IsWaitingMediaResources()) {
+    *aInfo = mInfo;
+    *aTags = nullptr;
+    return NS_OK;
   }
+
   if (mDemuxer->Crypto().valid) {
     if (!sIsEMEEnabled) {
       // TODO: Need to signal DRM/EME required somehow...
       return NS_ERROR_FAILURE;
     }
 
     // We have encrypted audio or video. We'll need a CDM to decrypt and
     // possibly decode this. Wait until we've received a CDM from the
@@ -730,9 +750,41 @@ MP4Reader::GetBuffered(dom::TimeRanges* 
   for (size_t i = 0; i < mTimeRanges.Length(); i++) {
     aBuffered->Add((mTimeRanges[i].start - aStartTime) / 1000000.0,
                    (mTimeRanges[i].end - aStartTime) / 1000000.0);
   }
 
   return NS_OK;
 }
 
+bool MP4Reader::IsDormantNeeded()
+{
+#ifdef MOZ_GONK_MEDIACODEC
+  return mVideo.mDecoder && mVideo.mDecoder->IsDormantNeeded();
+#endif
+  return false;
+}
+
+void MP4Reader::ReleaseMediaResources()
+{
+#ifdef MOZ_GONK_MEDIACODEC
+  // Before freeing a video codec, all video buffers needed to be released
+  // even from graphics pipeline.
+  VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
+  if (container) {
+    container->ClearCurrentFrame();
+  }
+  if (mVideo.mDecoder) {
+    mVideo.mDecoder->ReleaseMediaResources();
+  }
+#endif
+}
+
+void MP4Reader::NotifyResourcesStatusChanged()
+{
+#ifdef MOZ_GONK_MEDIACODEC
+  if (mDecoder) {
+    mDecoder->NotifyWaitingForResourcesStatusChanged();
+  }
+#endif
+}
+
 } // namespace mozilla
--- a/content/media/fmp4/MP4Reader.h
+++ b/content/media/fmp4/MP4Reader.h
@@ -54,17 +54,20 @@ public:
   virtual bool IsMediaSeekable() MOZ_OVERRIDE;
 
   virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength,
                                  int64_t aOffset) MOZ_OVERRIDE;
 
   virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
                                int64_t aStartTime) MOZ_OVERRIDE;
 
+  // For Media Resource Management
   virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
+  virtual bool IsDormantNeeded() MOZ_OVERRIDE;
+  virtual void ReleaseMediaResources() MOZ_OVERRIDE;
 
   virtual nsresult ResetDecode() MOZ_OVERRIDE;
 
   virtual void Shutdown() MOZ_OVERRIDE;
 
 private:
 
   void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
@@ -79,16 +82,19 @@ private:
   bool SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed);
 
   void Output(mp4_demuxer::TrackType aType, MediaData* aSample);
   void InputExhausted(mp4_demuxer::TrackType aTrack);
   void Error(mp4_demuxer::TrackType aTrack);
   bool Decode(mp4_demuxer::TrackType aTrack);
   void Flush(mp4_demuxer::TrackType aTrack);
   void DrainComplete(mp4_demuxer::TrackType aTrack);
+  void NotifyResourcesStatusChanged();
+  bool IsWaitingOnCodecResource();
+  bool IsWaitingOnCDMResource();
 
   nsAutoPtr<mp4_demuxer::MP4Demuxer> mDemuxer;
   nsAutoPtr<PlatformDecoderModule> mPlatform;
 
   class DecoderCallback : public MediaDataDecoderCallback {
   public:
     DecoderCallback(MP4Reader* aReader,
                     mp4_demuxer::TrackType aType)
@@ -103,16 +109,22 @@ private:
       mReader->InputExhausted(mType);
     }
     virtual void Error() MOZ_OVERRIDE {
       mReader->Error(mType);
     }
     virtual void DrainComplete() MOZ_OVERRIDE {
       mReader->DrainComplete(mType);
     }
+    virtual void NotifyResourcesStatusChanged() MOZ_OVERRIDE {
+      mReader->NotifyResourcesStatusChanged();
+    }
+    virtual void ReleaseMediaResources() MOZ_OVERRIDE {
+      mReader->ReleaseMediaResources();
+    }
   private:
     MP4Reader* mReader;
     mp4_demuxer::TrackType mType;
   };
 
   struct DecoderData {
     DecoderData(const char* aMonitorName,
                 uint32_t aDecodeAhead)
--- a/content/media/fmp4/PlatformDecoderModule.cpp
+++ b/content/media/fmp4/PlatformDecoderModule.cpp
@@ -9,44 +9,53 @@
 #include "WMFDecoderModule.h"
 #endif
 #ifdef MOZ_FFMPEG
 #include "FFmpegRuntimeLinker.h"
 #endif
 #ifdef MOZ_APPLEMEDIA
 #include "AppleDecoderModule.h"
 #endif
+#ifdef MOZ_GONK_MEDIACODEC
+#include "GonkDecoderModule.h"
+#endif
+
 #include "mozilla/Preferences.h"
 #include "EMEDecoderModule.h"
 #include "mozilla/CDMProxy.h"
 #include "SharedThreadPool.h"
 #include "MediaTaskQueue.h"
 
 namespace mozilla {
 
 extern PlatformDecoderModule* CreateBlankDecoderModule();
 
 bool PlatformDecoderModule::sUseBlankDecoder = false;
 bool PlatformDecoderModule::sFFmpegDecoderEnabled = false;
+bool PlatformDecoderModule::sGonkDecoderEnabled = false;
 
 /* static */
 void
 PlatformDecoderModule::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
   static bool alreadyInitialized = false;
   if (alreadyInitialized) {
     return;
   }
   alreadyInitialized = true;
 
   Preferences::AddBoolVarCache(&sUseBlankDecoder,
                                "media.fragmented-mp4.use-blank-decoder");
   Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
                                "media.fragmented-mp4.ffmpeg.enabled", false);
+#ifdef MOZ_GONK_MEDIACODEC
+  Preferences::AddBoolVarCache(&sGonkDecoderEnabled,
+                               "media.fragmented-mp4.gonk.enabled", false);
+#endif
 #ifdef XP_WIN
   WMFDecoderModule::Init();
 #endif
 #ifdef MOZ_APPLEMEDIA
   AppleDecoderModule::Init();
 #endif
 }
 
@@ -124,12 +133,17 @@ PlatformDecoderModule::Create()
   }
 #endif
 #ifdef MOZ_APPLEMEDIA
   nsAutoPtr<AppleDecoderModule> m(new AppleDecoderModule());
   if (NS_SUCCEEDED(m->Startup())) {
     return m.forget();
   }
 #endif
+#ifdef MOZ_GONK_MEDIACODEC
+  if (sGonkDecoderEnabled) {
+    return new GonkDecoderModule();
+  }
+#endif
   return nullptr;
 }
 
 } // namespace mozilla
--- a/content/media/fmp4/PlatformDecoderModule.h
+++ b/content/media/fmp4/PlatformDecoderModule.h
@@ -118,16 +118,17 @@ public:
 
   virtual ~PlatformDecoderModule() {}
 
 protected:
   PlatformDecoderModule() {}
   // Caches pref media.fragmented-mp4.use-blank-decoder
   static bool sUseBlankDecoder;
   static bool sFFmpegDecoderEnabled;
+  static bool sGonkDecoderEnabled;
 };
 
 // A callback used by MediaDataDecoder to return output/errors to the
 // MP4Reader. Implementation is threadsafe, and can be called on any thread.
 class MediaDataDecoderCallback {
 public:
   virtual ~MediaDataDecoderCallback() {}
 
@@ -139,16 +140,20 @@ public:
   // the decoder.
   virtual void Error() = 0;
 
   // Denotes that the last input sample has been inserted into the decoder,
   // and no more output can be produced unless more input is sent.
   virtual void InputExhausted() = 0;
 
   virtual void DrainComplete() = 0;
+
+  virtual void NotifyResourcesStatusChanged() {};
+
+  virtual void ReleaseMediaResources() {};
 };
 
 // MediaDataDecoder is the interface exposed by decoders created by the
 // PlatformDecoderModule's Create*Decoder() functions. The type of
 // media data that the decoder accepts as valid input and produces as
 // output is determined when the MediaDataDecoder is created.
 //
 // All functions must be threadsafe, and be able to be called on an
@@ -204,13 +209,22 @@ public:
   // decoder. The platform decoder should clean up any resources it's using
   // and release memory etc. Shutdown() must block until the decoder has
   // completed shutdown. The reader calls Flush() before calling Shutdown().
   // The reader will delete the decoder once Shutdown() returns.
   // The MediaDataDecoderCallback *must* not be called after Shutdown() has
   // returned.
   virtual nsresult Shutdown() = 0;
 
+  // For Codec Resource Management
+  virtual bool IsWaitingMediaResources() {
+    return false;
+  };
+  virtual bool IsDormantNeeded() {
+    return false;
+  };
+  virtual void ReleaseMediaResources() {};
+  virtual void ReleaseDecoder() {};
 };
 
 } // namespace mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkAudioDecoderManager.cpp
@@ -0,0 +1,197 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "GonkAudioDecoderManager.h"
+#include "MediaDecoderReader.h"
+#include "VideoUtils.h"
+#include "nsTArray.h"
+#include "prlog.h"
+#include "stagefright/MediaBuffer.h"
+#include "stagefright/MetaData.h"
+#include "stagefright/MediaErrors.h"
+#include <stagefright/foundation/AMessage.h>
+#include "media/openmax/OMX_Audio.h"
+
+#define LOG_TAG "GonkAudioDecoderManager"
+#include <android/log.h>
+#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define LOG(...)
+#endif
+#define READ_OUTPUT_BUFFER_TIMEOUT_US  3000
+
+using namespace android;
+typedef android::MediaCodecProxy MediaCodecProxy;
+
+namespace mozilla {
+
+GonkAudioDecoderManager::GonkAudioDecoderManager(
+  const mp4_demuxer::AudioDecoderConfig& aConfig)
+  : mAudioChannels(aConfig.channel_count)
+  , mAudioRate(aConfig.samples_per_second)
+  , mAudioProfile(aConfig.aac_profile)
+  , mAudioBuffer(nullptr)
+{
+  MOZ_COUNT_CTOR(GonkAudioDecoderManager);
+  MOZ_ASSERT(mAudioChannels);
+  mUserData.AppendElements(&aConfig.audio_specific_config[0],
+                           aConfig.audio_specific_config.length());
+}
+
+GonkAudioDecoderManager::~GonkAudioDecoderManager()
+{
+  MOZ_COUNT_DTOR(GonkAudioDecoderManager);
+}
+
+android::sp<MediaCodecProxy>
+GonkAudioDecoderManager::Init(MediaDataDecoderCallback* aCallback)
+{
+  if (mLooper != nullptr) {
+    return nullptr;
+  }
+  // Create ALooper
+  mLooper = new ALooper;
+  mLooper->setName("GonkAudioDecoderManager");
+  mLooper->start();
+
+  mDecoder = MediaCodecProxy::CreateByType(mLooper, "audio/mp4a-latm", false, false, nullptr);
+  if (!mDecoder.get()) {
+    return nullptr;
+  }
+  sp<AMessage> format = new AMessage;
+  // Fixed values
+  ALOG("Init Audio channel no:%d, sample-rate:%d", mAudioChannels, mAudioRate);
+  format->setString("mime", "audio/mp4a-latm");
+  format->setInt32("channel-count", mAudioChannels);
+  format->setInt32("sample-rate", mAudioRate);
+  format->setInt32("aac-profile", mAudioProfile);
+  format->setInt32("is-adts", true);
+  status_t err = mDecoder->configure(format, nullptr, nullptr, 0);
+  if (err != OK || !mDecoder->Prepare()) {
+    return nullptr;
+  }
+  status_t rv = mDecoder->Input(mUserData.Elements(), mUserData.Length(), 0,
+                                android::MediaCodec::BUFFER_FLAG_CODECCONFIG);
+
+  if (rv == OK) {
+    return mDecoder;
+  } else {
+    ALOG("Failed to input codec specific data!");
+    return nullptr;
+  }
+}
+
+nsresult
+GonkAudioDecoderManager::CreateAudioData(int64_t aStreamOffset, AudioData **v) {
+
+  void *data;
+  size_t dataOffset;
+  size_t size;
+  int64_t timeUs;
+
+  if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  data = mAudioBuffer->data();
+  dataOffset = mAudioBuffer->range_offset();
+  size = mAudioBuffer->range_length();
+
+  nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[size/2] );
+  memcpy(buffer.get(), data+dataOffset, size);
+  uint32_t frames = size / (2 * mAudioChannels);
+
+  CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
+  if (!duration.isValid()) {
+    return NS_ERROR_UNEXPECTED;
+  }
+  *v = new AudioData(aStreamOffset, timeUs, duration.value(), frames, buffer.forget(),
+		     mAudioChannels);
+  ReleaseAudioBuffer();
+  return NS_OK;
+}
+
+nsresult
+GonkAudioDecoderManager::Output(int64_t aStreamOffset,
+                                nsAutoPtr<MediaData>& aOutData)
+{
+  aOutData = nullptr;
+  status_t err;
+  err = mDecoder->Output(&mAudioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
+
+  switch (err) {
+    case OK:
+    {
+      if (mAudioBuffer && mAudioBuffer->range_length() != 0) {
+        int64_t timeUs;
+        if (!mAudioBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+          return NS_ERROR_UNEXPECTED;
+	}
+      }
+      AudioData* data = nullptr;
+      nsresult rv = CreateAudioData(aStreamOffset, &data);
+      // Frame should be non null only when we succeeded.
+      if (rv != NS_OK) {
+        return NS_ERROR_UNEXPECTED;
+      }
+      aOutData = data;
+      return NS_OK;
+    }
+    case android::INFO_FORMAT_CHANGED:
+    case android::INFO_OUTPUT_BUFFERS_CHANGED:
+    {
+      // If the format changed, update our cached info.
+      ALOG("Decoder format changed");
+      return Output(aStreamOffset, aOutData);
+    }
+    case -EAGAIN:
+    {
+      return NS_ERROR_NOT_AVAILABLE;
+    }
+    case android::ERROR_END_OF_STREAM:
+    {
+      ALOG("End of Stream");
+      return NS_ERROR_ABORT;
+    }
+    case -ETIMEDOUT:
+    {
+      ALOG("Timeout. can try again next time");
+      return NS_ERROR_UNEXPECTED;
+    }
+    default:
+    {
+      ALOG("Decoder failed, err=%d", err);
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+
+  return NS_OK;
+}
+
+void GonkAudioDecoderManager::ReleaseAudioBuffer() {
+  if (mAudioBuffer) {
+    sp<MetaData> metaData = mAudioBuffer->meta_data();
+    int32_t index;
+    metaData->findInt32(android::MediaCodecProxy::kKeyBufferIndex, &index);
+    mAudioBuffer->release();
+    mAudioBuffer = nullptr;
+    mDecoder->releaseOutputBuffer(index);
+  }
+}
+
+nsresult
+GonkAudioDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
+  uint32_t length = aSample->size;
+  status_t rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0);
+  return rv == OK ? NS_OK : NS_ERROR_UNEXPECTED;
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkAudioDecoderManager.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#if !defined(GonkAudioDecoderManager_h_)
+#define GonkAudioDecoderManager_h_
+
+#include "mozilla/RefPtr.h"
+#include "MP4Reader.h"
+#include "GonkMediaDataDecoder.h"
+
+using namespace android;
+
+namespace mozilla {
+
+class GonkAudioDecoderManager : public GonkDecoderManager {
+typedef android::MediaCodecProxy MediaCodecProxy;
+public:
+  GonkAudioDecoderManager(const mp4_demuxer::AudioDecoderConfig& aConfig);
+  ~GonkAudioDecoderManager();
+
+  virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
+
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
+  virtual nsresult Output(int64_t aStreamOffset,
+                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+private:
+
+  nsresult CreateAudioData(int64_t aStreamOffset,
+                              AudioData** aOutData);
+
+  void ReleaseAudioBuffer();
+  // MediaCodedc's wrapper that performs the decoding.
+  android::sp<MediaCodecProxy> mDecoder;
+
+  const uint32_t mAudioChannels;
+  const uint32_t mAudioRate;
+  const uint32_t mAudioProfile;
+  nsTArray<uint8_t> mUserData;
+
+  MediaDataDecoderCallback*  mReaderCallback;
+  android::MediaBuffer* mAudioBuffer;
+  android::sp<ALooper> mLooper;
+};
+
+} // namespace mozilla
+
+#endif // GonkAudioDecoderManager_h_
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkDecoderModule.cpp
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "GonkDecoderModule.h"
+#include "GonkVideoDecoderManager.h"
+#include "GonkAudioDecoderManager.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/DebugOnly.h"
+#include "GonkMediaDataDecoder.h"
+
+namespace mozilla {
+GonkDecoderModule::GonkDecoderModule()
+{
+}
+
+GonkDecoderModule::~GonkDecoderModule()
+{
+}
+
+/* static */
+void
+GonkDecoderModule::Init()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
+}
+
+nsresult
+GonkDecoderModule::Shutdown()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
+
+  return NS_OK;
+}
+
+already_AddRefed<MediaDataDecoder>
+GonkDecoderModule::CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                                    mozilla::layers::LayersBackend aLayersBackend,
+                                    mozilla::layers::ImageContainer* aImageContainer,
+                                    MediaTaskQueue* aVideoTaskQueue,
+                                    MediaDataDecoderCallback* aCallback)
+{
+  nsRefPtr<MediaDataDecoder> decoder =
+  new GonkMediaDataDecoder(new GonkVideoDecoderManager(aImageContainer,aConfig),
+                           aVideoTaskQueue, aCallback);
+  return decoder.forget();
+}
+
+already_AddRefed<MediaDataDecoder>
+GonkDecoderModule::CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
+                                   MediaTaskQueue* aAudioTaskQueue,
+                                   MediaDataDecoderCallback* aCallback)
+{
+  nsRefPtr<MediaDataDecoder> decoder =
+  new GonkMediaDataDecoder(new GonkAudioDecoderManager(aConfig), aAudioTaskQueue,
+                           aCallback);
+  return decoder.forget();
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkDecoderModule.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#if !defined(GonkPlatformDecoderModule_h_)
+#define GonkPlatformDecoderModule_h_
+
+#include "PlatformDecoderModule.h"
+
+namespace mozilla {
+
+class GonkDecoderModule : public PlatformDecoderModule {
+public:
+  GonkDecoderModule();
+  virtual ~GonkDecoderModule();
+
+  // Called when the decoders have shutdown.
+  virtual nsresult Shutdown() MOZ_OVERRIDE;
+
+  // Decode thread.
+  virtual already_AddRefed<MediaDataDecoder>
+  CreateH264Decoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
+                    mozilla::layers::LayersBackend aLayersBackend,
+                    mozilla::layers::ImageContainer* aImageContainer,
+                    MediaTaskQueue* aVideoTaskQueue,
+                    MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
+
+  // Decode thread.
+  virtual already_AddRefed<MediaDataDecoder>
+  CreateAACDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig,
+                   MediaTaskQueue* aAudioTaskQueue,
+                   MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
+
+  static void Init();
+};
+
+} // namespace mozilla
+
+#endif
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkMediaDataDecoder.cpp
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "mp4_demuxer/mp4_demuxer.h"
+#include "GonkMediaDataDecoder.h"
+#include "VideoUtils.h"
+#include "nsTArray.h"
+
+#include "prlog.h"
+#define LOG_TAG "GonkMediaDataDecoder(blake)"
+#include <android/log.h>
+#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define LOG(...)
+#endif
+
+using namespace android;
+
+namespace mozilla {
+
+GonkMediaDataDecoder::GonkMediaDataDecoder(GonkDecoderManager* aManager,
+                                           MediaTaskQueue* aTaskQueue,
+                                           MediaDataDecoderCallback* aCallback)
+  : mTaskQueue(aTaskQueue)
+  , mCallback(aCallback)
+  , mManager(aManager)
+{
+  MOZ_COUNT_CTOR(GonkMediaDataDecoder);
+}
+
+GonkMediaDataDecoder::~GonkMediaDataDecoder()
+{
+  MOZ_COUNT_DTOR(GonkMediaDataDecoder);
+}
+
+nsresult
+GonkMediaDataDecoder::Init()
+{
+  mDecoder = mManager->Init(mCallback);
+  return mDecoder.get() ? NS_OK : NS_ERROR_UNEXPECTED;
+}
+
+nsresult
+GonkMediaDataDecoder::Shutdown()
+{
+  mDecoder->stop();
+  mDecoder = nullptr;
+  return NS_OK;
+}
+
+// Inserts data into the decoder's pipeline.
+nsresult
+GonkMediaDataDecoder::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  mTaskQueue->Dispatch(
+    NS_NewRunnableMethodWithArg<nsAutoPtr<mp4_demuxer::MP4Sample>>(
+      this,
+      &GonkMediaDataDecoder::ProcessDecode,
+      nsAutoPtr<mp4_demuxer::MP4Sample>(aSample)));
+  return NS_OK;
+}
+
+void
+GonkMediaDataDecoder::ProcessDecode(mp4_demuxer::MP4Sample* aSample)
+{
+  nsresult rv = mManager->Input(aSample);
+  if (rv != NS_OK) {
+    NS_WARNING("GonkAudioDecoder failed to input data");
+    ALOG("Failed to input data err: %d",rv);
+    mCallback->Error();
+    return;
+  }
+
+  mLastStreamOffset = aSample->byte_offset;
+  ProcessOutput();
+}
+
+void
+GonkMediaDataDecoder::ProcessOutput()
+{
+  nsAutoPtr<MediaData> output;
+  nsresult rv;
+  while (true) {
+    rv = mManager->Output(mLastStreamOffset, output);
+    if (rv == NS_OK) {
+      mCallback->Output(output.forget());
+      continue;
+    }
+    else {
+      break;
+    }
+  }
+
+  if (rv == NS_ERROR_NOT_AVAILABLE) {
+    mCallback->InputExhausted();
+    return;
+  }
+  if (rv != NS_OK) {
+    NS_WARNING("GonkMediaDataDecoder failed to output data");
+    ALOG("Failed to output data");
+    mCallback->Error();
+  }
+}
+
+nsresult
+GonkMediaDataDecoder::Flush()
+{
+  // Flush the input task queue. This cancels all pending Decode() calls.
+  // Note this blocks until the task queue finishes its current job, if
+  // it's executing at all. Note the MP4Reader ignores all output while
+  // flushing.
+  mTaskQueue->Flush();
+
+  status_t err = mDecoder->flush();
+  return err == OK ? NS_OK : NS_ERROR_FAILURE;
+}
+
+void
+GonkMediaDataDecoder::ProcessDrain()
+{
+  // Then extract all available output.
+  ProcessOutput();
+  mCallback->DrainComplete();
+}
+
+nsresult
+GonkMediaDataDecoder::Drain()
+{
+  mTaskQueue->Dispatch(NS_NewRunnableMethod(this, &GonkMediaDataDecoder::ProcessDrain));
+  return NS_OK;
+}
+
+bool
+GonkMediaDataDecoder::IsWaitingMediaResources() {
+  return mDecoder->IsWaitingResources();
+}
+
+bool
+GonkMediaDataDecoder::IsDormantNeeded() {
+  return mDecoder->IsDormantNeeded();
+}
+
+void
+GonkMediaDataDecoder::ReleaseMediaResources() {
+  mDecoder->ReleaseMediaResources();
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkMediaDataDecoder.h
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#if !defined(GonkMediaDataDecoder_h_)
+#define GonkMediaDataDecoder_h_
+#include "mp4_demuxer/mp4_demuxer.h"
+#include "mozilla/RefPtr.h"
+#include "MP4Reader.h"
+#include "MediaCodecProxy.h"
+
+namespace mozilla {
+
+// Manage the data flow from inputting encoded data and outputting decode data.
+class GonkDecoderManager {
+public:
+  virtual ~GonkDecoderManager() {}
+
+  // Creates and initializs the GonkDecoder.
+  // Returns nullptr on failure.
+  virtual android::sp<android::MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) = 0;
+
+  // Produces decoded output, it blocks until output can be produced or a timeout
+  // is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
+  // if there's not enough data to produce more output. If this returns a failure
+  // code other than NS_ERROR_NOT_AVAILABLE, an error will be reported to the
+  // MP4Reader.
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
+  virtual nsresult Output(int64_t aStreamOffset,
+                          nsAutoPtr<MediaData>& aOutput) = 0;
+
+};
+
+// Samples are decoded using the GonkDecoder (MediaCodec)
+// created by the GonkDecoderManager. This class implements
+// the higher-level logic that drives mapping the Gonk to the async
+// MediaDataDecoder interface. The specifics of decoding the exact stream
+// type are handled by GonkDecoderManager and the GonkDecoder it creates.
+class GonkMediaDataDecoder : public MediaDataDecoder {
+public:
+  GonkMediaDataDecoder(GonkDecoderManager* aDecoderManager,
+                       MediaTaskQueue* aTaskQueue,
+                       MediaDataDecoderCallback* aCallback);
+
+  ~GonkMediaDataDecoder();
+
+  virtual nsresult Init() MOZ_OVERRIDE;
+
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample);
+
+  virtual nsresult Flush() MOZ_OVERRIDE;
+
+  virtual nsresult Drain() MOZ_OVERRIDE;
+
+  virtual nsresult Shutdown() MOZ_OVERRIDE;
+
+  virtual bool IsWaitingMediaResources() MOZ_OVERRIDE;
+
+  virtual bool IsDormantNeeded() MOZ_OVERRIDE;
+
+  virtual void ReleaseMediaResources() MOZ_OVERRIDE;
+
+private:
+
+  // Called on the task queue. Inserts the sample into the decoder, and
+  // extracts output if available.
+  void ProcessDecode(mp4_demuxer::MP4Sample* aSample);
+
+  // Called on the task queue. Extracts output if available, and delivers
+  // it to the reader. Called after ProcessDecode() and ProcessDrain().
+  void ProcessOutput();
+
+  // Called on the task queue. Orders the Gonk to drain, and then extracts
+  // all available output.
+  void ProcessDrain();
+
+  RefPtr<MediaTaskQueue> mTaskQueue;
+  MediaDataDecoderCallback* mCallback;
+
+  android::sp<android::MediaCodecProxy> mDecoder;
+  nsAutoPtr<GonkDecoderManager> mManager;
+
+  // The last offset into the media resource that was passed into Input().
+  // This is used to approximate the decoder's position in the media resource.
+  int64_t mLastStreamOffset;
+};
+
+} // namespace mozilla
+
+#endif // GonkMediaDataDecoder_h_
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -0,0 +1,456 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 <OMX_IVCommon.h>
+#include <gui/Surface.h>
+#include <ICrypto.h>
+#include "GonkVideoDecoderManager.h"
+#include "MediaDecoderReader.h"
+#include "ImageContainer.h"
+#include "VideoUtils.h"
+#include "nsThreadUtils.h"
+#include "Layers.h"
+#include "prlog.h"
+#include "stagefright/MediaBuffer.h"
+#include "stagefright/MetaData.h"
+#include "stagefright/MediaErrors.h"
+#include <stagefright/foundation/ADebug.h>
+#include <stagefright/foundation/AMessage.h>
+#include "mp4_demuxer/AnnexB.h"
+
+#define READ_OUTPUT_BUFFER_TIMEOUT_US  3000
+
+#define LOG_TAG "GonkVideoDecoderManager"
+#include <android/log.h>
+#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* GetDemuxerLog();
+#define LOG(...) PR_LOG(GetDemuxerLog(), PR_LOG_DEBUG, (__VA_ARGS__))
+#else
+#define LOG(...)
+#endif
+using namespace mozilla::layers;
+using namespace android;
+typedef android::MediaCodecProxy MediaCodecProxy;
+
+namespace mozilla {
+enum {
+  kNotifyCodecReserved = 'core',
+  kNotifyCodecCanceled = 'coca',
+};
+
+GonkVideoDecoderManager::GonkVideoDecoderManager(
+                                  mozilla::layers::ImageContainer* aImageContainer,
+		                  const mp4_demuxer::VideoDecoderConfig& aConfig)
+  : mImageContainer(aImageContainer)
+  , mConfig(aConfig)
+  , mReaderCallback(nullptr)
+  , mColorConverterBufferSize(0)
+{
+  NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
+  MOZ_ASSERT(mImageContainer);
+  MOZ_COUNT_CTOR(GonkVideoDecoderManager);
+  mVideoWidth  = aConfig.display_width;
+  mVideoHeight = aConfig.display_height;
+  mDisplayWidth = aConfig.display_width;
+  mDisplayHeight = aConfig.display_width;
+  mInfo.mVideo.mHasVideo = true;
+  nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
+  mInfo.mVideo.mDisplay = displaySize;
+
+  nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
+  nsIntSize frameSize(mVideoWidth, mVideoHeight);
+  mPicture = pictureRect;
+  mInitialFrame = frameSize;
+  mHandler = new MessageHandler(this);
+  mVideoListener = new VideoResourceListener(this);
+
+}
+
+GonkVideoDecoderManager::~GonkVideoDecoderManager()
+{
+  MOZ_COUNT_DTOR(GonkVideoDecoderManager);
+}
+
+android::sp<MediaCodecProxy>
+GonkVideoDecoderManager::Init(MediaDataDecoderCallback* aCallback)
+{
+  nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
+  nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
+  // Validate the container-reported frame and pictureRect sizes. This ensures
+  // that our video frame creation code doesn't overflow.
+  nsIntSize frameSize(mVideoWidth, mVideoHeight);
+  if (!IsValidVideoRegion(frameSize, pictureRect, displaySize)) {
+    ALOG("It is not a valid region");
+    return nullptr;
+  }
+
+  mReaderCallback = aCallback;
+
+  if (mLooper.get() != nullptr) {
+    return nullptr;
+  }
+  // Create ALooper
+  mLooper = new ALooper;
+  mLooper->setName("GonkVideoDecoderManager");
+  // Register AMessage handler to ALooper.
+  mLooper->registerHandler(mHandler);
+  // Start ALooper thread.
+  if (mLooper->start() != OK) {
+    return nullptr;
+  }
+  mDecoder = MediaCodecProxy::CreateByType(mLooper, "video/avc", false, true, mVideoListener);
+  return mDecoder;
+}
+
+nsresult
+GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
+{
+  *v = nullptr;
+  int64_t timeUs;
+  int32_t keyFrame;
+  if (!mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+    ALOG("Decoder did not return frame time");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (!mVideoBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
+    keyFrame = 0;
+  }
+
+  gfx::IntRect picture = ToIntRect(mPicture);
+  if (mFrameInfo.mWidth != mInitialFrame.width ||
+      mFrameInfo.mHeight != mInitialFrame.height) {
+
+    // Frame size is different from what the container reports. This is legal,
+    // and we will preserve the ratio of the crop rectangle as it
+    // was reported relative to the picture size reported by the container.
+    picture.x = (mPicture.x * mFrameInfo.mWidth) / mInitialFrame.width;
+    picture.y = (mPicture.y * mFrameInfo.mHeight) / mInitialFrame.height;
+    picture.width = (mFrameInfo.mWidth * mPicture.width) / mInitialFrame.width;
+    picture.height = (mFrameInfo.mHeight * mPicture.height) / mInitialFrame.height;
+  }
+
+  if (!(mVideoBuffer != nullptr && mVideoBuffer->size() > 0 && mVideoBuffer->data() != nullptr)) {
+    ALOG("mVideoBuffer is not valid!");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  uint8_t *yuv420p_buffer = (uint8_t *)mVideoBuffer->data();
+  int32_t stride = mFrameInfo.mStride;
+  int32_t slice_height = mFrameInfo.mSliceHeight;
+
+  // Converts to OMX_COLOR_FormatYUV420Planar
+  if (mFrameInfo.mColorFormat != OMX_COLOR_FormatYUV420Planar) {
+    ARect crop;
+    crop.top = 0;
+    crop.bottom = mFrameInfo.mHeight;
+    crop.left = 0;
+    crop.right = mFrameInfo.mWidth;
+    yuv420p_buffer = GetColorConverterBuffer(mFrameInfo.mWidth, mFrameInfo.mHeight);
+    if (mColorConverter.convertDecoderOutputToI420(mVideoBuffer->data(),
+        mFrameInfo.mWidth, mFrameInfo.mHeight, crop, yuv420p_buffer) != OK) {
+        ReleaseVideoBuffer();
+        ALOG("Color conversion failed!");
+        return NS_ERROR_UNEXPECTED;
+    }
+      stride = mFrameInfo.mWidth;
+      slice_height = mFrameInfo.mHeight;
+  }
+
+  size_t yuv420p_y_size = stride * slice_height;
+  size_t yuv420p_u_size = ((stride + 1) / 2) * ((slice_height + 1) / 2);
+  uint8_t *yuv420p_y = yuv420p_buffer;
+  uint8_t *yuv420p_u = yuv420p_y + yuv420p_y_size;
+  uint8_t *yuv420p_v = yuv420p_u + yuv420p_u_size;
+
+  // This is the approximate byte position in the stream.
+  int64_t pos = aStreamOffset;
+
+  VideoData::YCbCrBuffer b;
+  b.mPlanes[0].mData = yuv420p_y;
+  b.mPlanes[0].mWidth = mFrameInfo.mWidth;
+  b.mPlanes[0].mHeight = mFrameInfo.mHeight;
+  b.mPlanes[0].mStride = stride;
+  b.mPlanes[0].mOffset = 0;
+  b.mPlanes[0].mSkip = 0;
+
+  b.mPlanes[1].mData = yuv420p_u;
+  b.mPlanes[1].mWidth = (mFrameInfo.mWidth + 1) / 2;
+  b.mPlanes[1].mHeight = (mFrameInfo.mHeight + 1) / 2;
+  b.mPlanes[1].mStride = (stride + 1) / 2;
+  b.mPlanes[1].mOffset = 0;
+  b.mPlanes[1].mSkip = 0;
+
+  b.mPlanes[2].mData = yuv420p_v;
+  b.mPlanes[2].mWidth =(mFrameInfo.mWidth + 1) / 2;
+  b.mPlanes[2].mHeight = (mFrameInfo.mHeight + 1) / 2;
+  b.mPlanes[2].mStride = (stride + 1) / 2;
+  b.mPlanes[2].mOffset = 0;
+  b.mPlanes[2].mSkip = 0;
+
+  *v = VideoData::Create(
+      mInfo.mVideo,
+      mImageContainer,
+      pos,
+      timeUs,
+      1, // We don't know the duration.
+      b,
+      keyFrame,
+      -1,
+      picture);
+  ReleaseVideoBuffer();
+  return NS_OK;
+}
+
+bool
+GonkVideoDecoderManager::SetVideoFormat()
+{
+  // read video metadata from MediaCodec
+  sp<AMessage> codecFormat;
+  if (mDecoder->getOutputFormat(&codecFormat) == OK) {
+    AString mime;
+    int32_t width = 0;
+    int32_t height = 0;
+    int32_t stride = 0;
+    int32_t slice_height = 0;
+    int32_t color_format = 0;
+    int32_t crop_left = 0;
+    int32_t crop_top = 0;
+    int32_t crop_right = 0;
+    int32_t crop_bottom = 0;
+    if (!codecFormat->findString("mime", &mime) ||
+        !codecFormat->findInt32("width", &width) ||
+        !codecFormat->findInt32("height", &height) ||
+        !codecFormat->findInt32("stride", &stride) ||
+        !codecFormat->findInt32("slice-height", &slice_height) ||
+        !codecFormat->findInt32("color-format", &color_format) ||
+        !codecFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
+      ALOG("Failed to find values");
+      return false;
+    }
+    mFrameInfo.mWidth = width;
+    mFrameInfo.mHeight = height;
+    mFrameInfo.mStride = stride;
+    mFrameInfo.mSliceHeight = slice_height;
+    mFrameInfo.mColorFormat = color_format;
+
+    nsIntSize displaySize(width, height);
+    if (!IsValidVideoRegion(mInitialFrame, mPicture, displaySize)) {
+      ALOG("It is not a valid region");
+      return false;
+    }
+  }
+  return true;
+}
+
+// Blocks until decoded sample is produced by the deoder.
+nsresult
+GonkVideoDecoderManager::Output(int64_t aStreamOffset,
+                                nsAutoPtr<MediaData>& aOutData)
+{
+  aOutData = nullptr;
+  status_t err;
+  if (mDecoder == nullptr) {
+    ALOG("Decoder is not inited");
+    return NS_ERROR_UNEXPECTED;
+  }
+  err = mDecoder->Output(&mVideoBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
+
+  switch (err) {
+    case OK:
+    {
+      VideoData* data = nullptr;
+      nsresult rv = CreateVideoData(aStreamOffset, &data);
+      // Frame should be non null only when we succeeded.
+      if (rv != NS_OK || data == nullptr){
+        ALOG("Error unexpected in CreateVideoData");
+        return NS_ERROR_UNEXPECTED;
+      }
+      aOutData = data;
+      return NS_OK;
+    }
+    case android::INFO_FORMAT_CHANGED:
+    case android::INFO_OUTPUT_BUFFERS_CHANGED:
+    {
+      // If the format changed, update our cached info.
+      ALOG("Decoder format changed");
+      if (!SetVideoFormat()) {
+        return NS_ERROR_UNEXPECTED;
+      }
+      else
+        return Output(aStreamOffset, aOutData);
+    }
+    case -EAGAIN:
+    {
+      return NS_ERROR_NOT_AVAILABLE;
+    }
+    case android::ERROR_END_OF_STREAM:
+    {
+      ALOG("End of Stream");
+      return NS_ERROR_ABORT;
+    }
+    case -ETIMEDOUT:
+    {
+      ALOG("Timeout. can try again next time");
+      return NS_ERROR_UNEXPECTED;
+    }
+    default:
+    {
+      ALOG("Decoder failed, err=%d", err);
+      return NS_ERROR_UNEXPECTED;
+    }
+  }
+
+  return NS_OK;
+}
+
+void GonkVideoDecoderManager::ReleaseVideoBuffer() {
+  if (mVideoBuffer) {
+    sp<MetaData> metaData = mVideoBuffer->meta_data();
+    int32_t index;
+    metaData->findInt32(android::MediaCodecProxy::kKeyBufferIndex, &index);
+    mVideoBuffer->release();
+    mVideoBuffer = nullptr;
+    mDecoder->releaseOutputBuffer(index);
+  }
+}
+
+nsresult
+GonkVideoDecoderManager::Input(mp4_demuxer::MP4Sample* aSample)
+{
+  // We must prepare samples in AVC Annex B.
+  mp4_demuxer::AnnexB::ConvertSample(aSample, mConfig.annex_b);
+  // Forward sample data to the decoder.
+
+  const uint8_t* data = reinterpret_cast<const uint8_t*>(aSample->data);
+  uint32_t length = aSample->size;
+  if (mDecoder == nullptr) {
+    ALOG("Decoder is not inited");
+    return NS_ERROR_UNEXPECTED;
+  }
+  status_t rv = mDecoder->Input(data, length, aSample->composition_timestamp, 0);
+  return (rv == OK) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+void
+GonkVideoDecoderManager::codecReserved()
+{
+  sp<AMessage> format = new AMessage;
+  // Fixed values
+  format->setString("mime", "video/avc");
+  format->setInt32("width", mVideoWidth);
+  format->setInt32("height", mVideoHeight);
+
+  mDecoder->configure(format, nullptr, nullptr, 0);
+  mDecoder->Prepare();
+  SetVideoFormat();
+
+  if (mHandler != nullptr) {
+    // post kNotifyCodecReserved to MediaCodecReader::mLooper thread.
+    sp<AMessage> notify = new AMessage(kNotifyCodecReserved, mHandler->id());
+    notify->post();
+  }
+}
+
+void
+GonkVideoDecoderManager::codecCanceled()
+{
+  mDecoder = nullptr;
+  if (mHandler != nullptr) {
+    // post kNotifyCodecCanceled to MediaCodecReader::mLooper thread.
+    sp<AMessage> notify = new AMessage(kNotifyCodecCanceled, mHandler->id());
+    notify->post();
+  }
+
+}
+
+// Called on GonkVideoDecoderManager::mLooper thread.
+void
+GonkVideoDecoderManager::onMessageReceived(const sp<AMessage> &aMessage)
+{
+  switch (aMessage->what()) {
+    case kNotifyCodecReserved:
+    {
+      // Our decode may have acquired the hardware resource that it needs
+      // to start. Notify the state machine to resume loading metadata.
+      mReaderCallback->NotifyResourcesStatusChanged();
+      break;
+    }
+
+    case kNotifyCodecCanceled:
+    {
+      mReaderCallback->ReleaseMediaResources();
+      break;
+    }
+
+    default:
+      TRESPASS();
+      break;
+  }
+}
+
+GonkVideoDecoderManager::MessageHandler::MessageHandler(GonkVideoDecoderManager *aManager)
+  : mManager(aManager)
+{
+}
+
+GonkVideoDecoderManager::MessageHandler::~MessageHandler()
+{
+  mManager = nullptr;
+}
+
+void
+GonkVideoDecoderManager::MessageHandler::onMessageReceived(const android::sp<android::AMessage> &aMessage)
+{
+  if (mManager != nullptr) {
+    mManager->onMessageReceived(aMessage);
+  }
+}
+
+GonkVideoDecoderManager::VideoResourceListener::VideoResourceListener(GonkVideoDecoderManager *aManager)
+  : mManager(aManager)
+{
+}
+
+GonkVideoDecoderManager::VideoResourceListener::~VideoResourceListener()
+{
+  mManager = nullptr;
+}
+
+void
+GonkVideoDecoderManager::VideoResourceListener::codecReserved()
+{
+  if (mManager != nullptr) {
+    mManager->codecReserved();
+  }
+}
+
+void
+GonkVideoDecoderManager::VideoResourceListener::codecCanceled()
+{
+  if (mManager != nullptr) {
+    mManager->codecCanceled();
+  }
+}
+
+uint8_t *
+GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight)
+{
+  // Allocate a temporary YUV420Planer buffer.
+  size_t yuv420p_y_size = aWidth * aHeight;
+  size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2);
+  size_t yuv420p_v_size = yuv420p_u_size;
+  size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size;
+  if (mColorConverterBufferSize != yuv420p_size) {
+    mColorConverterBuffer = nullptr; // release the previous buffer first
+    mColorConverterBuffer = new uint8_t[yuv420p_size];
+    mColorConverterBufferSize = yuv420p_size;
+  }
+  return mColorConverterBuffer.get();
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/GonkVideoDecoderManager.h
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#if !defined(GonkVideoDecoderManager_h_)
+#define GonkVideoDecoderManager_h_
+
+#include "MP4Reader.h"
+#include "nsRect.h"
+#include "GonkMediaDataDecoder.h"
+#include "mozilla/RefPtr.h"
+#include "I420ColorConverterHelper.h"
+
+using namespace android;
+namespace mozilla {
+
+class GonkVideoDecoderManager : public GonkDecoderManager {
+typedef android::MediaCodecProxy MediaCodecProxy;
+
+public:
+  GonkVideoDecoderManager(mozilla::layers::ImageContainer* aImageContainer,
+		          const mp4_demuxer::VideoDecoderConfig& aConfig);
+
+  ~GonkVideoDecoderManager();
+
+  virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
+
+  virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+
+  virtual nsresult Output(int64_t aStreamOffset,
+                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+
+private:
+  struct FrameInfo
+  {
+    int32_t mWidth = 0;
+    int32_t mHeight = 0;
+    int32_t mStride = 0;
+    int32_t mSliceHeight = 0;
+    int32_t mColorFormat = 0;
+    int32_t mCropLeft = 0;
+    int32_t mCropTop = 0;
+    int32_t mCropRight = 0;
+    int32_t mCropBottom = 0;
+  };
+  class MessageHandler : public android::AHandler
+  {
+  public:
+    MessageHandler(GonkVideoDecoderManager *aManager);
+    ~MessageHandler();
+
+    virtual void onMessageReceived(const android::sp<android::AMessage> &aMessage);
+
+  private:
+    // Forbidden
+    MessageHandler() MOZ_DELETE;
+    MessageHandler(const MessageHandler &rhs) MOZ_DELETE;
+    const MessageHandler &operator=(const MessageHandler &rhs) MOZ_DELETE;
+
+    GonkVideoDecoderManager *mManager;
+  };
+  friend class MessageHandler;
+
+  class VideoResourceListener : public android::MediaCodecProxy::CodecResourceListener
+  {
+  public:
+    VideoResourceListener(GonkVideoDecoderManager *aManager);
+    ~VideoResourceListener();
+
+    virtual void codecReserved() MOZ_OVERRIDE;
+    virtual void codecCanceled() MOZ_OVERRIDE;
+
+  private:
+    // Forbidden
+    VideoResourceListener() MOZ_DELETE;
+    VideoResourceListener(const VideoResourceListener &rhs) MOZ_DELETE;
+    const VideoResourceListener &operator=(const VideoResourceListener &rhs) MOZ_DELETE;
+
+    GonkVideoDecoderManager *mManager;
+  };
+  friend class VideoResourceListener;
+
+  bool SetVideoFormat();
+
+  nsresult CreateVideoData(int64_t aStreamOffset, VideoData** aOutData);
+  void ReleaseVideoBuffer();
+  uint8_t* GetColorConverterBuffer(int32_t aWidth, int32_t aHeight);
+
+  // For codec resource management
+  void codecReserved();
+  void codecCanceled();
+  void onMessageReceived(const sp<AMessage> &aMessage);
+
+  const mp4_demuxer::VideoDecoderConfig& mConfig;
+  uint32_t mVideoWidth;
+  uint32_t mVideoHeight;
+  uint32_t mDisplayWidth;
+  uint32_t mDisplayHeight;
+  nsIntRect mPicture;
+  nsIntSize mInitialFrame;
+
+  android::sp<MediaCodecProxy> mDecoder;
+  nsRefPtr<layers::ImageContainer> mImageContainer;
+  MediaDataDecoderCallback* mCallback;
+
+  android::MediaBuffer* mVideoBuffer;
+
+  MediaDataDecoderCallback*  mReaderCallback;
+  MediaInfo mInfo;
+  android::sp<VideoResourceListener> mVideoListener;
+  android::sp<MessageHandler> mHandler;
+  android::sp<ALooper> mLooper;
+  FrameInfo mFrameInfo;
+
+  // color converter
+  android::I420ColorConverterHelper mColorConverter;
+  nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
+  size_t mColorConverterBufferSize;
+};
+
+} // namespace mozilla
+
+#endif // GonkVideoDecoderManager_h_
new file mode 100644
--- /dev/null
+++ b/content/media/fmp4/gonk/moz.build
@@ -0,0 +1,32 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXPORTS += [
+    'GonkAudioDecoderManager.h',
+    'GonkDecoderModule.h',
+    'GonkMediaDataDecoder.h',
+    'GonkVideoDecoderManager.h',
+]
+UNIFIED_SOURCES += [
+    'GonkAudioDecoderManager.cpp',
+    'GonkDecoderModule.cpp',
+    'GonkMediaDataDecoder.cpp',
+    'GonkVideoDecoderManager.cpp',
+]
+LOCAL_INCLUDES += [
+    '/content/media/omx/',
+    '/content/media/omx/mediaresourcemanager',
+]
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
+
+FAIL_ON_WARNINGS = True
+
+CXXFLAGS += [
+    '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
+        'frameworks/native/opengl/include',]
+]
--- a/content/media/fmp4/moz.build
+++ b/content/media/fmp4/moz.build
@@ -63,14 +63,18 @@ if CONFIG['MOZ_APPLEMEDIA']:
   ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '../base',
 ]
   
+if CONFIG['ANDROID_VERSION'] >= '18'and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
+    DEFINES['MOZ_GONK_MEDIACODEC'] = True
+    DIRS += ['gonk']
+
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     DEFINES['NOMINMAX'] = True
--- a/content/media/omx/MediaCodecProxy.cpp
+++ b/content/media/omx/MediaCodecProxy.cpp
@@ -1,20 +1,25 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "MediaCodecProxy.h"
-
 #include <string.h>
+#include <binder/IPCThreadState.h>
+#include <stagefright/foundation/ABuffer.h>
+#include <stagefright/foundation/ADebug.h>
+#include <stagefright/MetaData.h>
 
-#include <binder/IPCThreadState.h>
-
+#define LOG_TAG "MediaCodecProxy"
+#include <android/log.h>
+#define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
+#define TIMEOUT_DEQUEUE_INPUTBUFFER_MS 1000000ll
 namespace android {
 
 sp<MediaCodecProxy>
 MediaCodecProxy::CreateByType(sp<ALooper> aLooper,
                               const char *aMime,
                               bool aEncoder,
                               bool aAsync,
                               wp<CodecResourceListener> aListener)
@@ -384,9 +389,110 @@ MediaCodecProxy::resourceCanceled()
 
   // Notification
   sp<CodecResourceListener> listener = mListener.promote();
   if (listener != nullptr) {
     listener->codecCanceled();
   }
 }
 
+bool MediaCodecProxy::Prepare()
+{
+
+  status_t err;
+  if (start() != OK) {
+    ALOG("Couldn't start MediaCodec");
+    return false;
+  }
+  if (getInputBuffers(&mInputBuffers) != OK) {
+    ALOG("Couldn't get input buffers from MediaCodec");
+    return false;
+  }
+  if (getOutputBuffers(&mOutputBuffers) != OK) {
+    ALOG("Couldn't get output buffers from MediaCodec");
+    return false;
+  }
+
+  return true;
+}
+
+status_t MediaCodecProxy::Input(const uint8_t* aData, uint32_t aDataSize,
+                                int64_t aTimestampUsecs, uint64_t aflags)
+{
+  if (mCodec == nullptr) {
+    ALOG("MediaCodec has not been inited from input!");
+    return NO_INIT;
+  }
+
+  size_t index;
+  status_t err = dequeueInputBuffer(&index, TIMEOUT_DEQUEUE_INPUTBUFFER_MS);
+  if (err != OK) {
+    ALOG("dequeueInputBuffer returned %d", err);
+    return err;
+  }
+  const sp<ABuffer> &dstBuffer = mInputBuffers.itemAt(index);
+
+  CHECK_LE(aDataSize, dstBuffer->capacity());
+  dstBuffer->setRange(0, aDataSize);
+
+  memcpy(dstBuffer->data(), aData, aDataSize);
+  err = queueInputBuffer(index, 0, dstBuffer->size(), aTimestampUsecs, aflags);
+  if (err != OK) {
+    ALOG("queueInputBuffer returned %d", err);
+    return err;
+  }
+  return err;
+}
+
+status_t MediaCodecProxy::Output(MediaBuffer** aBuffer, int64_t aTimeoutUs)
+{
+
+  if (mCodec == nullptr) {
+    ALOG("MediaCodec has not been inited from output!");
+    return NO_INIT;
+  }
+
+  size_t index = 0;
+  size_t offset = 0;
+  size_t size = 0;
+  int64_t timeUs = 0;
+  uint32_t flags = 0;
+
+  *aBuffer = nullptr;
+
+  status_t err = dequeueOutputBuffer(&index, &offset, &size,
+                                      &timeUs, &flags, aTimeoutUs);
+  if (err != OK) {
+    ALOG("Output returned %d", err);
+    return err;
+  }
+
+  MediaBuffer *buffer;
+
+  buffer = new MediaBuffer(mOutputBuffers.itemAt(index));
+  sp<MetaData> metaData = buffer->meta_data();
+  metaData->setInt32(kKeyBufferIndex, index);
+  metaData->setInt64(kKeyTime, timeUs);
+  buffer->set_range(buffer->range_offset(), size);
+  *aBuffer = buffer;
+  return err;
+}
+
+bool MediaCodecProxy::IsWaitingResources()
+{
+  return mCodec == nullptr;
+}
+
+bool MediaCodecProxy::IsDormantNeeded()
+{
+  return mCodecLooper.get() ? true : false;
+}
+
+void MediaCodecProxy::ReleaseMediaResources()
+{
+  if (mCodec.get()) {
+    mCodec->stop();
+    mCodec->release();
+    mCodec.clear();
+  }
+}
+
 } // namespace android
--- a/content/media/omx/MediaCodecProxy.h
+++ b/content/media/omx/MediaCodecProxy.h
@@ -5,22 +5,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MEDIA_CODEC_PROXY_H
 #define MEDIA_CODEC_PROXY_H
 
 #include <nsString.h>
 
 #include <stagefright/MediaCodec.h>
+#include <stagefright/MediaBuffer.h>
 #include <utils/threads.h>
 
 #include "MediaResourceHandler.h"
 
 namespace android {
-
+// This class is intended to be a proxy for MediaCodec with codec resource
+// management. Basically user can use it like MediaCodec, but need to handle
+// the listener when Codec is reserved for Async case. A good example is
+// MediaCodecReader.cpp. Another useage is to use configure(), Prepare(),
+// Input(), and Output(). It is used in GonkVideoDecoderManager.cpp which
+// doesn't need to handle the buffers for codec.
 class MediaCodecProxy : public MediaResourceHandler::ResourceListener
 {
 public:
   /* Codec resource notification listener.
    * All functions are called on the Binder thread.
    */
   struct CodecResourceListener : public virtual RefBase {
     /* The codec resource is reserved and can be granted.
@@ -29,16 +35,19 @@ public:
     virtual void codecReserved() = 0;
     /* The codec resource is not reserved any more.
      * The client should release the resource as soon as possible if the
      * resource is still being held.
      */
     virtual void codecCanceled() = 0;
   };
 
+  enum {
+    kKeyBufferIndex = 'bfin',
+  };
   // Check whether MediaCodec has been allocated.
   bool allocated() const;
 
   // Static MediaCodec methods
   // Only support MediaCodec::CreateByType()
   static sp<MediaCodecProxy> CreateByType(sp<ALooper> aLooper,
                                           const char *aMime,
                                           bool aEncoder,
@@ -99,16 +108,23 @@ public:
 
   status_t getOutputBuffers(Vector<sp<ABuffer>> *aBuffers) const;
 
   // Notification will be posted once there "is something to do", i.e.
   // an input/output buffer has become available, a format change is
   // pending, an error is pending.
   void requestActivityNotification(const sp<AMessage> &aNotify);
 
+  status_t Input(const uint8_t* aData, uint32_t aDataSize,
+                 int64_t aTimestampUsecs, uint64_t flags);
+  status_t Output(MediaBuffer** aBuffer, int64_t aTimeoutUs);
+  bool Prepare();
+  bool IsWaitingResources();
+  bool IsDormantNeeded();
+  void ReleaseMediaResources();
 protected:
   virtual ~MediaCodecProxy();
 
   // MediaResourceHandler::EventListener::resourceReserved()
   virtual void resourceReserved();
   // MediaResourceHandler::EventListener::resourceCanceled()
   virtual void resourceCanceled();
 
@@ -144,13 +160,17 @@ private:
   wp<CodecResourceListener> mListener;
 
   // Media Resource Management
   sp<MediaResourceHandler> mResourceHandler;
 
   // MediaCodec instance
   mutable RWLock mCodecLock;
   sp<MediaCodec> mCodec;
+  //MediaCodec buffers to hold input/output data.
+  Vector<sp<ABuffer> > mInputBuffers;
+  Vector<sp<ABuffer> > mOutputBuffers;
+
 };
 
 } // namespace android
 
 #endif // MEDIA_CODEC_PROXY_H
--- a/dom/bluetooth/BluetoothCommon.h
+++ b/dom/bluetooth/BluetoothCommon.h
@@ -127,23 +127,88 @@ extern bool gBluetoothDebugFlag;
 #define BLUETOOTH_ADDRESS_NONE   "00:00:00:00:00:00"
 #define BLUETOOTH_ADDRESS_BYTES  6
 
 // Bluetooth stack internal error, such as I/O error
 #define ERR_INTERNAL_ERROR "InternalError"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
+enum BluetoothStatus {
+  STATUS_SUCCESS,
+  STATUS_FAIL,
+  STATUS_NOT_READY,
+  STATUS_NOMEM,
+  STATUS_BUSY,
+  STATUS_DONE,
+  STATUS_UNSUPPORTED,
+  STATUS_PARM_INVALID,
+  STATUS_UNHANDLED,
+  STATUS_AUTH_FAILURE,
+  STATUS_RMT_DEV_DOWN
+};
+
 enum BluetoothSocketType {
   RFCOMM = 1,
   SCO    = 2,
   L2CAP  = 3,
   EL2CAP = 4
 };
 
+enum BluetoothHandsfreeAtResponse {
+  HFP_AT_RESPONSE_ERROR,
+  HFP_AT_RESPONSE_OK
+};
+
+enum BluetoothHandsfreeCallAddressType {
+  HFP_CALL_ADDRESS_TYPE_UNKNOWN,
+  HFP_CALL_ADDRESS_TYPE_INTERNATIONAL
+};
+
+enum BluetoothHandsfreeCallDirection {
+  HFP_CALL_DIRECTION_OUTGOING,
+  HFP_CALL_DIRECTION_INCOMING
+};
+
+enum BluetoothHandsfreeCallMode {
+  HFP_CALL_MODE_VOICE,
+  HFP_CALL_MODE_DATA,
+  HFP_CALL_MODE_FAX
+};
+
+enum BluetoothHandsfreeCallMptyType {
+  HFP_CALL_MPTY_TYPE_SINGLE,
+  HFP_CALL_MPTY_TYPE_MULTI
+};
+
+enum BluetoothHandsfreeCallState {
+  HFP_CALL_STATE_ACTIVE,
+  HFP_CALL_STATE_HELD,
+  HFP_CALL_STATE_DIALING,
+  HFP_CALL_STATE_ALERTING,
+  HFP_CALL_STATE_INCOMING,
+  HFP_CALL_STATE_WAITING,
+  HFP_CALL_STATE_IDLE
+};
+
+enum BluetoothHandsfreeNetworkState {
+  HFP_NETWORK_STATE_NOT_AVAILABLE,
+  HFP_NETWORK_STATE_AVAILABLE
+};
+
+enum BluetoothHandsfreeServiceType {
+  HFP_SERVICE_TYPE_HOME,
+  HFP_SERVICE_TYPE_ROAMING
+};
+
+enum BluetoothHandsfreeVolumeType {
+  HFP_VOLUME_TYPE_SPEAKER,
+  HFP_VOLUME_TYPE_MICROPHONE
+};
+
 class BluetoothSignal;
 typedef mozilla::Observer<BluetoothSignal> BluetoothSignalObserver;
 
 // Enums for object types, currently used for shared function lookups
 // (get/setproperty, etc...). Possibly discernable via dbus paths, but this
 // method is future-proofed for platform independence.
 enum BluetoothObjectType {
   TYPE_MANAGER = 0,
@@ -158,11 +223,54 @@ enum ControlPlayStatus {
   PLAYSTATUS_PLAYING  = 0x01,
   PLAYSTATUS_PAUSED   = 0x02,
   PLAYSTATUS_FWD_SEEK = 0x03,
   PLAYSTATUS_REV_SEEK = 0x04,
   PLAYSTATUS_UNKNOWN,
   PLAYSTATUS_ERROR    = 0xFF,
 };
 
+enum BluetoothAvrcpPlayerAttribute {
+  AVRCP_PLAYER_ATTRIBUTE_EQUALIZER,
+  AVRCP_PLAYER_ATTRIBUTE_REPEAT,
+  AVRCP_PLAYER_ATTRIBUTE_SHUFFLE,
+  AVRCP_PLAYER_ATTRIBUTE_SCAN
+};
+
+enum BluetoothAvrcpStatus {
+  AVRCP_STATUS_BAD_COMMAND,
+  AVRCP_STATUS_BAD_PARAMETER,
+  AVRCP_STATUS_NOT_FOUND,
+  AVRCP_STATUS_INTERNAL_ERROR,
+  AVRCP_STATUS_SUCCESS
+};
+
+enum BluetoothAvrcpEvent {
+  AVRCP_EVENT_PLAY_STATUS_CHANGED,
+  AVRCP_EVENT_TRACK_CHANGE,
+  AVRCP_EVENT_TRACK_REACHED_END,
+  AVRCP_EVENT_TRACK_REACHED_START,
+  AVRCP_EVENT_PLAY_POS_CHANGED,
+  AVRCP_EVENT_APP_SETTINGS_CHANGED
+};
+
+enum BluetoothAvrcpNotification {
+  AVRCP_NTF_INTERIM,
+  AVRCP_NTF_CHANGED
+};
+
+struct BluetoothAvrcpElementAttribute {
+  uint32_t mId;
+  nsString mValue;
+};
+
+struct BluetoothAvrcpNotificationParam {
+  ControlPlayStatus mPlayStatus;
+  uint8_t mTrack[8];
+  uint32_t mSongPos;
+  uint8_t mNumAttr;
+  uint8_t mIds[256];
+  uint8_t mValues[256];
+};
+
 END_BLUETOOTH_NAMESPACE
 
 #endif // mozilla_dom_bluetooth_bluetoothcommon_h__
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
@@ -84,34 +84,34 @@ public:
     return NS_OK;
   }
 };
 
 #if ANDROID_VERSION > 17
 class UpdateRegisterNotificationTask : public nsRunnable
 {
 public:
-  UpdateRegisterNotificationTask(btrc_event_id_t aEventId, uint32_t aParam)
-    : mEventId(aEventId)
+  UpdateRegisterNotificationTask(BluetoothAvrcpEvent aEvent, uint32_t aParam)
+    : mEvent(aEvent)
     , mParam(aParam)
   {
     MOZ_ASSERT(!NS_IsMainThread());
   }
 
   nsresult Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
     NS_ENSURE_TRUE(a2dp, NS_OK);
-    a2dp->UpdateRegisterNotification(mEventId, mParam);
+    a2dp->UpdateRegisterNotification(mEvent, mParam);
     return NS_OK;
   }
 private:
-  btrc_event_id_t mEventId;
+  BluetoothAvrcpEvent mEvent;
   uint32_t mParam;
 };
 
 /*
  * This function maps attribute id and returns corresponding values
  * Attribute id refers to btrc_media_attr_t in bt_rc.h
  */
 static void
@@ -144,43 +144,45 @@ ConvertAttributeString(int aAttrId, nsAS
       aAttrStr.AppendInt(a2dp->GetDuration());
       break;
   }
 }
 
 class UpdateElementAttrsTask : public nsRunnable
 {
 public:
-  UpdateElementAttrsTask(uint8_t aNumAttr, btrc_media_attr_t* aPlayerAttrs)
-    : mNumAttr(aNumAttr)
-    , mPlayerAttrs(aPlayerAttrs)
+  UpdateElementAttrsTask(uint8_t aNumAttr, const btrc_media_attr_t* aPlayerAttrs)
+  : mNumAttr(aNumAttr)
   {
     MOZ_ASSERT(!NS_IsMainThread());
+
+    mAttrs = new BluetoothAvrcpElementAttribute[mNumAttr];
+
+    for (uint8_t i = 0; i < mNumAttr; ++i) {
+      mAttrs[i].mId = aPlayerAttrs[i];
+    }
   }
 
   nsresult Run()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
-    btrc_element_attr_val_t* attrs = new btrc_element_attr_val_t[mNumAttr];
-    for (int i = 0; i < mNumAttr; i++) {
-      nsAutoString attrText;
-      attrs[i].attr_id = mPlayerAttrs[i];
-      ConvertAttributeString(mPlayerAttrs[i], attrText);
-      strcpy((char *)attrs[i].text, NS_ConvertUTF16toUTF8(attrText).get());
+    for (uint8_t i = 0; i < mNumAttr; ++i) {
+      ConvertAttributeString(mAttrs[i].mId, mAttrs[i].mValue);
     }
 
     NS_ENSURE_TRUE(sBtAvrcpInterface, NS_OK);
-    sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, attrs, nullptr);
+    sBtAvrcpInterface->GetElementAttrRsp(mNumAttr, mAttrs, nullptr);
 
     return NS_OK;
   }
+
 private:
   uint8_t mNumAttr;
-  btrc_media_attr_t* mPlayerAttrs;
+  nsAutoArrayPtr<BluetoothAvrcpElementAttribute> mAttrs;
 };
 
 class UpdatePassthroughCmdTask : public nsRunnable
 {
 public:
   UpdatePassthroughCmdTask(const nsAString& aName)
     : mName(aName)
   {
@@ -337,19 +339,40 @@ AvrcpGetElementAttrCallback(uint8_t aNum
  * To reply RegisterNotification INTERIM response
  * See AVRCP 1.3 Spec 25.2
  * aParam: It only valids if event_id is BTRC_EVT_PLAY_POS_CHANGED,
  * which is playback interval time
  */
 static void
 AvrcpRegisterNotificationCallback(btrc_event_id_t aEventId, uint32_t aParam)
 {
+  BluetoothAvrcpEvent event;
+
   MOZ_ASSERT(!NS_IsMainThread());
 
-  NS_DispatchToMainThread(new UpdateRegisterNotificationTask(aEventId, aParam));
+  switch (aEventId) {
+    case BTRC_EVT_PLAY_STATUS_CHANGED:
+      event = AVRCP_EVENT_PLAY_STATUS_CHANGED;
+    case BTRC_EVT_TRACK_CHANGE:
+      event = AVRCP_EVENT_TRACK_CHANGE;
+    case BTRC_EVT_TRACK_REACHED_END:
+      event = AVRCP_EVENT_TRACK_REACHED_END;
+    case BTRC_EVT_TRACK_REACHED_START:
+      event = AVRCP_EVENT_TRACK_REACHED_START;
+    case BTRC_EVT_PLAY_POS_CHANGED:
+      event = AVRCP_EVENT_PLAY_POS_CHANGED;
+    case BTRC_EVT_APP_SETTINGS_CHANGED:
+      event = AVRCP_EVENT_APP_SETTINGS_CHANGED;
+      break;
+    default:
+      BT_LOGR("Unknown event 0x%x", aEventId);
+      return;
+  }
+
+  NS_DispatchToMainThread(new UpdateRegisterNotificationTask(event, aParam));
 }
 
 /*
  * Player application settings is optional for Avrcp 1.3
  * B2G 1.3 currently does not support Player application setting
  * related functions. Support Player Setting in the future version
  */
 static void
@@ -495,17 +518,17 @@ static btrc_callbacks_t sBtAvrcpCallback
 #if ANDROID_VERSION > 17
 class InitAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
 {
 public:
   InitAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothAvrcpInterface::Init failed: %d",
                (int)aStatus);
     if (mRes) {
       mRes->OnError(NS_ERROR_FAILURE);
     }
   }
 
@@ -523,17 +546,17 @@ private:
 
 class InitA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
 {
 public:
   InitA2dpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothA2dpInterface::Init failed: %d",
                (int)aStatus);
     if (mRes) {
       mRes->OnError(NS_ERROR_FAILURE);
     }
   }
 
@@ -654,17 +677,17 @@ BluetoothA2dpManager::Get()
 #if ANDROID_VERSION > 17
 class CleanupAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
 {
 public:
   CleanupAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothAvrcpInterface::Cleanup failed: %d",
                (int)aStatus);
     if (mRes) {
       mRes->OnError(NS_ERROR_FAILURE);
     }
   }
 
@@ -683,17 +706,17 @@ private:
 
 class CleanupA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
 {
 public:
   CleanupA2dpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothA2dpInterface::Cleanup failed: %d",
                (int)aStatus);
     if (mRes) {
       mRes->OnError(NS_ERROR_FAILURE);
     }
   }
 
@@ -780,17 +803,17 @@ BluetoothA2dpManager::OnConnectError()
 
   mController = nullptr;
   mDeviceAddress.Truncate();
 }
 
 class ConnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_LOGR("BluetoothA2dpInterface::Connect failed: %d", (int)aStatus);
 
     NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
     sBluetoothA2dpManager->OnConnectError();
   }
 };
 
@@ -817,34 +840,31 @@ BluetoothA2dpManager::Connect(const nsAS
   mController = aController;
 
   if (!sBtA2dpInterface) {
     BT_LOGR("sBluetoothA2dpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
-  bt_bdaddr_t remoteAddress;
-  StringToBdAddressType(aDeviceAddress, &remoteAddress);
-
-  sBtA2dpInterface->Connect(&remoteAddress, new ConnectResultHandler());
+  sBtA2dpInterface->Connect(aDeviceAddress, new ConnectResultHandler());
 }
 
 void
 BluetoothA2dpManager::OnDisconnectError()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
 }
 
 class DisconnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_LOGR("BluetoothA2dpInterface::Disconnect failed: %d", (int)aStatus);
 
     NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
     sBluetoothA2dpManager->OnDisconnectError();
   }
 };
 
@@ -874,20 +894,17 @@ BluetoothA2dpManager::Disconnect(Bluetoo
   mController = aController;
 
   if (!sBtA2dpInterface) {
     BT_LOGR("sBluetoothA2dpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
-  bt_bdaddr_t remoteAddress;
-  StringToBdAddressType(mDeviceAddress, &remoteAddress);
-
-  sBtA2dpInterface->Disconnect(&remoteAddress, new DisconnectResultHandler());
+  sBtA2dpInterface->Disconnect(mDeviceAddress, new DisconnectResultHandler());
 }
 
 void
 BluetoothA2dpManager::OnConnect(const nsAString& aErrorStr)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   /**
@@ -1098,36 +1115,35 @@ BluetoothA2dpManager::UpdateMetaData(con
   MOZ_ASSERT(NS_IsMainThread());
 
 #if ANDROID_VERSION > 17
   NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
 
   // Send track changed and position changed if track num is not the same.
   // See also AVRCP 1.3 Spec 5.4.2
   if (mMediaNumber != aMediaNumber &&
-      mTrackChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
-    btrc_register_notification_t param;
+      mTrackChangedNotifyType == AVRCP_NTF_INTERIM) {
+    BluetoothAvrcpNotificationParam param;
     // convert to network big endian format
     // since track stores as uint8[8]
     // 56 = 8 * (BTRC_UID_SIZE -1)
     for (int i = 0; i < BTRC_UID_SIZE; ++i) {
-      param.track[i] = (aMediaNumber >> (56 - 8 * i));
+      param.mTrack[i] = (aMediaNumber >> (56 - 8 * i));
     }
-    mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-    sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_TRACK_CHANGE,
-                                               BTRC_NOTIFICATION_TYPE_CHANGED,
-                                               &param, nullptr);
-    if (mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
-      param.song_pos = mPosition;
+    mTrackChangedNotifyType = AVRCP_NTF_CHANGED;
+    sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_TRACK_CHANGE,
+                                               AVRCP_NTF_CHANGED,
+                                               param, nullptr);
+    if (mPlayPosChangedNotifyType == AVRCP_NTF_INTERIM) {
+      param.mSongPos = mPosition;
       // EVENT_PLAYBACK_POS_CHANGED shall be notified if changed current track
-      mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-      sBtAvrcpInterface->RegisterNotificationRsp(
-        BTRC_EVT_PLAY_POS_CHANGED,
-        BTRC_NOTIFICATION_TYPE_CHANGED,
-        &param, nullptr);
+      mPlayPosChangedNotifyType = AVRCP_NTF_CHANGED;
+      sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_PLAY_POS_CHANGED,
+                                                 AVRCP_NTF_CHANGED,
+                                                 param, nullptr);
     }
   }
 
   mTitle.Assign(aTitle);
   mArtist.Assign(aArtist);
   mAlbum.Assign(aAlbum);
   mMediaNumber = aMediaNumber;
   mTotalMediaCount = aTotalMediaCount;
@@ -1144,105 +1160,105 @@ BluetoothA2dpManager::UpdatePlayStatus(u
                                        uint32_t aPosition,
                                        ControlPlayStatus aPlayStatus)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
 #if ANDROID_VERSION > 17
   NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
   // always update playstatus first
-  sBtAvrcpInterface->GetPlayStatusRsp((btrc_play_status_t)aPlayStatus,
-                                      aDuration, aPosition, nullptr);
+  sBtAvrcpInterface->GetPlayStatusRsp(aPlayStatus, aDuration,
+                                      aPosition, nullptr);
   // when play status changed, send both play status and position
   if (mPlayStatus != aPlayStatus &&
-      mPlayStatusChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
-    btrc_register_notification_t param;
-    param.play_status = (btrc_play_status_t)aPlayStatus;
-    mPlayStatusChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-    sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_STATUS_CHANGED,
-                                               BTRC_NOTIFICATION_TYPE_CHANGED,
-                                               &param, nullptr);
+      mPlayStatusChangedNotifyType == AVRCP_NTF_INTERIM) {
+    BluetoothAvrcpNotificationParam param;
+    param.mPlayStatus = aPlayStatus;
+    mPlayStatusChangedNotifyType = AVRCP_NTF_CHANGED;
+    sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_PLAY_STATUS_CHANGED,
+                                               AVRCP_NTF_CHANGED,
+                                               param, nullptr);
   }
 
   if (mPosition != aPosition &&
-      mPlayPosChangedNotifyType == BTRC_NOTIFICATION_TYPE_INTERIM) {
-    btrc_register_notification_t param;
-    param.song_pos = aPosition;
-    mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_CHANGED;
-    sBtAvrcpInterface->RegisterNotificationRsp(BTRC_EVT_PLAY_POS_CHANGED,
-                                               BTRC_NOTIFICATION_TYPE_CHANGED,
-                                               &param, nullptr);
+      mPlayPosChangedNotifyType == AVRCP_NTF_INTERIM) {
+    BluetoothAvrcpNotificationParam param;
+    param.mSongPos = aPosition;
+    mPlayPosChangedNotifyType = AVRCP_NTF_CHANGED;
+    sBtAvrcpInterface->RegisterNotificationRsp(AVRCP_EVENT_PLAY_POS_CHANGED,
+                                               AVRCP_NTF_CHANGED,
+                                               param, nullptr);
   }
 
   mDuration = aDuration;
   mPosition = aPosition;
   mPlayStatus = aPlayStatus;
 #endif
 }
 
 /*
  * This function handles RegisterNotification request from
  * AvrcpRegisterNotificationCallback, which updates current
  * track/status/position status in the INTERRIM response.
  *
  * aParam is only valid when position changed
  */
 void
-BluetoothA2dpManager::UpdateRegisterNotification(int aEventId, int aParam)
+BluetoothA2dpManager::UpdateRegisterNotification(BluetoothAvrcpEvent aEvent,
+                                                 uint32_t aParam)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
 #if ANDROID_VERSION > 17
   NS_ENSURE_TRUE_VOID(sBtAvrcpInterface);
 
-  btrc_register_notification_t param;
+  BluetoothAvrcpNotificationParam param;
 
-  switch (aEventId) {
-    case BTRC_EVT_PLAY_STATUS_CHANGED:
-      mPlayStatusChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM;
-      param.play_status = (btrc_play_status_t)mPlayStatus;
+  switch (aEvent) {
+    case AVRCP_EVENT_PLAY_STATUS_CHANGED:
+      mPlayStatusChangedNotifyType = AVRCP_NTF_INTERIM;
+      param.mPlayStatus = mPlayStatus;
       break;
-    case BTRC_EVT_TRACK_CHANGE:
+    case AVRCP_EVENT_TRACK_CHANGE:
       // In AVRCP 1.3 and 1.4, the identifier parameter of EVENT_TRACK_CHANGED
       // is different.
       // AVRCP 1.4: If no track is selected, we shall return 0xFFFFFFFFFFFFFFFF,
       // otherwise return 0x0 in the INTERRIM response. The expanded text in
       // version 1.4 is to allow for new UID feature. As for AVRCP 1.3, we shall
       // return 0xFFFFFFFF. Since PTS enforces to check this part to comply with
       // the most updated spec.
-      mTrackChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM;
+      mTrackChangedNotifyType = AVRCP_NTF_INTERIM;
       // needs to convert to network big endian format since track stores
       // as uint8[8]. 56 = 8 * (BTRC_UID_SIZE -1).
       for (int index = 0; index < BTRC_UID_SIZE; ++index) {
         // We cannot easily check if a track is selected, so whenever A2DP is
         // streaming, we assume a track is selected.
         if (mSinkState == BluetoothA2dpManager::SinkState::SINK_PLAYING) {
-          param.track[index] = 0x0;
+          param.mTrack[index] = 0x0;
         } else {
-          param.track[index] = 0xFF;
+          param.mTrack[index] = 0xFF;
         }
       }
       break;
-    case BTRC_EVT_PLAY_POS_CHANGED:
+    case AVRCP_EVENT_PLAY_POS_CHANGED:
       // If no track is selected, return 0xFFFFFFFF in the INTERIM response
-      mPlayPosChangedNotifyType = BTRC_NOTIFICATION_TYPE_INTERIM;
+      mPlayPosChangedNotifyType = AVRCP_NTF_INTERIM;
       if (mSinkState == BluetoothA2dpManager::SinkState::SINK_PLAYING) {
-        param.song_pos = mPosition;
+        param.mSongPos = mPosition;
       } else {
-        param.song_pos = 0xFFFFFFFF;
+        param.mSongPos = 0xFFFFFFFF;
       }
       mPlaybackInterval = aParam;
       break;
     default:
       break;
   }
 
-  sBtAvrcpInterface->RegisterNotificationRsp((btrc_event_id_t)aEventId,
-                                              BTRC_NOTIFICATION_TYPE_INTERIM,
-                                              &param, nullptr);
+  sBtAvrcpInterface->RegisterNotificationRsp(aEvent, AVRCP_NTF_INTERIM,
+                                             param, nullptr);
 #endif
 }
 
 void
 BluetoothA2dpManager::GetAlbum(nsAString& aAlbum)
 {
   aAlbum.Assign(mAlbum);
 }
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.h
@@ -47,17 +47,17 @@ public:
                       const nsAString& aArtist,
                       const nsAString& aAlbum,
                       uint64_t aMediaNumber,
                       uint64_t aTotalMediaCount,
                       uint32_t aDuration);
   void UpdatePlayStatus(uint32_t aDuration,
                         uint32_t aPosition,
                         ControlPlayStatus aPlayStatus);
-  void UpdateRegisterNotification(int aEventId, int aParam);
+  void UpdateRegisterNotification(BluetoothAvrcpEvent aEvent, uint32_t aParam);
   void GetAlbum(nsAString& aAlbum);
   uint32_t GetDuration();
   ControlPlayStatus GetPlayStatus();
   uint32_t GetPosition();
   uint64_t GetMediaNumber();
   uint64_t GetTotalMediaNumber();
   void GetTitle(nsAString& aTitle);
   void GetArtist(nsAString& aArtist);
@@ -100,16 +100,16 @@ private:
    * 1. The initial response to this Notify command shall be an INTERIM
    * response with current status.
    * 2. The following response shall be a CHANGED response with the updated
    * status.
    * mPlayStatusChangedNotifType, mTrackChangedNotifType,
    * mPlayPosChangedNotifType represents current RegisterNotification
    * notification type.
    */
-  int mPlayStatusChangedNotifyType;
-  int mTrackChangedNotifyType;
-  int mPlayPosChangedNotifyType;
+  BluetoothAvrcpNotification mPlayStatusChangedNotifyType;
+  BluetoothAvrcpNotification mTrackChangedNotifyType;
+  BluetoothAvrcpNotification mPlayPosChangedNotifyType;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/bluetooth/bluedroid/BluetoothInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothInterface.cpp
@@ -15,16 +15,542 @@
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 template<class T>
 struct interface_traits
 { };
 
 //
+// Conversion
+//
+
+static nsresult
+Convert(bt_status_t aIn, BluetoothStatus& aOut)
+{
+  static const BluetoothStatus sStatus[] = {
+    [BT_STATUS_SUCCESS] = STATUS_SUCCESS,
+    [BT_STATUS_FAIL] = STATUS_FAIL,
+    [BT_STATUS_NOT_READY] = STATUS_NOT_READY,
+    [BT_STATUS_NOMEM] = STATUS_NOMEM,
+    [BT_STATUS_BUSY] = STATUS_BUSY,
+    [BT_STATUS_DONE] = STATUS_DONE,
+    [BT_STATUS_UNSUPPORTED] = STATUS_UNSUPPORTED,
+    [BT_STATUS_PARM_INVALID] = STATUS_PARM_INVALID,
+    [BT_STATUS_UNHANDLED] = STATUS_UNHANDLED,
+    [BT_STATUS_AUTH_FAILURE] = STATUS_AUTH_FAILURE,
+    [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[] = {
+    [false] = BT_SCAN_MODE_CONNECTABLE,
+    [true] = BT_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 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 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(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[] = {
+    [0] = static_cast<btsock_type_t>(0), // invalid, [0] required by gcc
+    [BluetoothSocketType::RFCOMM] = BTSOCK_RFCOMM,
+    [BluetoothSocketType::SCO] = BTSOCK_SCO,
+    [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[] = {
+    [HFP_AT_RESPONSE_ERROR] = BTHF_AT_RESPONSE_ERROR,
+    [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[] = {
+    [HFP_CALL_ADDRESS_TYPE_UNKNOWN] = BTHF_CALL_ADDRTYPE_UNKNOWN,
+    [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[] = {
+    [HFP_CALL_DIRECTION_OUTGOING] = BTHF_CALL_DIRECTION_OUTGOING,
+    [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[] = {
+    [HFP_CALL_MODE_VOICE] = BTHF_CALL_TYPE_VOICE,
+    [HFP_CALL_MODE_DATA] = BTHF_CALL_TYPE_DATA,
+    [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[] = {
+    [HFP_CALL_MPTY_TYPE_SINGLE] = BTHF_CALL_MPTY_TYPE_SINGLE,
+    [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[] = {
+    [HFP_CALL_STATE_ACTIVE] = BTHF_CALL_STATE_ACTIVE,
+    [HFP_CALL_STATE_HELD] = BTHF_CALL_STATE_HELD,
+    [HFP_CALL_STATE_DIALING] = BTHF_CALL_STATE_DIALING,
+    [HFP_CALL_STATE_ALERTING] = BTHF_CALL_STATE_ALERTING,
+    [HFP_CALL_STATE_INCOMING] = BTHF_CALL_STATE_INCOMING,
+    [HFP_CALL_STATE_WAITING] = BTHF_CALL_STATE_WAITING,
+    [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[] = {
+    [HFP_NETWORK_STATE_NOT_AVAILABLE] = BTHF_NETWORK_STATE_NOT_AVAILABLE,
+    [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[] = {
+    [HFP_SERVICE_TYPE_HOME] = BTHF_SERVICE_TYPE_HOME,
+    [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[] = {
+    [HFP_VOLUME_TYPE_SPEAKER] = BTHF_VOLUME_TYPE_SPK,
+    [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;
+}
+
+#if ANDROID_VERSION >= 18
+static nsresult
+Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut)
+{
+  static const btrc_play_status_t sPlayStatus[] = {
+    [PLAYSTATUS_STOPPED] = BTRC_PLAYSTATE_STOPPED,
+    [PLAYSTATUS_PLAYING] = BTRC_PLAYSTATE_PLAYING,
+    [PLAYSTATUS_PAUSED] = BTRC_PLAYSTATE_PAUSED,
+    [PLAYSTATUS_FWD_SEEK] = BTRC_PLAYSTATE_FWD_SEEK,
+    [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[] = {
+    [AVRCP_PLAYER_ATTRIBUTE_EQUALIZER] = BTRC_PLAYER_ATTR_EQUALIZER,
+    [AVRCP_PLAYER_ATTRIBUTE_REPEAT] = BTRC_PLAYER_ATTR_REPEAT,
+    [AVRCP_PLAYER_ATTRIBUTE_SHUFFLE] = BTRC_PLAYER_ATTR_SHUFFLE,
+    [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(enum BluetoothAvrcpStatus aIn, btrc_status_t& aOut)
+{
+  static const btrc_status_t sStatus[] = {
+    [AVRCP_STATUS_BAD_COMMAND] = BTRC_STS_BAD_CMD,
+    [AVRCP_STATUS_BAD_PARAMETER] = BTRC_STS_BAD_PARAM,
+    [AVRCP_STATUS_NOT_FOUND] = BTRC_STS_NOT_FOUND,
+    [AVRCP_STATUS_INTERNAL_ERROR] = BTRC_STS_INTERNAL_ERR,
+    [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[] = {
+    [AVRCP_EVENT_PLAY_STATUS_CHANGED] = BTRC_EVT_PLAY_STATUS_CHANGED,
+    [AVRCP_EVENT_TRACK_CHANGE] = BTRC_EVT_TRACK_CHANGE,
+    [AVRCP_EVENT_TRACK_REACHED_END] = BTRC_EVT_TRACK_REACHED_END,
+    [AVRCP_EVENT_TRACK_REACHED_START] = BTRC_EVT_TRACK_REACHED_START,
+    [AVRCP_EVENT_PLAY_POS_CHANGED] = BTRC_EVT_PLAY_POS_CHANGED,
+    [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(enum BluetoothAvrcpNotification aIn, btrc_notification_type_t& aOut)
+{
+  static const btrc_notification_type_t sNotificationType[] = {
+    [AVRCP_NTF_INTERIM] = BTRC_NOTIFICATION_TYPE_INTERIM,
+    [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;
+}
+
+#endif
+
+/* |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;
+}
+
+//
 // Result handling
 //
 
 template <typename Obj, typename Res>
 class BluetoothInterfaceRunnable0 : public nsRunnable
 {
 public:
   BluetoothInterfaceRunnable0(Obj* aObj, Res (Obj::*aMethod)())
@@ -131,80 +657,90 @@ typedef
 typedef
   BluetoothInterfaceRunnable3<BluetoothSocketResultHandler, void,
                               int, const nsString, int,
                               int, const nsAString_internal&, int>
   BluetoothSocketIntStringIntResultRunnable;
 
 typedef
   BluetoothInterfaceRunnable1<BluetoothSocketResultHandler, void,
-                              bt_status_t, bt_status_t>
+                              BluetoothStatus, BluetoothStatus>
   BluetoothSocketErrorRunnable;
 
 static nsresult
 DispatchBluetoothSocketResult(BluetoothSocketResultHandler* aRes,
                               void (BluetoothSocketResultHandler::*aMethod)(int),
-                              int aArg, bt_status_t aStatus)
+                              int aArg, BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
   nsRunnable* runnable;
 
-  if (aStatus == BT_STATUS_SUCCESS) {
+  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, bt_status_t aStatus)
+  int aArg1, const nsAString& aArg2, int aArg3, BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
   nsRunnable* runnable;
 
-  if (aStatus == BT_STATUS_SUCCESS) {
+  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(btsock_type_t aType,
-                                 const char* aServiceName,
-                                 const uint8_t* aServiceUuid,
-                                 int aChannel, int aFlags,
+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
 
-  bt_status_t status = mInterface->listen(aType, aServiceName, aServiceUuid,
-                                          aChannel, &fd, aFlags);
+  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, status);
+                                  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
@@ -237,36 +773,36 @@ public:
   : mFd(aFd)
   , mClientFd(-1)
   , mLen(0)
   { }
 
   virtual ~SocketMessageWatcher()
   { }
 
-  virtual void Proceed(bt_status_t aStatus) = 0;
+  virtual void Proceed(BluetoothStatus aStatus) = 0;
 
   void OnFileCanReadWithoutBlocking(int aFd) MOZ_OVERRIDE
   {
-    bt_status_t status;
+    BluetoothStatus status;
 
     switch (mLen) {
       case 0:
         status = RecvMsg1();
         break;
       case MSG1_SIZE:
         status = RecvMsg2();
         break;
       default:
         /* message-size error */
-        status = BT_STATUS_FAIL;
+        status = STATUS_FAIL;
         break;
     }
 
-    if (IsComplete() || status != BT_STATUS_SUCCESS) {
+    if (IsComplete() || status != STATUS_SUCCESS) {
       mWatcher.StopWatchingFileDescriptor();
       Proceed(status);
     }
   }
 
   void OnFileCanWriteWithoutBlocking(int aFd) MOZ_OVERRIDE
   { }
 
@@ -318,62 +854,62 @@ public:
   }
 
   int GetClientFd() const
   {
     return mClientFd;
   }
 
 private:
-  bt_status_t RecvMsg1()
+  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 BT_STATUS_FAIL;
+      return STATUS_FAIL;
     }
 
     mLen += res;
 
-    return BT_STATUS_SUCCESS;
+    return STATUS_SUCCESS;
   }
 
-  bt_status_t RecvMsg2()
+  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 BT_STATUS_FAIL;
+      return STATUS_FAIL;
     }
 
     mLen += res;
 
     if (msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE)) {
-      return BT_STATUS_FAIL;
+      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
@@ -381,17 +917,17 @@ private:
         if (mClientFd != -1) {
           TEMP_FAILURE_RETRY(close(mClientFd));
         }
         // retrieve sent client fd
         mClientFd = *(static_cast<int*>(CMSG_DATA(cmsgptr)));
       }
     }
 
-    return BT_STATUS_SUCCESS;
+    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]);
   }
@@ -402,21 +938,22 @@ private:
     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
   {
-    char str[18];
-    sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
-            mBuf[aOffset + 0], mBuf[aOffset + 1], mBuf[aOffset + 2],
-            mBuf[aOffset + 3], mBuf[aOffset + 4], mBuf[aOffset + 5]);
-    aBdAddress.AssignLiteral(str);
+    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];
 };
@@ -469,50 +1006,62 @@ private:
 class ConnectWatcher MOZ_FINAL : public SocketMessageWatcher
 {
 public:
   ConnectWatcher(int aFd, BluetoothSocketResultHandler* aRes)
   : SocketMessageWatcher(aFd)
   , mRes(aRes)
   { }
 
-  void Proceed(bt_status_t aStatus) MOZ_OVERRIDE
+  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 bt_bdaddr_t* aBdAddr,
-                                  btsock_type_t aType, const uint8_t* aUuid,
-                                  int aChannel, int aFlags,
+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
 
-  bt_status_t status = mInterface->connect(aBdAddr, aType, aUuid, aChannel,
-                                           &fd, aFlags);
+  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, status);
+    DispatchBluetoothSocketResult(aRes,
+                                  &BluetoothSocketResultHandler::Connect,
+                                  -1, EmptyString(), 0,
+                                  ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* 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
@@ -524,17 +1073,17 @@ public:
   AcceptWatcher(int aFd, BluetoothSocketResultHandler* aRes)
   : SocketMessageWatcher(aFd)
   , mRes(aRes)
   {
     /* not supplying a result handler leaks received file descriptor */
     MOZ_ASSERT(mRes);
   }
 
-  void Proceed(bt_status_t aStatus) MOZ_OVERRIDE
+  void Proceed(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     if (mRes) {
       DispatchBluetoothSocketResult(mRes,
                                     &BluetoothSocketResultHandler::Accept,
                                     GetClientFd(), GetBdAddress(),
                                     GetConnectionStatus(),
                                     aStatus);
     }
@@ -580,30 +1129,30 @@ struct interface_traits<BluetoothHandsfr
 };
 
 typedef
   BluetoothInterfaceRunnable0<BluetoothHandsfreeResultHandler, void>
   BluetoothHandsfreeResultRunnable;
 
 typedef
   BluetoothInterfaceRunnable1<BluetoothHandsfreeResultHandler, void,
-                              bt_status_t, bt_status_t>
+                              BluetoothStatus, BluetoothStatus>
   BluetoothHandsfreeErrorRunnable;
 
 static nsresult
 DispatchBluetoothHandsfreeResult(
   BluetoothHandsfreeResultHandler* aRes,
   void (BluetoothHandsfreeResultHandler::*aMethod)(),
-  bt_status_t aStatus)
+  BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
   nsRunnable* runnable;
 
-  if (aStatus == BT_STATUS_SUCCESS) {
+  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);
@@ -625,219 +1174,328 @@ void
 BluetoothHandsfreeInterface::Init(bthf_callbacks_t* aCallbacks,
                                   BluetoothHandsfreeResultHandler* aRes)
 {
   bt_status_t status = mInterface->init(aCallbacks);
 
   if (aRes) {
     DispatchBluetoothHandsfreeResult(aRes,
                                      &BluetoothHandsfreeResultHandler::Init,
-                                     status);
+                                     ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothHandsfreeInterface::Cleanup(BluetoothHandsfreeResultHandler* aRes)
 {
   mInterface->cleanup();
 
   if (aRes) {
     DispatchBluetoothHandsfreeResult(aRes,
                                      &BluetoothHandsfreeResultHandler::Cleanup,
-                                     BT_STATUS_SUCCESS);
+                                     STATUS_SUCCESS);
   }
 }
 
 /* Connect / Disconnect */
 
 void
-BluetoothHandsfreeInterface::Connect(bt_bdaddr_t* aBdAddr,
+BluetoothHandsfreeInterface::Connect(const nsAString& aBdAddr,
                                      BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->connect(aBdAddr);
+  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, status);
+      aRes, &BluetoothHandsfreeResultHandler::Connect,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothHandsfreeInterface::Disconnect(bt_bdaddr_t* aBdAddr,
-                                        BluetoothHandsfreeResultHandler* aRes)
+BluetoothHandsfreeInterface::Disconnect(
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->disconnect(aBdAddr);
+  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, status);
+      aRes, &BluetoothHandsfreeResultHandler::Disconnect,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothHandsfreeInterface::ConnectAudio(
-  bt_bdaddr_t* aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->connect_audio(aBdAddr);
+  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, status);
+      aRes, &BluetoothHandsfreeResultHandler::ConnectAudio,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothHandsfreeInterface::DisconnectAudio(
-  bt_bdaddr_t* aBdAddr, BluetoothHandsfreeResultHandler* aRes)
+  const nsAString& aBdAddr, BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->disconnect_audio(aBdAddr);
+  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, status);
+      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, status);
+      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, status);
+      aRes, &BluetoothHandsfreeResultHandler::StopVoiceRecognition,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Volume */
 
 void
 BluetoothHandsfreeInterface::VolumeControl(
-  bthf_volume_type_t aType, int aVolume, BluetoothHandsfreeResultHandler* aRes)
+  BluetoothHandsfreeVolumeType aType, int aVolume,
+  BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->volume_control(aType, aVolume);
+  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, status);
+      aRes, &BluetoothHandsfreeResultHandler::VolumeControl,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Device status */
 
 void
 BluetoothHandsfreeInterface::DeviceStatusNotification(
-  bthf_network_state_t aNtkState, bthf_service_type_t aSvcType, int aSignal,
+  BluetoothHandsfreeNetworkState aNtkState,
+  BluetoothHandsfreeServiceType aSvcType, int aSignal,
   int aBattChg, BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->device_status_notification(
-    aNtkState, aSvcType, aSignal, aBattChg);
+  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,
-      status);
+      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, status);
+      aRes, &BluetoothHandsfreeResultHandler::CopsResponse,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothHandsfreeInterface::CindResponse(
-  int aSvc, int aNumActive, int aNumHeld, bthf_call_state_t aCallSetupState,
-  int aSignal, int aRoam, int aBattChg, BluetoothHandsfreeResultHandler* aRes)
+  int aSvc, int aNumActive, int aNumHeld,
+  BluetoothHandsfreeCallState aCallSetupState,
+  int aSignal, int aRoam, int aBattChg,
+  BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->cind_response(aSvc, aNumActive, aNumHeld,
-                                                 aCallSetupState, aSignal,
-                                                 aRoam, aBattChg);
+  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, status);
+      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, status);
+      aRes, &BluetoothHandsfreeResultHandler::FormattedAtResponse,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothHandsfreeInterface::AtResponse(bthf_at_response_t aResponseCode,
-                                        int aErrorCode,
-                                        BluetoothHandsfreeResultHandler* aRes)
+BluetoothHandsfreeInterface::AtResponse(
+  BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
+  BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->at_response(aResponseCode, aErrorCode);
+  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, status);
+      aRes, &BluetoothHandsfreeResultHandler::AtResponse,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothHandsfreeInterface::ClccResponse(
-  int aIndex, bthf_call_direction_t aDir, bthf_call_state_t aState,
-  bthf_call_mode_t aMode, bthf_call_mpty_type_t aMpty, const char* aNumber,
-  bthf_call_addrtype_t aType, BluetoothHandsfreeResultHandler* aRes)
+  int aIndex,
+  BluetoothHandsfreeCallDirection aDir,
+  BluetoothHandsfreeCallState aState,
+  BluetoothHandsfreeCallMode aMode,
+  BluetoothHandsfreeCallMptyType aMpty,
+  const nsAString& aNumber,
+  BluetoothHandsfreeCallAddressType aType,
+  BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->clcc_response(aIndex, aDir, aState, aMode,
-                                                 aMpty, aNumber, aType);
+  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, status);
+      aRes, &BluetoothHandsfreeResultHandler::ClccResponse,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Phone State */
 
 void
 BluetoothHandsfreeInterface::PhoneStateChange(int aNumActive, int aNumHeld,
-  bthf_call_state_t aCallSetupState, const char* aNumber,
-  bthf_call_addrtype_t aType, BluetoothHandsfreeResultHandler* aRes)
+  BluetoothHandsfreeCallState aCallSetupState, const nsAString& aNumber,
+  BluetoothHandsfreeCallAddressType aType,
+  BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->phone_state_change(aNumActive, aNumHeld,
-                                                      aCallSetupState,
-                                                      aNumber, aType);
+  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, status);
+      aRes, &BluetoothHandsfreeResultHandler::PhoneStateChange,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 //
 // Bluetooth Advanced Audio Interface
 //
 
 template<>
@@ -852,30 +1510,30 @@ struct interface_traits<BluetoothA2dpInt
 };
 
 typedef
   BluetoothInterfaceRunnable0<BluetoothA2dpResultHandler, void>
   BluetoothA2dpResultRunnable;
 
 typedef
   BluetoothInterfaceRunnable1<BluetoothA2dpResultHandler, void,
-                              bt_status_t, bt_status_t>
+                              BluetoothStatus, BluetoothStatus>
   BluetoothA2dpErrorRunnable;
 
 static nsresult
 DispatchBluetoothA2dpResult(
   BluetoothA2dpResultHandler* aRes,
   void (BluetoothA2dpResultHandler::*aMethod)(),
-  bt_status_t aStatus)
+  BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
   nsRunnable* runnable;
 
-  if (aStatus == BT_STATUS_SUCCESS) {
+  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);
@@ -896,52 +1554,66 @@ BluetoothA2dpInterface::~BluetoothA2dpIn
 void
 BluetoothA2dpInterface::Init(btav_callbacks_t* aCallbacks,
                              BluetoothA2dpResultHandler* aRes)
 {
   bt_status_t status = mInterface->init(aCallbacks);
 
   if (aRes) {
     DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Init,
-                                status);
+                                ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothA2dpInterface::Cleanup(BluetoothA2dpResultHandler* aRes)
 {
   mInterface->cleanup();
 
   if (aRes) {
     DispatchBluetoothA2dpResult(aRes, &BluetoothA2dpResultHandler::Cleanup,
-                                BT_STATUS_SUCCESS);
+                                STATUS_SUCCESS);
   }
 }
 
 void
-BluetoothA2dpInterface::Connect(bt_bdaddr_t *aBdAddr,
+BluetoothA2dpInterface::Connect(const nsAString& aBdAddr,
                                 BluetoothA2dpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->connect(aBdAddr);
+  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,
-                                status);
+                                ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothA2dpInterface::Disconnect(bt_bdaddr_t *aBdAddr,
+BluetoothA2dpInterface::Disconnect(const nsAString& aBdAddr,
                                    BluetoothA2dpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->disconnect(aBdAddr);
+  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,
-                                status);
+                                ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 //
 // Bluetooth AVRCP Interface
 //
 
 #if ANDROID_VERSION >= 18
@@ -957,30 +1629,30 @@ struct interface_traits<BluetoothAvrcpIn
 };
 
 typedef
   BluetoothInterfaceRunnable0<BluetoothAvrcpResultHandler, void>
   BluetoothAvrcpResultRunnable;
 
 typedef
   BluetoothInterfaceRunnable1<BluetoothAvrcpResultHandler, void,
-                              bt_status_t, bt_status_t>
+                              BluetoothStatus, BluetoothStatus>
   BluetoothAvrcpErrorRunnable;
 
 static nsresult
 DispatchBluetoothAvrcpResult(
   BluetoothAvrcpResultHandler* aRes,
   void (BluetoothAvrcpResultHandler::*aMethod)(),
-  bt_status_t aStatus)
+  BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
   nsRunnable* runnable;
 
-  if (aStatus == BT_STATUS_SUCCESS) {
+  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);
@@ -1001,184 +1673,300 @@ BluetoothAvrcpInterface::~BluetoothAvrcp
 void
 BluetoothAvrcpInterface::Init(btrc_callbacks_t* aCallbacks,
                               BluetoothAvrcpResultHandler* aRes)
 {
   bt_status_t status = mInterface->init(aCallbacks);
 
   if (aRes) {
     DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Init,
-                                 status);
+                                 ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::Cleanup(BluetoothAvrcpResultHandler* aRes)
 {
   mInterface->cleanup();
 
   if (aRes) {
     DispatchBluetoothAvrcpResult(aRes, &BluetoothAvrcpResultHandler::Cleanup,
-                                 BT_STATUS_SUCCESS);
+                                 STATUS_SUCCESS);
   }
 }
 
 void
-BluetoothAvrcpInterface::GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
+BluetoothAvrcpInterface::GetPlayStatusRsp(ControlPlayStatus aPlayStatus,
                                           uint32_t aSongLen, uint32_t aSongPos,
                                           BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->get_play_status_rsp(aPlayStatus, aSongLen,
-                                                       aSongPos);
+  bt_status_t status;
+  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;
+  }
+
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::GetPlayStatusRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::ListPlayerAppAttrRsp(
-  int aNumAttr, btrc_player_attr_t* aPAttrs,
+  int aNumAttr, const BluetoothAvrcpPlayerAttribute* aPAttrs,
   BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->list_player_app_attr_rsp(aNumAttr, aPAttrs);
+  bt_status_t status;
+  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;
+  }
 
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::ListPlayerAppAttrRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::ListPlayerAppValueRsp(
   int aNumVal, uint8_t* aPVals, BluetoothAvrcpResultHandler* aRes)
 {
   bt_status_t status = mInterface->list_player_app_value_rsp(aNumVal, aPVals);
 
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::ListPlayerAppValueRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::GetPlayerAppValueRsp(
-  btrc_player_settings_t* aPVals, BluetoothAvrcpResultHandler* aRes)
+  uint8_t aNumAttrs, const uint8_t* aIds, const uint8_t* aValues,
+  BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->get_player_app_value_rsp(aPVals);
+  bt_status_t status;
+  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;
+  }
 
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::GetPlayerAppAttrTextRsp(
-  int aNumAttr, btrc_player_setting_text_t* aPAttrs,
+  int aNumAttr, const uint8_t* aIds, const char** aTexts,
   BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->get_player_app_attr_text_rsp(aNumAttr,
-                                                                aPAttrs);
+  bt_status_t status;
+  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;
+  }
+
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppAttrTextRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::GetPlayerAppValueTextRsp(
-  int aNumVal, btrc_player_setting_text_t* aPVals,
+  int aNumVal, const uint8_t* aIds, const char** aTexts,
   BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->get_player_app_value_text_rsp(aNumVal,
-                                                                 aPVals);
+  bt_status_t status;
+  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;
+  }
+
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::GetPlayerAppValueTextRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::GetElementAttrRsp(
-  uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs,
+  uint8_t aNumAttr, const BluetoothAvrcpElementAttribute* aAttrs,
   BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->get_element_attr_rsp(aNumAttr, aPAttrs);
+  bt_status_t status;
+  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;
+  }
 
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::GetElementAttrRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::SetPlayerAppValueRsp(
-  btrc_status_t aRspStatus, BluetoothAvrcpResultHandler* aRes)
+  BluetoothAvrcpStatus aRspStatus, BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->set_player_app_value_rsp(aRspStatus);
+  bt_status_t status;
+  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;
+  }
 
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp, status);
+      aRes, &BluetoothAvrcpResultHandler::SetPlayerAppValueRsp,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothAvrcpInterface::RegisterNotificationRsp(
-  btrc_event_id_t aEventId, btrc_notification_type_t aType,
-  btrc_register_notification_t* aPParam, BluetoothAvrcpResultHandler* aRes)
+  BluetoothAvrcpEvent aEvent, BluetoothAvrcpNotification aType,
+  const BluetoothAvrcpNotificationParam& aParam,
+  BluetoothAvrcpResultHandler* aRes)
 {
-  bt_status_t status = mInterface->register_notification_rsp(aEventId, aType,
-                                                             aPParam);
+  nsresult rv;
+  bt_status_t status;
+  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;
+  }
+
   if (aRes) {
     DispatchBluetoothAvrcpResult(
-      aRes, &BluetoothAvrcpResultHandler::RegisterNotificationRsp, status);
+      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, status);
+      aRes, &BluetoothAvrcpResultHandler::SetVolume,
+      ConvertDefault(status, STATUS_FAIL));
   }
 }
 #endif
 
 //
 // Bluetooth Core Interface
 //
 
 typedef
   BluetoothInterfaceRunnable0<BluetoothResultHandler, void>
   BluetoothResultRunnable;
 
 typedef
-  BluetoothInterfaceRunnable1<BluetoothResultHandler, void, int, int>
+  BluetoothInterfaceRunnable1<BluetoothResultHandler, void,
+                              BluetoothStatus, BluetoothStatus>
   BluetoothErrorRunnable;
 
 static nsresult
 DispatchBluetoothResult(BluetoothResultHandler* aRes,
                         void (BluetoothResultHandler::*aMethod)(),
-                        int aStatus)
+                        BluetoothStatus aStatus)
 {
   MOZ_ASSERT(aRes);
 
   nsRunnable* runnable;
 
-  if (aStatus == BT_STATUS_SUCCESS) {
+  if (aStatus == STATUS_SUCCESS) {
     runnable = new BluetoothResultRunnable(aRes, aMethod);
   } else {
     runnable = new
       BluetoothErrorRunnable(aRes, &BluetoothResultHandler::OnError, aStatus);
   }
   nsresult rv = NS_DispatchToMainThread(runnable);
   if (NS_FAILED(rv)) {
     BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
@@ -1259,286 +2047,405 @@ BluetoothInterface::~BluetoothInterface(
 
 void
 BluetoothInterface::Init(bt_callbacks_t* aCallbacks,
                          BluetoothResultHandler* aRes)
 {
   int status = mInterface->init(aCallbacks);
 
   if (aRes) {
-    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Init, status);
+    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Init,
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothInterface::Cleanup(BluetoothResultHandler* aRes)
 {
   mInterface->cleanup();
 
   if (aRes) {
     DispatchBluetoothResult(aRes, &BluetoothResultHandler::Cleanup,
-                            BT_STATUS_SUCCESS);
+                            STATUS_SUCCESS);
   }
 }
 
 void
 BluetoothInterface::Enable(BluetoothResultHandler* aRes)
 {
   int status = mInterface->enable();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Enable, status);
+    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Enable,
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothInterface::Disable(BluetoothResultHandler* aRes)
 {
   int status = mInterface->disable();
 
   if (aRes) {
-    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Disable, status);
+    DispatchBluetoothResult(aRes, &BluetoothResultHandler::Disable,
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Adapter Properties */
 
 void
 BluetoothInterface::GetAdapterProperties(BluetoothResultHandler* aRes)
 {
   int status = mInterface->get_adapter_properties();
 
   if (aRes) {
     DispatchBluetoothResult(aRes,
                             &BluetoothResultHandler::GetAdapterProperties,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::GetAdapterProperty(bt_property_type_t aType,
+BluetoothInterface::GetAdapterProperty(const nsAString& aName,
                                        BluetoothResultHandler* aRes)
 {
-  int status = mInterface->get_adapter_property(aType);
+  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::GetAdapterProperty,
-                            status);
+                            &BluetoothResultHandler::GetAdapterProperties,
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::SetAdapterProperty(const bt_property_t* aProperty,
+BluetoothInterface::SetAdapterProperty(const BluetoothNamedValue& aProperty,
                                        BluetoothResultHandler* aRes)
 {
-  int status = mInterface->set_adapter_property(aProperty);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Remote Device Properties */
 
 void
-BluetoothInterface::GetRemoteDeviceProperties(bt_bdaddr_t *aRemoteAddr,
+BluetoothInterface::GetRemoteDeviceProperties(const nsAString& aRemoteAddr,
                                               BluetoothResultHandler* aRes)
 {
-  int status = mInterface->get_remote_device_properties(aRemoteAddr);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::GetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
-                                            bt_property_type_t aType,
+BluetoothInterface::GetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+                                            const nsAString& aName,
                                             BluetoothResultHandler* aRes)
 {
-  int status = mInterface->get_remote_device_property(aRemoteAddr, aType);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::SetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
-                                            const bt_property_t* aProperty,
+BluetoothInterface::SetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+                                            const BluetoothNamedValue& aProperty,
                                             BluetoothResultHandler* aRes)
 {
-  int status = mInterface->set_remote_device_property(aRemoteAddr, aProperty);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Remote Services */
 
 void
-BluetoothInterface::GetRemoteServiceRecord(bt_bdaddr_t* aRemoteAddr,
-                                           bt_uuid_t* aUuid,
+BluetoothInterface::GetRemoteServiceRecord(const nsAString& aRemoteAddr,
+                                           const uint8_t aUuid[16],
                                            BluetoothResultHandler* aRes)
 {
-  int status = mInterface->get_remote_service_record(aRemoteAddr, aUuid);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::GetRemoteServices(bt_bdaddr_t* aRemoteAddr,
+BluetoothInterface::GetRemoteServices(const nsAString& aRemoteAddr,
                                       BluetoothResultHandler* aRes)
 {
-  int status = mInterface->get_remote_services(aRemoteAddr);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Discovery */
 
 void
 BluetoothInterface::StartDiscovery(BluetoothResultHandler* aRes)
 {
   int status = mInterface->start_discovery();
 
   if (aRes) {
     DispatchBluetoothResult(aRes,
                             &BluetoothResultHandler::StartDiscovery,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothInterface::CancelDiscovery(BluetoothResultHandler* aRes)
 {
   int status = mInterface->cancel_discovery();
 
   if (aRes) {
     DispatchBluetoothResult(aRes,
                             &BluetoothResultHandler::CancelDiscovery,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Bonds */
 
 void
-BluetoothInterface::CreateBond(const bt_bdaddr_t* aBdAddr,
+BluetoothInterface::CreateBond(const nsAString& aBdAddr,
                                BluetoothResultHandler* aRes)
 {
-  int status = mInterface->create_bond(aBdAddr);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::RemoveBond(const bt_bdaddr_t* aBdAddr,
+BluetoothInterface::RemoveBond(const nsAString& aBdAddr,
                                BluetoothResultHandler* aRes)
 {
-  int status = mInterface->remove_bond(aBdAddr);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::CancelBond(const bt_bdaddr_t* aBdAddr,
+BluetoothInterface::CancelBond(const nsAString& aBdAddr,
                                BluetoothResultHandler* aRes)
 {
-  int status = mInterface->cancel_bond(aBdAddr);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Authentication */
 
 void
-BluetoothInterface::PinReply(const bt_bdaddr_t* aBdAddr, uint8_t aAccept,
-                             uint8_t aPinLen, bt_pin_code_t* aPinCode,
+BluetoothInterface::PinReply(const nsAString& aBdAddr, bool aAccept,
+                             const nsAString& aPinCode,
                              BluetoothResultHandler* aRes)
 {
-  int status = mInterface->pin_reply(aBdAddr, aAccept, aPinLen, aPinCode);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
-BluetoothInterface::SspReply(const bt_bdaddr_t* aBdAddr,
-                             bt_ssp_variant_t aVariant,
-                             uint8_t aAccept, uint32_t aPasskey,
+BluetoothInterface::SspReply(const nsAString& aBdAddr,
+                             const nsAString& aVariant,
+                             bool aAccept, uint32_t aPasskey,
                              BluetoothResultHandler* aRes)
 {
-  int status = mInterface->ssp_reply(aBdAddr, aVariant, aAccept, aPasskey);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* DUT Mode */
 
 void
-BluetoothInterface::DutModeConfigure(uint8_t aEnable,
+BluetoothInterface::DutModeConfigure(bool aEnable,
                                      BluetoothResultHandler* aRes)
 {
-  int status = mInterface->dut_mode_configure(aEnable);
+  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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 void
 BluetoothInterface::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,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* LE Mode */
 
 void
 BluetoothInterface::LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
                                BluetoothResultHandler* aRes)
@@ -1547,17 +2454,17 @@ BluetoothInterface::LeTestMode(uint16_t 
   int status = mInterface->le_test_mode(aOpcode, aBuf, aLen);
 #else
   int status = BT_STATUS_UNSUPPORTED;
 #endif
 
   if (aRes) {
     DispatchBluetoothResult(aRes,
                             &BluetoothResultHandler::LeTestMode,
-                            status);
+                            ConvertDefault(status, STATUS_FAIL));
   }
 }
 
 /* Profile Interfaces */
 
 template <class T>
 T*
 BluetoothInterface::GetProfileInterface()
--- a/dom/bluetooth/bluedroid/BluetoothInterface.h
+++ b/dom/bluetooth/bluedroid/BluetoothInterface.h
@@ -10,57 +10,62 @@
 #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/dom/bluetooth/BluetoothTypes.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothInterface;
 
 //
 // Socket Interface
 //
 
 class BluetoothSocketResultHandler
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothSocketResultHandler)
 
   virtual ~BluetoothSocketResultHandler() { }
 
-  virtual void OnError(bt_status_t aStatus)
+  virtual void OnError(BluetoothStatus aStatus)
   {
-    BT_WARNING("received error code %d", (int)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:
   friend class BluetoothInterface;
 
   // Init and Cleanup is handled by BluetoothInterface
 
-  void Listen(btsock_type_t aType,
-              const char* aServiceName, const uint8_t* aServiceUuid,
-              int aChannel, int aFlags, BluetoothSocketResultHandler* aRes);
+  void Listen(BluetoothSocketType aType,
+              const nsAString& aServiceName,
+              const uint8_t aServiceUuid[16],
+              int aChannel, bool aEncrypt, bool aAuth,
+              BluetoothSocketResultHandler* aRes);
 
-  void Connect(const bt_bdaddr_t* aBdAddr, btsock_type_t aType,
-               const uint8_t* aUuid, int aChannel, int aFlags,
+  void Connect(const nsAString& aBdAddr,
+               BluetoothSocketType aType,
+               const uint8_t aUuid[16],
+               int aChannel, bool aEncrypt, bool aAuth,
                BluetoothSocketResultHandler* aRes);
 
   void Accept(int aFd, BluetoothSocketResultHandler* aRes);
 
 protected:
   BluetoothSocketInterface(const btsock_interface_t* aInterface);
   ~BluetoothSocketInterface();
 
@@ -74,17 +79,17 @@ private:
 
 class BluetoothHandsfreeResultHandler
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothHandsfreeResultHandler)
 
   virtual ~BluetoothHandsfreeResultHandler() { }
 
-  virtual void OnError(bt_status_t aStatus)
+  virtual void OnError(BluetoothStatus aStatus)
   {
     BT_WARNING("Received error code %d", (int)aStatus);
   }
 
   virtual void Init() { }
   virtual void Cleanup() { }
 
   virtual void Connect() { }
@@ -113,65 +118,68 @@ public:
   friend class BluetoothInterface;
 
   void Init(bthf_callbacks_t* aCallbacks,
             BluetoothHandsfreeResultHandler* aRes);
   void Cleanup(BluetoothHandsfreeResultHandler* aRes);
 
   /* Connect / Disconnect */
 
-  void Connect(bt_bdaddr_t* aBdAddr,
+  void Connect(const nsAString& aBdAddr,
                BluetoothHandsfreeResultHandler* aRes);
-  void Disconnect(bt_bdaddr_t* aBdAddr,
+  void Disconnect(const nsAString& aBdAddr,
                   BluetoothHandsfreeResultHandler* aRes);
-  void ConnectAudio(bt_bdaddr_t* aBdAddr,
+  void ConnectAudio(const nsAString& aBdAddr,
                     BluetoothHandsfreeResultHandler* aRes);
-  void DisconnectAudio(bt_bdaddr_t* aBdAddr,
+  void DisconnectAudio(const nsAString& aBdAddr,
                        BluetoothHandsfreeResultHandler* aRes);
 
   /* Voice Recognition */
 
   void StartVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
   void StopVoiceRecognition(BluetoothHandsfreeResultHandler* aRes);
 
   /* Volume */
 
-  void VolumeControl(bthf_volume_type_t aType, int aVolume,
+  void VolumeControl(BluetoothHandsfreeVolumeType aType, int aVolume,
                      BluetoothHandsfreeResultHandler* aRes);
 
   /* Device status */
 
-  void DeviceStatusNotification(bthf_network_state_t aNtkState,
-                                bthf_service_type_t aSvcType,
+  void DeviceStatusNotification(BluetoothHandsfreeNetworkState aNtkState,
+                                BluetoothHandsfreeServiceType aSvcType,
                                 int aSignal, int aBattChg,
                                 BluetoothHandsfreeResultHandler* aRes);
 
   /* Responses */
 
   void CopsResponse(const char* aCops,
                     BluetoothHandsfreeResultHandler* aRes);
   void CindResponse(int aSvc, int aNumActive, int aNumHeld,
-                    bthf_call_state_t aCallSetupState, int aSignal,
+                    BluetoothHandsfreeCallState aCallSetupState, int aSignal,
                     int aRoam, int aBattChg,
                     BluetoothHandsfreeResultHandler* aRes);
   void FormattedAtResponse(const char* aRsp,
                            BluetoothHandsfreeResultHandler* aRes);
-  void AtResponse(bthf_at_response_t aResponseCode, int aErrorCode,
+  void AtResponse(BluetoothHandsfreeAtResponse aResponseCode, int aErrorCode,
                   BluetoothHandsfreeResultHandler* aRes);
-  void ClccResponse(int aIndex, bthf_call_direction_t aDir,
-                    bthf_call_state_t aState, bthf_call_mode_t aMode,
-                    bthf_call_mpty_type_t aMpty, const char* aNumber,
-                    bthf_call_addrtype_t aType,
+  void ClccResponse(int aIndex, BluetoothHandsfreeCallDirection aDir,
+                    BluetoothHandsfreeCallState aState,
+                    BluetoothHandsfreeCallMode aMode,
+                    BluetoothHandsfreeCallMptyType aMpty,
+                    const nsAString& aNumber,
+                    BluetoothHandsfreeCallAddressType aType,
                     BluetoothHandsfreeResultHandler* aRes);
 
   /* Phone State */
 
   void PhoneStateChange(int aNumActive, int aNumHeld,
-                        bthf_call_state_t aCallSetupState,
-                        const char* aNumber, bthf_call_addrtype_t aType,
+                        BluetoothHandsfreeCallState aCallSetupState,
+                        const nsAString& aNumber,
+                        BluetoothHandsfreeCallAddressType aType,
                         BluetoothHandsfreeResultHandler* aRes);
 
 protected:
   BluetoothHandsfreeInterface(const bthf_interface_t* aInterface);
   ~BluetoothHandsfreeInterface();
 
 private:
   const bthf_interface_t* mInterface;
@@ -183,19 +191,19 @@ private:
 
 class BluetoothA2dpResultHandler
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothA2dpResultHandler)
 
   virtual ~BluetoothA2dpResultHandler() { }
 
-  virtual void OnError(bt_status_t aStatus)
+  virtual void OnError(BluetoothStatus aStatus)
   {
-    BT_WARNING("received error code %d", (int)aStatus);
+    BT_WARNING("Received error code %d", (int)aStatus);
   }
 
   virtual void Init() { }
   virtual void Cleanup() { }
   virtual void Connect() { }
   virtual void Disconnect() { }
 };
 
@@ -203,19 +211,19 @@ class BluetoothA2dpInterface
 {
 public:
   friend class BluetoothInterface;
 
   void Init(btav_callbacks_t *aCallbacks,
             BluetoothA2dpResultHandler* aRes);
   void Cleanup(BluetoothA2dpResultHandler* aRes);
 
-  void Connect(bt_bdaddr_t *aBdAddr,
+  void Connect(const nsAString& aBdAddr,
                BluetoothA2dpResultHandler* aRes);
-  void Disconnect(bt_bdaddr_t *aBdAddr,
+  void Disconnect(const nsAString& aBdAddr,
                   BluetoothA2dpResultHandler* aRes);
 
 protected:
   BluetoothA2dpInterface(const btav_interface_t* aInterface);
   ~BluetoothA2dpInterface();
 
 private:
   const btav_interface_t* mInterface;
@@ -227,19 +235,19 @@ private:
 
 class BluetoothAvrcpResultHandler
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothAvrcpResultHandler)
 
   virtual ~BluetoothAvrcpResultHandler() { }
 
-  virtual void OnError(bt_status_t aStatus)
+  virtual void OnError(BluetoothStatus aStatus)
   {
-    BT_WARNING("received error code %d", (int)aStatus);
+    BT_WARNING("Received error code %d", (int)aStatus);
   }
 
   virtual void Init() { }
   virtual void Cleanup() { }
 
   virtual void GetPlayStatusRsp() { }
 
   virtual void ListPlayerAppAttrRsp() { }
@@ -263,43 +271,49 @@ class BluetoothAvrcpInterface
 #if ANDROID_VERSION >= 18
 public:
   friend class BluetoothInterface;
 
   void Init(btrc_callbacks_t* aCallbacks,
             BluetoothAvrcpResultHandler* aRes);
   void Cleanup(BluetoothAvrcpResultHandler* aRes);
 
-  void GetPlayStatusRsp(btrc_play_status_t aPlayStatus,
+  void GetPlayStatusRsp(ControlPlayStatus aPlayStatus,
                         uint32_t aSongLen, uint32_t aSongPos,
                         BluetoothAvrcpResultHandler* aRes);
 
-  void ListPlayerAppAttrRsp(int aNumAttr, btrc_player_attr_t* aPAttrs,
+  void ListPlayerAppAttrRsp(int aNumAttr,
+                            const BluetoothAvrcpPlayerAttribute* aPAttrs,
                             BluetoothAvrcpResultHandler* aRes);
   void ListPlayerAppValueRsp(int aNumVal, uint8_t* aPVals,
                              BluetoothAvrcpResultHandler* aRes);
 
-  void GetPlayerAppValueRsp(btrc_player_settings_t* aPVals,
+  /* 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,
-                               btrc_player_setting_text_t* aPAttrs,
+                               const uint8_t* aIds, const char** aTexts,
                                BluetoothAvrcpResultHandler* aRes);
+  /* TODO: redesign this interface once we actually use it */
   void GetPlayerAppValueTextRsp(int aNumVal,
-                                btrc_player_setting_text_t* aPVals,
+                                const uint8_t* aIds, const char** aTexts,
                                 BluetoothAvrcpResultHandler* aRes);
 
-  void GetElementAttrRsp(uint8_t aNumAttr, btrc_element_attr_val_t* aPAttrs,
+  void GetElementAttrRsp(uint8_t aNumAttr,
+                         const BluetoothAvrcpElementAttribute* aAttr,
                          BluetoothAvrcpResultHandler* aRes);
 
-  void SetPlayerAppValueRsp(btrc_status_t aRspStatus,
+  void SetPlayerAppValueRsp(BluetoothAvrcpStatus aRspStatus,
                             BluetoothAvrcpResultHandler* aRes);
 
-  void RegisterNotificationRsp(btrc_event_id_t aEventId,
-                               btrc_notification_type_t aType,
-                               btrc_register_notification_t* aPParam,
+  void RegisterNotificationRsp(BluetoothAvrcpEvent aEvent,
+                               BluetoothAvrcpNotification aType,
+                               const BluetoothAvrcpNotificationParam& aParam,
                                BluetoothAvrcpResultHandler* aRes);
 
   void SetVolume(uint8_t aVolume, BluetoothAvrcpResultHandler* aRes);
 
 protected:
   BluetoothAvrcpInterface(const btrc_interface_t* aInterface);
   ~BluetoothAvrcpInterface();
 
@@ -314,19 +328,19 @@ private:
 
 class BluetoothResultHandler
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothResultHandler)
 
   virtual ~BluetoothResultHandler() { }
 
-  virtual void OnError(int aStatus)
+  virtual void OnError(BluetoothStatus aStatus)
   {
-    BT_LOGR("received error code %d", aStatus);
+    BT_LOGR("Received error code %d", aStatus);
   }
 
   virtual void Init() { }
   virtual void Cleanup() { }
   virtual void Enable() { }
   virtual void Disable() { }
 
   virtual void GetAdapterProperties() { }
@@ -366,64 +380,64 @@ public:
 
   void Enable(BluetoothResultHandler* aRes);
   void Disable(BluetoothResultHandler* aRes);
 
 
   /* Adapter Properties */
 
   void GetAdapterProperties(BluetoothResultHandler* aRes);
-  void GetAdapterProperty(bt_property_type_t aType,
+  void GetAdapterProperty(const nsAString& aName,
                           BluetoothResultHandler* aRes);
-  void SetAdapterProperty(const bt_property_t* aProperty,
+  void SetAdapterProperty(const BluetoothNamedValue& aProperty,
                           BluetoothResultHandler* aRes);
 
   /* Remote Device Properties */
 
-  void GetRemoteDeviceProperties(bt_bdaddr_t *aRemoteAddr,
+  void GetRemoteDeviceProperties(const nsAString& aRemoteAddr,
                                  BluetoothResultHandler* aRes);
-  void GetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
-                               bt_property_type_t aType,
+  void GetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+                               const nsAString& aName,
                                BluetoothResultHandler* aRes);
-  void SetRemoteDeviceProperty(bt_bdaddr_t* aRemoteAddr,
-                               const bt_property_t* aProperty,
+  void SetRemoteDeviceProperty(const nsAString& aRemoteAddr,
+                               const BluetoothNamedValue& aProperty,
                                BluetoothResultHandler* aRes);
 
   /* Remote Services */
 
-  void GetRemoteServiceRecord(bt_bdaddr_t* aRemoteAddr,
-                              bt_uuid_t* aUuid,
+  void GetRemoteServiceRecord(const nsAString& aRemoteAddr,
+                              const uint8_t aUuid[16],
                               BluetoothResultHandler* aRes);
-  void GetRemoteServices(bt_bdaddr_t* aRemoteAddr,
+  void GetRemoteServices(const nsAString& aRemoteAddr,
                          BluetoothResultHandler* aRes);
 
   /* Discovery */
 
   void StartDiscovery(BluetoothResultHandler* aRes);
   void CancelDiscovery(BluetoothResultHandler* aRes);
 
   /* Bonds */
 
-  void CreateBond(const bt_bdaddr_t* aBdAddr, BluetoothResultHandler* aRes);
-  void RemoveBond(const bt_bdaddr_t* aBdAddr, BluetoothResultHandler* aRes);
-  void CancelBond(const bt_bdaddr_t* aBdAddr, BluetoothResultHandler* aRes);
+  void CreateBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
+  void RemoveBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
+  void CancelBond(const nsAString& aBdAddr, BluetoothResultHandler* aRes);
 
   /* Authentication */
 
-  void PinReply(const bt_bdaddr_t* aBdAddr, uint8_t aAccept,
-                uint8_t aPinLen, bt_pin_code_t* aPinCode,
+  void PinReply(const nsAString& aBdAddr, bool aAccept,
+                const nsAString& aPinCode,
                 BluetoothResultHandler* aRes);
 
-  void SspReply(const bt_bdaddr_t* aBdAddr, bt_ssp_variant_t aVariant,
-                uint8_t aAccept, uint32_t aPasskey,
+  void SspReply(const nsAString& aBdAddr, const nsAString& aVariant,
+                bool aAccept, uint32_t aPasskey,
                 BluetoothResultHandler* aRes);
 
   /* DUT Mode */
 
-  void DutModeConfigure(uint8_t aEnable, BluetoothResultHandler* aRes);
+  void DutModeConfigure(bool aEnable, BluetoothResultHandler* aRes);
   void DutModeSend(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
                    BluetoothResultHandler* aRes);
 
   /* LE Mode */
 
   void LeTestMode(uint16_t aOpcode, uint8_t* aBuf, uint8_t aLen,
                   BluetoothResultHandler* aRes);
 
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -103,17 +103,17 @@ private:
 
 class SetupAfterEnabledTask MOZ_FINAL : public nsRunnable
 {
 public:
   class SetAdapterPropertyResultHandler MOZ_FINAL
   : public BluetoothResultHandler
   {
   public:
-    void OnError(int aStatus) MOZ_OVERRIDE
+    void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
     {
       BT_LOGR("Fail to set: BT_SCAN_MODE_CONNECTABLE");
     }
   };
 
   NS_IMETHOD
   Run()
   {
@@ -122,25 +122,20 @@ public:
     // Bluetooth just enabled, clear profile controllers and runnable arrays.
     sControllerArray.Clear();
     sBondingRunnableArray.Clear();
     sGetDeviceRunnableArray.Clear();
     sSetPropertyRunnableArray.Clear();
     sUnbondingRunnableArray.Clear();
 
     // Bluetooth scan mode is NONE by default
-    bt_scan_mode_t mode = BT_SCAN_MODE_CONNECTABLE;
-    bt_property_t prop;
-    prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
-    prop.val = (void*)&mode;
-    prop.len = sizeof(mode);
-
     NS_ENSURE_TRUE(sBtInterface, NS_ERROR_FAILURE);
-    sBtInterface->SetAdapterProperty(&prop,
-                                     new SetAdapterPropertyResultHandler());
+    sBtInterface->SetAdapterProperty(
+      BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), true),
+      new SetAdapterPropertyResultHandler());
 
     // Try to fire event 'AdapterAdded' to fit the original behaviour when
     // we used BlueZ as backend.
     BluetoothService* bs = BluetoothService::Get();
     NS_ENSURE_TRUE(bs, NS_ERROR_FAILURE);
 
     bs->AdapterAddedReceived();
     bs->TryFiringAdapterAdded();
@@ -845,17 +840,17 @@ EnsureBluetoothHalLoad()
   NS_ENSURE_TRUE(sBtInterface, false);
 
   return true;
 }
 
 class EnableResultHandler MOZ_FINAL : public BluetoothResultHandler
 {
 public:
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BT_LOGR("BluetoothInterface::Enable failed: %d", aStatus);
 
     nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(false);
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       BT_WARNING("Failed to dispatch to main thread!");
@@ -918,17 +913,17 @@ public:
     nsRefPtr<ProfileInitResultHandler> res =
       new ProfileInitResultHandler(MOZ_ARRAY_LENGTH(sInitManager));
 
     for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sInitManager); ++i) {
       sInitManager[i](res);
     }
   }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BT_LOGR("BluetoothInterface::Init failed: %d", aStatus);
 
     sBtInterface = nullptr;
 
     nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(false);
@@ -960,17 +955,17 @@ StartGonkBluetooth()
   sBtInterface->Init(&sBluetoothCallbacks, new InitResultHandler());
 
   return NS_OK;
 }
 
 class DisableResultHandler MOZ_FINAL : public BluetoothResultHandler
 {
 public:
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BT_LOGR("BluetoothInterface::Disable failed: %d", aStatus);
 
     nsRefPtr<nsRunnable> runnable = new BluetoothService::ToggleBtAck(true);
     if (NS_FAILED(NS_DispatchToMainThread(runnable))) {
       BT_WARNING("Failed to dispatch to main thread!");
@@ -999,36 +994,36 @@ StopGonkBluetooth()
 
   sBtInterface->Disable(new DisableResultHandler());
 
   return NS_OK;
 }
 
 static void
 ReplyStatusError(BluetoothReplyRunnable* aBluetoothReplyRunnable,
-                 int aStatusCode, const nsAString& aCustomMsg)
+                 BluetoothStatus aStatusCode, const nsAString& aCustomMsg)
 {
   MOZ_ASSERT(aBluetoothReplyRunnable, "Reply runnable is nullptr");
 
   BT_LOGR("error code(%d)", aStatusCode);
 
   nsAutoString replyError;
   replyError.Assign(aCustomMsg);
 
-  if (aStatusCode == BT_STATUS_BUSY) {
+  if (aStatusCode == STATUS_BUSY) {
     replyError.AppendLiteral(":BT_STATUS_BUSY");
-  } else if (aStatusCode == BT_STATUS_NOT_READY) {
+  } else if (aStatusCode == STATUS_NOT_READY) {
     replyError.AppendLiteral(":BT_STATUS_NOT_READY");
-  } else if (aStatusCode == BT_STATUS_DONE) {
+  } else if (aStatusCode == STATUS_DONE) {
     replyError.AppendLiteral(":BT_STATUS_DONE");
-  } else if (aStatusCode == BT_STATUS_AUTH_FAILURE) {
+  } else if (aStatusCode == STATUS_AUTH_FAILURE) {
     replyError.AppendLiteral(":BT_STATUS_AUTH_FAILURE");
-  } else if (aStatusCode == BT_STATUS_RMT_DEV_DOWN) {
+  } else if (aStatusCode == STATUS_RMT_DEV_DOWN) {
     replyError.AppendLiteral(":BT_STATUS_RMT_DEV_DOWN");
-  } else if (aStatusCode == BT_STATUS_FAIL) {
+  } else if (aStatusCode == STATUS_FAIL) {
     replyError.AppendLiteral(":BT_STATUS_FAIL");
   }
 
   DispatchBluetoothReply(aBluetoothReplyRunnable, BluetoothValue(true),
                          replyError);
 }
 
 /**
@@ -1118,17 +1113,17 @@ BluetoothServiceBluedroid::GetDefaultAda
 class GetRemoteDevicePropertiesResultHandler MOZ_FINAL
 : public BluetoothResultHandler
 {
 public:
   GetRemoteDevicePropertiesResultHandler(const nsAString& aDeviceAddress)
   : mDeviceAddress(aDeviceAddress)
   { }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BT_WARNING("GetRemoteDeviceProperties(%s) failed: %d",
                mDeviceAddress.get(), aStatus);
 
     /* dispatch result after final pending operation */
     if (--sRequestedDeviceCountArray[0] == 0) {
@@ -1178,20 +1173,17 @@ BluetoothServiceBluedroid::GetConnectedD
     return NS_OK;
   }
 
   sRequestedDeviceCountArray.AppendElement(requestedDeviceCount);
   sGetDeviceRunnableArray.AppendElement(aRunnable);
 
   for (int i = 0; i < requestedDeviceCount; i++) {
     // Retrieve all properties of devices
-    bt_bdaddr_t addressType;
-    StringToBdAddressType(deviceAddresses[i], &addressType);
-
-    sBtInterface->GetRemoteDeviceProperties(&addressType,
+    sBtInterface->GetRemoteDeviceProperties(deviceAddresses[i],
       new GetRemoteDevicePropertiesResultHandler(deviceAddresses[i]));
   }
 
   return NS_OK;
 }
 
 nsresult
 BluetoothServiceBluedroid::GetPairedDevicePropertiesInternal(
@@ -1208,20 +1200,17 @@ BluetoothServiceBluedroid::GetPairedDevi
     return NS_OK;
   }
 
   sRequestedDeviceCountArray.AppendElement(requestedDeviceCount);
   sGetDeviceRunnableArray.AppendElement(aRunnable);
 
   for (int i = 0; i < requestedDeviceCount; i++) {
     // Retrieve all properties of devices
-    bt_bdaddr_t addressType;
-    StringToBdAddressType(aDeviceAddress[i], &addressType);
-
-    sBtInterface->GetRemoteDeviceProperties(&addressType,
+    sBtInterface->GetRemoteDeviceProperties(aDeviceAddress[i],
       new GetRemoteDevicePropertiesResultHandler(aDeviceAddress[i]));
   }
 
   return NS_OK;
 }
 
 class StartDiscoveryResultHandler MOZ_FINAL : public BluetoothResultHandler
 {
@@ -1231,17 +1220,17 @@ public:
   { }
 
   void StartDiscovery() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     DispatchBluetoothReply(mRunnable, true, EmptyString());
   }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("StartDiscovery"));
   }
 
 private:
   BluetoothReplyRunnable* mRunnable;
 };
@@ -1266,17 +1255,17 @@ public:
   { }
 
   void CancelDiscovery() MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     DispatchBluetoothReply(mRunnable, true, EmptyString());
   }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("StopDiscovery"));
   }
 
 private:
   BluetoothReplyRunnable* mRunnable;
 };
@@ -1295,74 +1284,36 @@ BluetoothServiceBluedroid::StopDiscovery
 
 class SetAdapterPropertyResultHandler MOZ_FINAL : public BluetoothResultHandler
 {
 public:
   SetAdapterPropertyResultHandler(BluetoothReplyRunnable* aRunnable)
   : mRunnable(aRunnable)
   { }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("SetProperty"));
   }
 private:
   BluetoothReplyRunnable* mRunnable;
 };
 
 nsresult
 BluetoothServiceBluedroid::SetProperty(BluetoothObjectType aType,
                                        const BluetoothNamedValue& aValue,
                                        BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
-
   ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
 
-  const nsString propName = aValue.name();
-  bt_property_t prop;
-  bt_scan_mode_t scanMode;
-  nsCString str;
-
-  // For Bluedroid, it's necessary to check property name for SetProperty
-  if (propName.EqualsLiteral("Name")) {
-    prop.type = BT_PROPERTY_BDNAME;
-  } else if (propName.EqualsLiteral("Discoverable")) {
-    prop.type = BT_PROPERTY_ADAPTER_SCAN_MODE;
-  } else if (propName.EqualsLiteral("DiscoverableTimeout")) {
-    prop.type = BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT;
-  } else {
-    BT_LOGR("Warning: Property type is not supported yet, type: %d", prop.type);
-  }
-
-  if (aValue.value().type() == BluetoothValue::Tuint32_t) {
-    // Set discoverable timeout
-    prop.val = (void*)aValue.value().get_uint32_t();
-  } else if (aValue.value().type() == BluetoothValue::TnsString) {
-    // Set name
-    str = NS_ConvertUTF16toUTF8(aValue.value().get_nsString());
-    const char* name = str.get();
-    prop.val = (void*)name;
-    prop.len = strlen(name);
-  } else if (aValue.value().type() == BluetoothValue::Tbool) {
-    scanMode = aValue.value().get_bool() ?
-                 BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE :
-                 BT_SCAN_MODE_CONNECTABLE;
-
-    prop.val = (void*)&scanMode;
-    prop.len = sizeof(scanMode);
-  } else {
-    BT_LOGR("SetProperty but the property cannot be recognized correctly.");
-    return NS_OK;
-  }
-
   sSetPropertyRunnableArray.AppendElement(aRunnable);
 
-  sBtInterface->SetAdapterProperty(&prop,
+  sBtInterface->SetAdapterProperty(aValue,
     new SetAdapterPropertyResultHandler(aRunnable));
 
   return NS_OK;
 }
 
 nsresult
 BluetoothServiceBluedroid::GetServiceChannel(
   const nsAString& aDeviceAddress,
@@ -1382,17 +1333,17 @@ BluetoothServiceBluedroid::UpdateSdpReco
 
 class CreateBondResultHandler MOZ_FINAL : public BluetoothResultHandler
 {
 public:
   CreateBondResultHandler(BluetoothReplyRunnable* aRunnable)
   : mRunnable(aRunnable)
   { }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     sBondingRunnableArray.RemoveElement(mRunnable);
     ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("CreatedPairedDevice"));
   }
 
 private:
   BluetoothReplyRunnable* mRunnable;
 };
@@ -1401,35 +1352,32 @@ nsresult
 BluetoothServiceBluedroid::CreatePairedDeviceInternal(
   const nsAString& aDeviceAddress, int aTimeout,
   BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
 
-  bt_bdaddr_t remoteAddress;
-  StringToBdAddressType(aDeviceAddress, &remoteAddress);
-
   sBondingRunnableArray.AppendElement(aRunnable);
 
-  sBtInterface->CreateBond(&remoteAddress,
+  sBtInterface->CreateBond(aDeviceAddress,
                            new CreateBondResultHandler(aRunnable));
 
   return NS_OK;
 }
 
 class RemoveBondResultHandler MOZ_FINAL : public BluetoothResultHandler
 {
 public:
   RemoveBondResultHandler(BluetoothReplyRunnable* aRunnable)
   : mRunnable(aRunnable)
   { }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     sUnbondingRunnableArray.RemoveElement(mRunnable);
     ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("RemoveDevice"));
   }
 
 private:
   BluetoothReplyRunnable* mRunnable;
 };
@@ -1437,23 +1385,19 @@ private:
 nsresult
 BluetoothServiceBluedroid::RemoveDeviceInternal(
   const nsAString& aDeviceAddress, BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, NS_OK);
 
-  bt_bdaddr_t remoteAddress;
-  StringToBdAddressType(aDeviceAddress, &remoteAddress);
-
-  PRUint32 i = sUnbondingRunnableArray.Length();
   sUnbondingRunnableArray.AppendElement(aRunnable);
 
-  sBtInterface->RemoveBond(&remoteAddress,
+  sBtInterface->RemoveBond(aDeviceAddress,
                            new RemoveBondResultHandler(aRunnable));
 
   return NS_OK;
 }
 
 class PinReplyResultHandler MOZ_FINAL : public BluetoothResultHandler
 {
 public:
@@ -1461,17 +1405,17 @@ public:
   : mRunnable(aRunnable)
   { }
 
   void PinReply() MOZ_OVERRIDE
   {
     DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
   }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     ReplyStatusError(mRunnable, aStatus, NS_LITERAL_STRING("SetPinCode"));
   }
 
 private:
   BluetoothReplyRunnable* mRunnable;
 };
 
@@ -1479,22 +1423,17 @@ bool
 BluetoothServiceBluedroid::SetPinCodeInternal(
   const nsAString& aDeviceAddress, const nsAString& aPinCode,
   BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
 
-  bt_bdaddr_t remoteAddress;
-  StringToBdAddressType(aDeviceAddress, &remoteAddress);
-
-  sBtInterface->PinReply(
-    &remoteAddress, true, aPinCode.Length(),
-    (bt_pin_code_t*)NS_ConvertUTF16toUTF8(aPinCode).get(),
+  sBtInterface->PinReply(aDeviceAddress, true, aPinCode,
     new PinReplyResultHandler(aRunnable));
 
   return true;
 }
 
 bool
 BluetoothServiceBluedroid::SetPasskeyInternal(
   const nsAString& aDeviceAddress, uint32_t aPasskey,
@@ -1510,17 +1449,17 @@ public:
   : mRunnable(aRunnable)
   { }
 
   void SspReply() MOZ_OVERRIDE
   {
     DispatchBluetoothReply(mRunnable, BluetoothValue(true), EmptyString());
   }
 
-  void OnError(int aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     ReplyStatusError(mRunnable, aStatus,
                      NS_LITERAL_STRING("SetPairingConfirmation"));
   }
 
 private:
   BluetoothReplyRunnable* mRunnable;
 };
@@ -1529,21 +1468,19 @@ bool
 BluetoothServiceBluedroid::SetPairingConfirmationInternal(
   const nsAString& aDeviceAddress, bool aConfirm,
   BluetoothReplyRunnable* aRunnable)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   ENSURE_BLUETOOTH_IS_READY(aRunnable, false);
 
-  bt_bdaddr_t remoteAddress;
-  StringToBdAddressType(aDeviceAddress, &remoteAddress);
-
-  sBtInterface->SspReply(&remoteAddress, (bt_ssp_variant_t)0, aConfirm, 0,
-                         new SspReplyResultHandler(aRunnable));
+  sBtInterface->SspReply(aDeviceAddress,
+                         NS_ConvertUTF8toUTF16("PasskeyConfirmation"),
+                         aConfirm, 0, new SspReplyResultHandler(aRunnable));
   return true;
 }
 
 bool
 BluetoothServiceBluedroid::SetAuthorizationInternal(
   const nsAString& aDeviceAddress, bool aAllow,
   BluetoothReplyRunnable* aRunnable)
 {
--- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
@@ -645,17 +645,17 @@ public:
       BT_LOGD("mConsumer is null, aborting receive!");
       return;
     }
 
     mImpl->mConsumer->SetAddress(aBdAddress);
     XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new AcceptTask(mImpl, aFd));
   }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     BT_LOGR("BluetoothSocketInterface::Accept failed: %d", (int)aStatus);
   }
 
 private:
   DroidSocketImpl* mImpl;
 };
@@ -827,17 +827,17 @@ public:
 
     if (!mImpl->IsShutdownOnMainThread()) {
       mImpl->mConsumer->SetAddress(aBdAddress);
     }
     XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                      new SocketConnectTask(mImpl, aFd));
   }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
     BT_WARNING("Connect failed: %d", (int)aStatus);
   }
 
 private:
   DroidSocketImpl* mImpl;
 };
@@ -846,27 +846,24 @@ bool
 BluetoothSocket::Connect(const nsAString& aDeviceAddress, int aChannel)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_FALSE(mImpl, false);
 
   mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this, aDeviceAddress,
                               aChannel, mAuth, mEncrypt);
 
-  bt_bdaddr_t remoteBdAddress;
-  StringToBdAddressType(aDeviceAddress, &remoteBdAddress);
+  // TODO: uuid as argument
+  sBluetoothSocketInterface->Connect(
+    aDeviceAddress,
+    BluetoothSocketType::RFCOMM,
+    UUID_OBEX_OBJECT_PUSH,
+    aChannel, mEncrypt, mAuth,
+    new ConnectSocketResultHandler(mImpl));
 
-  // TODO: uuid as argument
-  sBluetoothSocketInterface->Connect(&remoteBdAddress,
-                                     BTSOCK_RFCOMM,
-                                     UUID_OBEX_OBJECT_PUSH,
-                                     aChannel,
-                                     (BTSOCK_FLAG_ENCRYPT * mEncrypt) |
-                                     (BTSOCK_FLAG_AUTH * mAuth),
-                                     new ConnectSocketResultHandler(mImpl));
   return true;
 }
 
 class ListenResultHandler MOZ_FINAL : public BluetoothSocketResultHandler
 {
 public:
   ListenResultHandler(DroidSocketImpl* aImpl)
   : mImpl(aImpl)
@@ -877,17 +874,17 @@ public:
   void Listen(int aFd) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                      new SocketListenTask(mImpl, aFd));
   }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     BT_WARNING("Listen failed: %d", (int)aStatus);
   }
 
 private:
   DroidSocketImpl* mImpl;
@@ -897,23 +894,23 @@ bool
 BluetoothSocket::Listen(int aChannel)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_FALSE(mImpl, false);
 
   mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this, aChannel, mAuth,
                               mEncrypt);
 
-  sBluetoothSocketInterface->Listen(BTSOCK_RFCOMM,
-                                    "OBEX Object Push",
-                                    UUID_OBEX_OBJECT_PUSH,
-                                    aChannel,
-                                    (BTSOCK_FLAG_ENCRYPT * mEncrypt) |
-                                    (BTSOCK_FLAG_AUTH * mAuth),
-                                    new ListenResultHandler(mImpl));
+  sBluetoothSocketInterface->Listen(
+    BluetoothSocketType::RFCOMM,
+    NS_LITERAL_STRING("OBEX Object Push"),
+    UUID_OBEX_OBJECT_PUSH,
+    aChannel, mEncrypt, mAuth,
+    new ListenResultHandler(mImpl));
+
   return true;
 }
 
 bool
 BluetoothSocket::SendDroidSocketData(UnixSocketRawData* aData)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE(mImpl, false);
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -246,17 +246,17 @@ class BluetoothHfpManager::RespondToBLDN
 {
 private:
   void Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(sBluetoothHfpManager);
 
     if (!sBluetoothHfpManager->mDialingRequestProcessed) {
       sBluetoothHfpManager->mDialingRequestProcessed = true;
-      sBluetoothHfpManager->SendResponse(BTHF_AT_RESPONSE_ERROR);
+      sBluetoothHfpManager->SendResponse(HFP_AT_RESPONSE_ERROR);
     }
   }
 };
 
 class BluetoothHfpManager::MainThreadTask : public nsRunnable
 {
 public:
   MainThreadTask(const int aCommand,
@@ -320,31 +320,33 @@ Call::Call()
 {
   Reset();
 }
 
 void
 Call::Set(const nsAString& aNumber, const bool aIsOutgoing)
 {
   mNumber = aNumber;
-  mDirection = (aIsOutgoing) ? BTHF_CALL_DIRECTION_OUTGOING :
-                               BTHF_CALL_DIRECTION_INCOMING;
+  mDirection = (aIsOutgoing) ? HFP_CALL_DIRECTION_OUTGOING :
+                               HFP_CALL_DIRECTION_INCOMING;
   // Same logic as implementation in ril_worker.js
   if (aNumber.Length() && aNumber[0] == '+') {
-    mType = BTHF_CALL_ADDRTYPE_INTERNATIONAL;
+    mType = HFP_CALL_ADDRESS_TYPE_INTERNATIONAL;
+  } else {
+    mType = HFP_CALL_ADDRESS_TYPE_UNKNOWN;
   }
 }
 
 void
 Call::Reset()
 {
   mState = nsITelephonyService::CALL_STATE_DISCONNECTED;
-  mDirection = BTHF_CALL_DIRECTION_OUTGOING;
+  mDirection = HFP_CALL_DIRECTION_OUTGOING;
   mNumber.Truncate();
-  mType = BTHF_CALL_ADDRTYPE_UNKNOWN;
+  mType = HFP_CALL_ADDRESS_TYPE_UNKNOWN;
 }
 
 bool
 Call::IsActive()
 {
   return (mState == nsITelephonyService::CALL_STATE_CONNECTED);
 }
 
@@ -374,18 +376,18 @@ void
 BluetoothHfpManager::Cleanup()
 {
   mReceiveVgsFlag = false;
   mDialingRequestProcessed = true;
 
   mConnectionState = BTHF_CONNECTION_STATE_DISCONNECTED;
   mPrevConnectionState = BTHF_CONNECTION_STATE_DISCONNECTED;
   mBattChg = 5;
-  mService = 0;
-  mRoam = 0;
+  mService = HFP_NETWORK_STATE_NOT_AVAILABLE;
+  mRoam = HFP_SERVICE_TYPE_HOME;
   mSignal = 0;
 
   mController = nullptr;
 }
 
 void
 BluetoothHfpManager::Reset()
 {
@@ -440,17 +442,17 @@ public:
   CleanupInitResultHandler(BluetoothHandsfreeInterface* aInterface,
                            BluetoothProfileResultHandler* aRes)
   : mInterface(aInterface)
   , mRes(aRes)
   {
     MOZ_ASSERT(mInterface);
   }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::Init failed: %d", (int)aStatus);
     if (mRes) {
       mRes->OnError(NS_ERROR_FAILURE);
     }
   }
 
   void Init() MOZ_OVERRIDE
@@ -547,17 +549,17 @@ BluetoothHfpManager::~BluetoothHfpManage
 
 class CleanupResultHandler MOZ_FINAL : public BluetoothHandsfreeResultHandler
 {
 public:
   CleanupResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::Cleanup failed: %d", (int)aStatus);
     if (mRes) {
       mRes->OnError(NS_ERROR_FAILURE);
     }
   }
 
   void Cleanup() MOZ_OVERRIDE
@@ -740,17 +742,17 @@ BluetoothHfpManager::ProcessDtmfCmd(char
 void
 BluetoothHfpManager::ProcessAtChld(bthf_chld_type_t aChld)
 {
   nsAutoCString message("CHLD=");
   message.AppendInt((int)aChld);
   BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
                       NS_ConvertUTF8toUTF16(message));
 
-  SendResponse(BTHF_AT_RESPONSE_OK);
+  SendResponse(HFP_AT_RESPONSE_OK);
 }
 
 void BluetoothHfpManager::ProcessDialCall(char *aNumber)
 {
   nsAutoCString message(aNumber);
 
   // There are three cases based on aNumber,
   // 1) Empty value:    Redial, BLDN
@@ -772,66 +774,67 @@ void BluetoothHfpManager::ProcessDialCal
     BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
                         NS_ConvertUTF8toUTF16(newMsg));
     BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::POST_TASK_RESPOND_TO_BLDN);
   } else {
     nsAutoCString newMsg("ATD");
     newMsg += StringHead(message, message.Length() - 1);
     BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
                         NS_ConvertUTF8toUTF16(newMsg));
-    SendResponse(BTHF_AT_RESPONSE_OK);
+    SendResponse(HFP_AT_RESPONSE_OK);
   }
 }
 
 void
 BluetoothHfpManager::ProcessAtCnum()
 {
   if (!mMsisdn.IsEmpty()) {
     nsAutoCString message("+CNUM: ,\"");
     message.Append(NS_ConvertUTF16toUTF8(mMsisdn).get());
     message.AppendLiteral("\",");
     message.AppendInt(BTHF_CALL_ADDRTYPE_UNKNOWN);
     message.AppendLiteral(",,4");
 
     SendLine(message.get());
   }
 
-  SendResponse(BTHF_AT_RESPONSE_OK);
+  SendResponse(HFP_AT_RESPONSE_OK);
 }
 
 class CindResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::CindResponse failed: %d",
                (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::ProcessAtCind()
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
   int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
-  bthf_call_state_t callState = ConvertToBthfCallState(GetCallSetupState());
+  BluetoothHandsfreeCallState callState =
+    ConvertToBluetoothHandsfreeCallState(GetCallSetupState());
 
   sBluetoothHfpInterface->CindResponse(mService, numActive, numHeld,
                                        callState, mSignal, mRoam, mBattChg,
                                        new CindResponseResultHandler());
 }
 
 class CopsResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::CopsResponse failed: %d",
                (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::ProcessAtCops()
@@ -854,38 +857,38 @@ BluetoothHfpManager::ProcessAtClcc()
 
   if (!mCdmaSecondCall.mNumber.IsEmpty()) {
     MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
     MOZ_ASSERT(i == 2);
 
     SendCLCC(mCdmaSecondCall, 2);
   }
 
-  SendResponse(BTHF_AT_RESPONSE_OK);
+  SendResponse(HFP_AT_RESPONSE_OK);
 }
 
 class AtResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::AtResponse failed: %d",
                (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::ProcessUnknownAt(char *aAtString)
 {
   BT_LOGR("[%s]", aAtString);
 
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
-  sBluetoothHfpInterface->AtResponse(BTHF_AT_RESPONSE_ERROR, 0,
+  sBluetoothHfpInterface->AtResponse(HFP_AT_RESPONSE_ERROR, 0,
                                      new AtResponseResultHandler());
 }
 
 void
 BluetoothHfpManager::ProcessKeyPressed()
 {
   bool hasActiveCall =
     (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED) > 0);
@@ -991,17 +994,17 @@ BluetoothHfpManager::NotifyDialer(const 
 
   BT_ENSURE_TRUE_VOID_BROADCAST_SYSMSG(type, parameters);
 }
 
 class VolumeControlResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::VolumeControl failed: %d",
                (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::HandleVolumeChanged(const nsAString& aData)
@@ -1042,17 +1045,17 @@ BluetoothHfpManager::HandleVolumeChanged
   if (mReceiveVgsFlag) {
     mReceiveVgsFlag = false;
     return;
   }
 
   // Only send volume back when there's a connected headset
   if (IsConnected()) {
     NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
-    sBluetoothHfpInterface->VolumeControl(BTHF_VOLUME_TYPE_SPK, mCurrentVgs,
+    sBluetoothHfpInterface->VolumeControl(HFP_VOLUME_TYPE_SPEAKER, mCurrentVgs,
                                           new VolumeControlResultHandler());
   }
 }
 
 void
 BluetoothHfpManager::HandleVoiceConnectionChanged(uint32_t aClientId)
 {
   nsCOMPtr<nsIMobileConnectionProvider> connection =
@@ -1065,28 +1068,29 @@ BluetoothHfpManager::HandleVoiceConnecti
 
   nsString type;
   voiceInfo->GetType(type);
   mPhoneType = GetPhoneType(type);
 
   // Roam
   bool roaming;
   voiceInfo->GetRoaming(&roaming);
-  mRoam = (roaming) ? 1 : 0;
+  mRoam = (roaming) ? HFP_SERVICE_TYPE_ROAMING : HFP_SERVICE_TYPE_HOME;
 
   // Service
   nsString regState;
   voiceInfo->GetState(regState);
 
   int service = (regState.EqualsLiteral("registered")) ? 1 : 0;
   if (service != mService) {
     // Notify BluetoothRilListener of service change
     mListener->ServiceChanged(aClientId, service);
   }
-  mService = service;
+  mService = service ? HFP_NETWORK_STATE_AVAILABLE :
+                       HFP_NETWORK_STATE_NOT_AVAILABLE;
 
   // Signal
   JSContext* cx = nsContentUtils::GetSafeJSContext();
   NS_ENSURE_TRUE_VOID(cx);
   JS::Rooted<JS::Value> value(cx);
   voiceInfo->GetRelSignalStrength(&value);
   NS_ENSURE_TRUE_VOID(value.isNumber());
   mSignal = (int)ceil(value.toNumber() / 20.0);
@@ -1138,129 +1142,129 @@ BluetoothHfpManager::HandleShutdown()
   DisconnectSco();
   sBluetoothHfpManager = nullptr;
 }
 
 class ClccResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::ClccResponse failed: %d",
                (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::SendCLCC(Call& aCall, int aIndex)
 {
   NS_ENSURE_TRUE_VOID(aCall.mState !=
                         nsITelephonyService::CALL_STATE_DISCONNECTED);
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
-  bthf_call_state_t callState = ConvertToBthfCallState(aCall.mState);
+  BluetoothHandsfreeCallState callState =
+    ConvertToBluetoothHandsfreeCallState(aCall.mState);
 
   if (mPhoneType == PhoneType::CDMA && aIndex == 1 && aCall.IsActive()) {
-    callState = (mCdmaSecondCall.IsActive()) ? BTHF_CALL_STATE_HELD :
-                                               BTHF_CALL_STATE_ACTIVE;
+    callState = (mCdmaSecondCall.IsActive()) ? HFP_CALL_STATE_HELD :
+                                               HFP_CALL_STATE_ACTIVE;
   }
 
-  if (callState == BTHF_CALL_STATE_INCOMING &&
+  if (callState == HFP_CALL_STATE_INCOMING &&
       FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
-    callState = BTHF_CALL_STATE_WAITING;
+    callState = HFP_CALL_STATE_WAITING;
   }
 
   sBluetoothHfpInterface->ClccResponse(
-    aIndex, aCall.mDirection, callState, BTHF_CALL_TYPE_VOICE,
-    BTHF_CALL_MPTY_TYPE_SINGLE, NS_ConvertUTF16toUTF8(aCall.mNumber).get(),
+    aIndex, aCall.mDirection, callState, HFP_CALL_MODE_VOICE,
+    HFP_CALL_MPTY_TYPE_SINGLE, aCall.mNumber,
     aCall.mType, new ClccResponseResultHandler());
 }
 
 class FormattedAtResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::FormattedAtResponse failed: %d",
                (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->FormattedAtResponse(
     aMessage, new FormattedAtResponseResultHandler());
 }
 
 void
-BluetoothHfpManager::SendResponse(bthf_at_response_t aResponseCode)
+BluetoothHfpManager::SendResponse(BluetoothHandsfreeAtResponse aResponseCode)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->AtResponse(
     aResponseCode, 0, new AtResponseResultHandler());
 }
 
 class PhoneStateChangeResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::PhoneStateChange failed: %d",
                (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::UpdatePhoneCIND(uint32_t aCallIndex)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
   int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
-  bthf_call_state_t callSetupState =
-    ConvertToBthfCallState(GetCallSetupState());
-  nsAutoCString number =
-    NS_ConvertUTF16toUTF8(mCurrentCallArray[aCallIndex].mNumber);
-  bthf_call_addrtype_t type = mCurrentCallArray[aCallIndex].mType;
+  BluetoothHandsfreeCallState callSetupState =
+    ConvertToBluetoothHandsfreeCallState(GetCallSetupState());
+  BluetoothHandsfreeCallAddressType type = mCurrentCallArray[aCallIndex].mType;
 
   BT_LOGR("[%d] state %d => BTHF: active[%d] held[%d] setupstate[%d]",
           aCallIndex, mCurrentCallArray[aCallIndex].mState,
           numActive, numHeld, callSetupState);
 
   sBluetoothHfpInterface->PhoneStateChange(
-    numActive, numHeld, callSetupState, number.get(), type,
+    numActive, numHeld, callSetupState,
+    mCurrentCallArray[aCallIndex].mNumber, type,
     new PhoneStateChangeResultHandler());
 }
 
 class DeviceStatusNotificationResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING(
       "BluetoothHandsfreeInterface::DeviceStatusNotification failed: %d",
       (int)aStatus);
   }
 };
 
 void
 BluetoothHfpManager::UpdateDeviceCIND()
 {
   if (sBluetoothHfpInterface) {
     sBluetoothHfpInterface->DeviceStatusNotification(
-      (bthf_network_state_t) mService,
-      (bthf_service_type_t) mRoam,
+      mService,
+      mRoam,
       mSignal,
       mBattChg, new DeviceStatusNotificationResultHandler());
   }
 }
 
 uint32_t
 BluetoothHfpManager::FindFirstCall(uint16_t aState)
 {
@@ -1304,34 +1308,34 @@ BluetoothHfpManager::GetCallSetupState()
       default:
         break;
     }
   }
 
   return nsITelephonyService::CALL_STATE_DISCONNECTED;
 }
 
-bthf_call_state_t
-BluetoothHfpManager::ConvertToBthfCallState(int aCallState)
+BluetoothHandsfreeCallState
+BluetoothHfpManager::ConvertToBluetoothHandsfreeCallState(int aCallState) const
 {
-  bthf_call_state_t state;
+  BluetoothHandsfreeCallState state;
 
   // Refer to AOSP BluetoothPhoneService.convertCallState
   if (aCallState == nsITelephonyService::CALL_STATE_INCOMING) {
-    state = BTHF_CALL_STATE_INCOMING;
+    state = HFP_CALL_STATE_INCOMING;
   } else if (aCallState == nsITelephonyService::CALL_STATE_DIALING) {
-    state = BTHF_CALL_STATE_DIALING;
+    state = HFP_CALL_STATE_DIALING;
   } else if (aCallState == nsITelephonyService::CALL_STATE_ALERTING) {
-    state = BTHF_CALL_STATE_ALERTING;
+    state = HFP_CALL_STATE_ALERTING;
   } else if (aCallState == nsITelephonyService::CALL_STATE_CONNECTED) {
-    state = BTHF_CALL_STATE_ACTIVE;
+    state = HFP_CALL_STATE_ACTIVE;
   } else if (aCallState == nsITelephonyService::CALL_STATE_HELD) {
-    state = BTHF_CALL_STATE_HELD;
+    state = HFP_CALL_STATE_HELD;
   } else { // disconnected
-    state = BTHF_CALL_STATE_IDLE;
+    state = HFP_CALL_STATE_IDLE;
   }
 
   return state;
 }
 
 bool
 BluetoothHfpManager::IsTransitionState(uint16_t aCallState, bool aIsConference)
 {
@@ -1395,17 +1399,17 @@ BluetoothHfpManager::HandleCallStateChan
   if (!IsTransitionState(aCallState, aIsConference)) {
     UpdatePhoneCIND(aCallIndex);
   }
 
   switch (aCallState) {
     case nsITelephonyService::CALL_STATE_DIALING:
       // We've send Dialer a dialing request and this is the response.
       if (!mDialingRequestProcessed) {
-        SendResponse(BTHF_AT_RESPONSE_OK);
+        SendResponse(HFP_AT_RESPONSE_OK);
         mDialingRequestProcessed = true;
       }
       break;
     case nsITelephonyService::CALL_STATE_DISCONNECTED:
       // -1 is necessary because call 0 is an invalid (padding) call object.
       if (mCurrentCallArray.Length() - 1 ==
           GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) {
         // In order to let user hear busy tone via connected Bluetooth headset,
@@ -1492,60 +1496,56 @@ BluetoothHfpManager::ToggleCalls()
                              nsITelephonyService::CALL_STATE_HELD :
                              nsITelephonyService::CALL_STATE_CONNECTED;
 }
 
 class ConnectAudioResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::ConnectAudio failed: %d",
                (int)aStatus);
   }
 };
 
 bool
 BluetoothHfpManager::ConnectSco()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE(!sInShutdown, false);
   NS_ENSURE_TRUE(IsConnected() && !IsScoConnected(), false);
   NS_ENSURE_TRUE(sBluetoothHfpInterface, false);
 
-  bt_bdaddr_t deviceBdAddress;
-  StringToBdAddressType(mDeviceAddress, &deviceBdAddress);
-  sBluetoothHfpInterface->ConnectAudio(&deviceBdAddress,
+  sBluetoothHfpInterface->ConnectAudio(mDeviceAddress,
                                        new ConnectAudioResultHandler());
 
   return true;
 }
 
 class DisconnectAudioResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::DisconnectAudio failed: %d",
                (int)aStatus);
   }
 };
 
 bool
 BluetoothHfpManager::DisconnectSco()
 {
   NS_ENSURE_TRUE(IsScoConnected(), false);
   NS_ENSURE_TRUE(sBluetoothHfpInterface, false);
 
-  bt_bdaddr_t deviceBdAddress;
-  StringToBdAddressType(mDeviceAddress, &deviceBdAddress);
-  sBluetoothHfpInterface->DisconnectAudio(&deviceBdAddress,
+  sBluetoothHfpInterface->DisconnectAudio(mDeviceAddress,
                                           new DisconnectAudioResultHandler());
 
   return true;
 }
 
 bool
 BluetoothHfpManager::IsScoConnected()
 {
@@ -1573,17 +1573,17 @@ class ConnectResultHandler MOZ_FINAL : p
 {
 public:
   ConnectResultHandler(BluetoothHfpManager* aHfpManager)
   : mHfpManager(aHfpManager)
   {
     MOZ_ASSERT(mHfpManager);
   }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::Connect failed: %d",
                (int)aStatus);
     mHfpManager->OnConnectError();
   }
 
 private:
   BluetoothHfpManager* mHfpManager;
@@ -1602,23 +1602,20 @@ BluetoothHfpManager::Connect(const nsASt
   }
 
   if (!sBluetoothHfpInterface) {
     BT_LOGR("sBluetoothHfpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
-  bt_bdaddr_t deviceBdAddress;
-  StringToBdAddressType(aDeviceAddress, &deviceBdAddress);
-
   mDeviceAddress = aDeviceAddress;
   mController = aController;
 
-  sBluetoothHfpInterface->Connect(&deviceBdAddress,
+  sBluetoothHfpInterface->Connect(mDeviceAddress,
                                   new ConnectResultHandler(this));
 }
 
 void
 BluetoothHfpManager::OnDisconnectError()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
@@ -1629,17 +1626,17 @@ class DisconnectResultHandler MOZ_FINAL 
 {
 public:
   DisconnectResultHandler(BluetoothHfpManager* aHfpManager)
   : mHfpManager(aHfpManager)
   {
     MOZ_ASSERT(mHfpManager);
   }
 
-  void OnError(bt_status_t aStatus) MOZ_OVERRIDE
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::Disconnect failed: %d",
                (int)aStatus);
     mHfpManager->OnDisconnectError();
   }
 
 private:
   BluetoothHfpManager* mHfpManager;
@@ -1653,22 +1650,19 @@ BluetoothHfpManager::Disconnect(Bluetoot
   MOZ_ASSERT(!mController);
 
   if (!sBluetoothHfpInterface) {
     BT_LOGR("sBluetoothHfpInterface is null");
     aController->NotifyCompletion(NS_LITERAL_STRING(ERR_NO_AVAILABLE_RESOURCE));
     return;
   }
 
-  bt_bdaddr_t deviceBdAddress;
-  StringToBdAddressType(mDeviceAddress, &deviceBdAddress);
-
   mController = aController;
 
-  sBluetoothHfpInterface->Disconnect(&deviceBdAddress,
+  sBluetoothHfpInterface->Disconnect(mDeviceAddress,
                                      new DisconnectResultHandler(this));
 }
 
 void
 BluetoothHfpManager::OnConnect(const nsAString& aErrorStr)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
@@ -61,18 +61,18 @@ class Call {
 public:
   Call();
   void Set(const nsAString& aNumber, const bool aIsOutgoing);
   void Reset();
   bool IsActive();
 
   uint16_t mState;
   nsString mNumber;
-  bthf_call_direction_t mDirection; // 0: outgoing call; 1: incoming call
-  bthf_call_addrtype_t mType;
+  BluetoothHandsfreeCallDirection mDirection;
+  BluetoothHandsfreeCallAddressType mType;
 };
 
 class BluetoothHfpManager : public BluetoothHfpManagerBase
                           , public BatteryObserver
 {
 public:
   BT_DECL_HFP_MGR_BASE
 
@@ -148,31 +148,32 @@ private:
   void NotifyDialer(const nsAString& aCommand);
 
   PhoneType GetPhoneType(const nsAString& aType);
   void ResetCallArray();
   uint32_t FindFirstCall(uint16_t aState);
   uint32_t GetNumberOfCalls(uint16_t aState);
   uint16_t GetCallSetupState();
   bool IsTransitionState(uint16_t aCallState, bool aIsConference);
-  bthf_call_state_t ConvertToBthfCallState(int aCallState);
+  BluetoothHandsfreeCallState
+    ConvertToBluetoothHandsfreeCallState(int aCallState) const;
 
   void UpdatePhoneCIND(uint32_t aCallIndex);
   void UpdateDeviceCIND();
   void SendCLCC(Call& aCall, int aIndex);
   void SendLine(const char* aMessage);
-  void SendResponse(bthf_at_response_t aResponseCode);
+  void SendResponse(BluetoothHandsfreeAtResponse aResponseCode);
 
   int mConnectionState;
   int mPrevConnectionState;
   int mAudioState;
   // Device CIND
   int mBattChg;
-  int mService;
-  int mRoam;
+  BluetoothHandsfreeNetworkState mService;
+  BluetoothHandsfreeServiceType mRoam;
   int mSignal;
 
   int mCurrentVgs;
   int mCurrentVgm;
   bool mReceiveVgsFlag;
   bool mDialingRequestProcessed;
   PhoneType mPhoneType;
   nsString mDeviceAddress;
--- a/dom/nfc/nsNfc.js
+++ b/dom/nfc/nsNfc.js
@@ -195,24 +195,22 @@ mozNfc.prototype = {
   },
 
   getNFCTag: function getNFCTag(sessionToken) {
     let obj = new MozNFCTag();
     obj.initialize(this._window, sessionToken);
     if (this._nfcContentHelper.setSessionToken(sessionToken)) {
       return this._window.MozNFCTag._create(this._window, obj);
     }
-    throw new Error("Unable to create NFCTag object, Reason:  Bad SessionToken " +
-                     sessionToken);
+    return null;
   },
 
   getNFCPeer: function getNFCPeer(sessionToken) {
     if (!sessionToken || !this._nfcContentHelper.setSessionToken(sessionToken)) {
-      throw new Error("Unable to create NFCPeer object, Reason:  Bad SessionToken " +
-                      sessionToken);
+      return null;
     }
 
     if (!this.nfcObject) {
       let obj = new MozNFCPeer();
       obj.initialize(this._window, sessionToken);
       this.nfcObject = obj;
       this.nfcObject.contentObject = this._window.MozNFCPeer._create(this._window, obj);
     }
--- a/dom/nfc/tests/marionette/test_nfc_peer.js
+++ b/dom/nfc/tests/marionette/test_nfc_peer.js
@@ -80,28 +80,16 @@ function testPeerReady() {
 
 function testCheckP2PRegFailure() {
   window.navigator.mozSetMessageHandler(
     "nfc-manager-tech-discovered", handleTechnologyDiscoveredRE0ForP2PRegFailure);
 
   toggleNFC(true).then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0));
 }
 
-function testCheckNfcPeerObjForInvalidToken() {
-  try {
-    // Use a'fakeSessionToken'
-    let peer = nfc.getNFCPeer("fakeSessionToken");
-    ok(false, "Should not get a NFCPeer object.");
-  } catch (ex) {
-    ok(true, "Exception expected");
-  }
-
-  toggleNFC(false).then(runNextTest);
-}
-
 function testPeerLostShouldNotBeCalled() {
   nfc.onpeerlost = function () {
     ok(false, "onpeerlost shouldn't be called");
   };
 
   toggleNFC(true)
     .then(() => NCI.activateRE(emulator.P2P_RE_INDEX_0))
     .then(NCI.deactivate)
@@ -146,19 +134,38 @@ function testPeerShouldThrow() {
   } catch (e) {
     ok(true, "Exception expected");
   }
 
   nfc.onpeerready = null;
   toggleNFC(false).then(runNextTest);
 }
 
+function testPeerInvalidToken() {
+  let peer = nfc.getNFCPeer("fakeSessionToken");
+  is(peer, null, "NFCPeer should be null on wrong session token");
+
+  runNextTest();
+}
+
+/**
+ * Added for completeness in Bug 1042651,
+ * TODO: remove once Bug 963531 lands
+ */
+function testTagInvalidToken() {
+  let tag = nfc.getNFCTag("fakeSessionToken");
+  is(tag, null, "NFCTag should be null on wrong session token");
+
+  runNextTest();
+}
+
 let tests = [
   testPeerReady,
   testCheckP2PRegFailure,
-  testCheckNfcPeerObjForInvalidToken,
   testPeerLostShouldNotBeCalled,
-  testPeerShouldThrow
+  testPeerShouldThrow,
+  testPeerInvalidToken,
+  testTagInvalidToken
 ];
 
 SpecialPowers.pushPermissions(
   [{"type": "nfc-manager", "allow": true, context: document},
    {"type": "nfc-write", "allow": true, context: document}], runTests);
--- a/dom/webidl/MozNFC.webidl
+++ b/dom/webidl/MozNFC.webidl
@@ -41,20 +41,25 @@ interface MozNFCManager {
     */
    DOMRequest powerOff();
 };
 
 [JSImplementation="@mozilla.org/navigatorNfc;1",
  NavigatorProperty="mozNfc",
  Func="Navigator::HasNFCSupport"]
 interface MozNFC : EventTarget {
-   [Throws]
-   MozNFCTag getNFCTag(DOMString sessionId);
-   [Throws]
-   MozNFCPeer getNFCPeer(DOMString sessionId);
+   /**
+    * Returns MozNFCTag object or null in case of invalid sessionToken
+    */
+   MozNFCTag? getNFCTag(DOMString sessionToken);
+
+   /**
+    * Returns MozNFCPeer object or null in case of invalid sessionToken
+    */
+   MozNFCPeer? getNFCPeer(DOMString sessionToken);
 
    /**
     * This event will be fired when another NFCPeer is detected, and user confirms
     * to share data to the NFCPeer object by calling mozNFC.notifyUserAcceptedP2P.
     * The event will be type of NFCPeerEvent.
     */
    [CheckPermissions="nfc-write"]
    attribute EventHandler onpeerready;
--- a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
@@ -92,27 +92,27 @@ public:
   {
   }
 
   int64_t duration;
   uint32_t channel_count;
   uint32_t bits_per_sample;
   uint32_t samples_per_second;
   int8_t frequency_index;
+  int8_t aac_profile;
   mozilla::Vector<uint8_t> extra_data;
   mozilla::Vector<uint8_t> audio_specific_config;
   CryptoTrack crypto;
 
   void Update(stagefright::sp<stagefright::MetaData>& aMetaData,
               const char* aMimeType);
   bool IsValid();
 
 private:
   friend class MP4Demuxer;
-  int8_t aac_profile;
 };
 
 class VideoDecoderConfig : public TrackConfig
 {
 public:
   VideoDecoderConfig() : display_width(0), display_height(0) {}
 
   int32_t display_width;