Merge m-c to fx-team a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 02 Sep 2014 19:46:23 -0700
changeset 203397 53ab51cc4eb0a8b475ff1e8e1db8e59688c8b97e
parent 203396 c8dc98469fc0950aef15c589473f4440cd19e115 (current diff)
parent 203197 e58842c764dd10913e29f54e3cecd7654499a830 (diff)
child 203398 e92f2cc211cab77c5981f6ad526635300cffde80
push id48665
push userryanvm@gmail.com
push dateWed, 03 Sep 2014 20:40:15 +0000
treeherdermozilla-inbound@0da762e6868a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone35.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 m-c to fx-team a=merge
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/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="4b4336c73c081b39776d399835ce4853aee5cc1c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <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="7ddb07033043613303061416882c9b02ac3d76b6"/>
@@ -30,17 +30,17 @@
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
   <project name="device/sample" path="device/sample" revision="1a3d8efa0ad32ec8f145367a3cf0f54b97385c3c"/>
   <project name="platform/abi/cpp" path="abi/cpp" revision="18f1b5e28734183ff8073fe86dc46bc4ebba8a59"/>
   <project name="platform/bionic" path="bionic" revision="86b1f589c313422a7da1812512b9ec8d1cf9ba3c"/>
-  <project name="platform/bootable/recovery" path="bootable/recovery" revision="a556e98f857546c94b5a9c179ee3c99a7c17d729"/>
+  <project name="platform/bootable/recovery" path="bootable/recovery" revision="4eece0d80928a2b5266b78421ebf0c8686d4ad2c"/>
   <project name="platform/external/aac" path="external/aac" revision="fa3eba16446cc8f2f5e2dfc20d86a49dbd37299e"/>
   <project name="platform/external/bison" path="external/bison" revision="c2418b886165add7f5a31fc5609f0ce2d004a90e"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="c50830cae1b748024eec7e73ad98a4e427f663c7"/>
   <project name="platform/external/bsdiff" path="external/bsdiff" revision="23e322ab19fb7d74c2c37e40ce364d9f709bdcee"/>
   <project name="platform/external/bzip2" path="external/bzip2" revision="1cb636bd8e9e5cdfd5d5b2909a122f6e80db62de"/>
   <project name="platform/external/checkpolicy" path="external/checkpolicy" revision="0d73ef7049feee794f14cf1af88d05dae8139914"/>
   <project name="platform/external/dhcpcd" path="external/dhcpcd" revision="84b7252b0a9d0edc9a1db1e0c518771d26b23058"/>
   <project name="platform/external/dnsmasq" path="external/dnsmasq" revision="41d356427a632f5336384bfa45c8420ffc274f66"/>
@@ -128,16 +128,16 @@
   <project name="platform/external/icu4c" path="external/icu4c" revision="2bb01561780583cc37bc667f0ea79f48a122d8a2"/>
   <!-- dolphin specific things -->
   <project name="device/sprd" path="device/sprd" revision="4eac1e31bf69596bf229a6877c9aa3493ecd9fce"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="4e58336019b5cbcfd134caf55b142236cf986618"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="facca8d3e35431b66f85a4eb42bc6c5b24bd04da"/>
   <project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
   <project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
-  <project name="kernel/common" path="kernel" revision="600fa6e2bbc9518a8c4ac9ad687d6eafd2cc9b7b"/>
+  <project name="kernel/common" path="kernel" revision="03effd4db31881b2dd8d57575694515327f9ea2e"/>
   <project name="platform/system/core" path="system/core" revision="53d584d4a4b4316e4de9ee5f210d662f89b44e7e"/>
-  <project name="u-boot" path="u-boot" revision="fc5df5228c1242cda0743231b3c63a89c802889e"/>
+  <project name="u-boot" path="u-boot" revision="df509ae75495aa409969973b97ee781037dee1fe"/>
   <project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7feb3df0e150053e0143ef525f6e082bda320aea"/>
   <project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="2be9b6d4984da4a2d0afde1e149c01a12f691f30"/>
   <project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
   <project name="vendor/sprd/proprietories" path="vendor/sprd/proprietories" revision="d2466593022f7078aaaf69026adf3367c2adb7bb"/>
 </manifest>
--- 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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7ddb07033043613303061416882c9b02ac3d76b6"/>
   <!-- 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="74465af039d2809454afdfef285285bb63146e1b">
     <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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7ddb07033043613303061416882c9b02ac3d76b6"/>
   <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"/>
--- 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="4b4336c73c081b39776d399835ce4853aee5cc1c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <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="7ddb07033043613303061416882c9b02ac3d76b6"/>
--- 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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7ddb07033043613303061416882c9b02ac3d76b6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-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="4b4336c73c081b39776d399835ce4853aee5cc1c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <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="7ddb07033043613303061416882c9b02ac3d76b6"/>
--- 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="74465af039d2809454afdfef285285bb63146e1b">
     <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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7ddb07033043613303061416882c9b02ac3d76b6"/>
   <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"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "a5c22fd2faed558bd633a191e9db710b8080abca", 
+    "revision": "a0fe2fdc571f1a5eb5474e08773fac80f9bb9fbd", 
     "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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <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="7ddb07033043613303061416882c9b02ac3d76b6"/>
   <!-- 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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <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="74465af039d2809454afdfef285285bb63146e1b">
     <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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7ddb07033043613303061416882c9b02ac3d76b6"/>
   <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"/>
--- 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="7e469783859785a8bd4bf02a802f32561c84be7b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="52670853c17fc0d3d33065c667c0ce124c93b98f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <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="7ddb07033043613303061416882c9b02ac3d76b6"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/dom/bluetooth2/BluetoothCommon.h
+++ b/dom/bluetooth2/BluetoothCommon.h
@@ -296,26 +296,40 @@ enum BluetoothSocketType {
   EL2CAP = 4
 };
 
 enum BluetoothHandsfreeAtResponse {
   HFP_AT_RESPONSE_ERROR,
   HFP_AT_RESPONSE_OK
 };
 
+enum BluetoothHandsfreeAudioState {
+  HFP_AUDIO_STATE_DISCONNECTED,
+  HFP_AUDIO_STATE_CONNECTING,
+  HFP_AUDIO_STATE_CONNECTED,
+  HFP_AUDIO_STATE_DISCONNECTING,
+};
+
 enum BluetoothHandsfreeCallAddressType {
   HFP_CALL_ADDRESS_TYPE_UNKNOWN,
   HFP_CALL_ADDRESS_TYPE_INTERNATIONAL
 };
 
 enum BluetoothHandsfreeCallDirection {
   HFP_CALL_DIRECTION_OUTGOING,
   HFP_CALL_DIRECTION_INCOMING
 };
 
+enum BluetoothHandsfreeCallHoldType {
+  HFP_CALL_HOLD_RELEASEHELD,
+  HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD,
+  HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD,
+  HFP_CALL_HOLD_ADDHELDTOCONF
+};
+
 enum BluetoothHandsfreeCallMode {
   HFP_CALL_MODE_VOICE,
   HFP_CALL_MODE_DATA,
   HFP_CALL_MODE_FAX
 };
 
 enum BluetoothHandsfreeCallMptyType {
   HFP_CALL_MPTY_TYPE_SINGLE,
@@ -327,26 +341,45 @@ enum BluetoothHandsfreeCallState {
   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 BluetoothHandsfreeConnectionState
+{
+  HFP_CONNECTION_STATE_DISCONNECTED,
+  HFP_CONNECTION_STATE_CONNECTING,
+  HFP_CONNECTION_STATE_CONNECTED,
+  HFP_CONNECTION_STATE_SLC_CONNECTED,
+  HFP_CONNECTION_STATE_DISCONNECTING
+};
+
 enum BluetoothHandsfreeNetworkState {
   HFP_NETWORK_STATE_NOT_AVAILABLE,
   HFP_NETWORK_STATE_AVAILABLE
 };
 
+enum BluetoothHandsfreeNRECState {
+  HFP_NREC_STOPPED,
+  HFP_NREC_STARTED
+};
+
 enum BluetoothHandsfreeServiceType {
   HFP_SERVICE_TYPE_HOME,
   HFP_SERVICE_TYPE_ROAMING
 };
 
+enum BluetoothHandsfreeVoiceRecognitionState {
+  HFP_VOICE_RECOGNITION_STOPPED,
+  HFP_VOICE_RECOGNITION_STARTED
+};
+
 enum BluetoothHandsfreeVolumeType {
   HFP_VOLUME_TYPE_SPEAKER,
   HFP_VOLUME_TYPE_MICROPHONE
 };
 
 class BluetoothSignal;
 typedef mozilla::Observer<BluetoothSignal> BluetoothSignalObserver;
 
--- a/dom/bluetooth2/bluedroid/BluetoothInterface.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothInterface.cpp
@@ -357,21 +357,35 @@ Convert(bt_discovery_state_t aIn, bool& 
   if (aIn >= MOZ_ARRAY_LENGTH(sDiscoveryState)) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
   aOut = sDiscoveryState[aIn];
   return NS_OK;
 }
 
 static nsresult
+Convert(const char* aIn, nsACString& aOut)
+{
+  aOut.Assign(aIn);
+
+  return NS_OK;
+}
+
+static nsresult
+Convert(const char* aIn, nsAString& aOut)
+{
+  aOut = NS_ConvertUTF8toUTF16(aIn);
+
+  return NS_OK;
+}
+
+static nsresult
 Convert(const bt_bdname_t& aIn, nsAString& aOut)
 {
-  aOut = NS_ConvertUTF8toUTF16(reinterpret_cast<const char*>(aIn.name));
-
-  return NS_OK;
+  return Convert(reinterpret_cast<const char*>(aIn.name), aOut);
 }
 
 static nsresult
 Convert(const bt_bdname_t* aIn, nsAString& aOut)
 {
   if (!aIn) {
     aOut.Truncate();
     return NS_OK;
@@ -599,16 +613,113 @@ Convert(BluetoothHandsfreeVolumeType aIn
   };
   if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
   aOut = sVolumeType[aIn];
   return NS_OK;
 }
 
+static nsresult
+Convert(bthf_audio_state_t aIn, BluetoothHandsfreeAudioState& aOut)
+{
+  static const BluetoothHandsfreeAudioState sAudioState[] = {
+    CONVERT(BTHF_AUDIO_STATE_DISCONNECTED, HFP_AUDIO_STATE_DISCONNECTED),
+    CONVERT(BTHF_AUDIO_STATE_CONNECTING, HFP_AUDIO_STATE_CONNECTING),
+    CONVERT(BTHF_AUDIO_STATE_CONNECTED, HFP_AUDIO_STATE_CONNECTED),
+    CONVERT(BTHF_AUDIO_STATE_DISCONNECTING, HFP_AUDIO_STATE_DISCONNECTING)
+  };
+  if (aIn >= MOZ_ARRAY_LENGTH(sAudioState)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sAudioState[aIn];
+  return NS_OK;
+}
+
+static nsresult
+Convert(bthf_chld_type_t aIn, BluetoothHandsfreeCallHoldType& aOut)
+{
+  static const BluetoothHandsfreeCallHoldType sCallHoldType[] = {
+    CONVERT(BTHF_CHLD_TYPE_RELEASEHELD, HFP_CALL_HOLD_RELEASEHELD),
+    CONVERT(BTHF_CHLD_TYPE_RELEASEACTIVE_ACCEPTHELD,
+      HFP_CALL_HOLD_RELEASEACTIVE_ACCEPTHELD),
+    CONVERT(BTHF_CHLD_TYPE_HOLDACTIVE_ACCEPTHELD,
+      HFP_CALL_HOLD_HOLDACTIVE_ACCEPTHELD),
+    CONVERT(BTHF_CHLD_TYPE_ADDHELDTOCONF, HFP_CALL_HOLD_ADDHELDTOCONF)
+  };
+  if (aIn >= MOZ_ARRAY_LENGTH(sCallHoldType)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sCallHoldType[aIn];
+  return NS_OK;
+}
+
+static nsresult
+Convert(bthf_connection_state_t aIn, BluetoothHandsfreeConnectionState& aOut)
+{
+  static const BluetoothHandsfreeConnectionState sConnectionState[] = {
+    CONVERT(BTHF_CONNECTION_STATE_DISCONNECTED,
+      HFP_CONNECTION_STATE_DISCONNECTED),
+    CONVERT(BTHF_CONNECTION_STATE_CONNECTING, HFP_CONNECTION_STATE_CONNECTING),
+    CONVERT(BTHF_CONNECTION_STATE_CONNECTED, HFP_CONNECTION_STATE_CONNECTED),
+    CONVERT(BTHF_CONNECTION_STATE_SLC_CONNECTED,
+      HFP_CONNECTION_STATE_SLC_CONNECTED),
+    CONVERT(BTHF_CONNECTION_STATE_DISCONNECTING,
+      HFP_CONNECTION_STATE_DISCONNECTING)
+  };
+  if (aIn >= MOZ_ARRAY_LENGTH(sConnectionState)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sConnectionState[aIn];
+  return NS_OK;
+}
+
+static nsresult
+Convert(bthf_nrec_t aIn, BluetoothHandsfreeNRECState& aOut)
+{
+  static const BluetoothHandsfreeNRECState sNRECState[] = {
+    CONVERT(BTHF_NREC_STOP, HFP_NREC_STOPPED),
+    CONVERT(BTHF_NREC_START, HFP_NREC_STARTED)
+  };
+  if (aIn >= MOZ_ARRAY_LENGTH(sNRECState)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sNRECState[aIn];
+  return NS_OK;
+}
+
+static nsresult
+Convert(bthf_vr_state_t aIn, BluetoothHandsfreeVoiceRecognitionState& aOut)
+{
+  static const BluetoothHandsfreeVoiceRecognitionState
+    sVoiceRecognitionState[] = {
+    CONVERT(BTHF_VR_STATE_STOPPED, HFP_VOICE_RECOGNITION_STOPPED),
+    CONVERT(BTHF_VR_STATE_STARTED, HFP_VOICE_RECOGNITION_STARTED)
+  };
+  if (aIn >= MOZ_ARRAY_LENGTH(sVoiceRecognitionState)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sVoiceRecognitionState[aIn];
+  return NS_OK;
+}
+
+static nsresult
+Convert(bthf_volume_type_t aIn, BluetoothHandsfreeVolumeType& aOut)
+{
+  static const BluetoothHandsfreeVolumeType sVolumeType[] = {
+    CONVERT(BTHF_VOLUME_TYPE_SPK, HFP_VOLUME_TYPE_SPEAKER),
+    CONVERT(BTHF_VOLUME_TYPE_MIC, HFP_VOLUME_TYPE_MICROPHONE)
+  };
+  if (aIn >= MOZ_ARRAY_LENGTH(sVolumeType)) {
+    return NS_ERROR_ILLEGAL_VALUE;
+  }
+  aOut = sVolumeType[aIn];
+  return NS_OK;
+}
+
 #if ANDROID_VERSION >= 18
 static nsresult
 Convert(ControlPlayStatus aIn, btrc_play_status_t& aOut)
 {
   static const btrc_play_status_t sPlayStatus[] = {
     CONVERT(PLAYSTATUS_STOPPED, BTRC_PLAYSTATE_STOPPED),
     CONVERT(PLAYSTATUS_PLAYING, BTRC_PLAYSTATE_PLAYING),
     CONVERT(PLAYSTATUS_PAUSED, BTRC_PLAYSTATE_PAUSED),
@@ -949,16 +1060,70 @@ private:
   Tin2 mArg2;
   Tin3 mArg3;
 };
 
 //
 // Notification handling
 //
 
+template <typename ObjectWrapper, typename Res>
+class BluetoothNotificationRunnable0 : public nsRunnable
+{
+public:
+  typedef typename ObjectWrapper::ObjectType  ObjectType;
+  typedef BluetoothNotificationRunnable0<ObjectWrapper, Res> SelfType;
+
+  static already_AddRefed<SelfType> Create(Res (ObjectType::*aMethod)())
+  {
+    nsRefPtr<SelfType> runnable(new SelfType(aMethod));
+
+    return runnable.forget();
+  }
+
+  static void
+  Dispatch(Res (ObjectType::*aMethod)())
+  {
+    nsRefPtr<SelfType> runnable = Create(aMethod);
+
+    if (!runnable) {
+      BT_WARNING("BluetoothNotificationRunnable0::Create failed");
+      return;
+    }
+    nsresult rv = NS_DispatchToMainThread(runnable);
+    if (NS_FAILED(rv)) {
+      BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
+    }
+  }
+
+  NS_METHOD
+  Run() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    ObjectType* obj = ObjectWrapper::GetInstance();
+
+    if (!obj) {
+      BT_WARNING("Notification handler not initialized");
+    } else {
+      ((*obj).*mMethod)();
+    }
+    return NS_OK;
+  }
+
+private:
+  BluetoothNotificationRunnable0(Res (ObjectType::*aMethod)())
+  : mMethod(aMethod)
+  {
+    MOZ_ASSERT(mMethod);
+  }
+
+  Res (ObjectType::*mMethod)();
+};
+
 template <typename ObjectWrapper, typename Res,
           typename Tin1, typename Arg1=Tin1>
 class BluetoothNotificationRunnable1 : public nsRunnable
 {
 public:
   typedef typename ObjectWrapper::ObjectType  ObjectType;
   typedef BluetoothNotificationRunnable1<ObjectWrapper, Res,
                                          Tin1, Arg1> SelfType;
@@ -1915,31 +2080,279 @@ DispatchBluetoothHandsfreeResult(
   }
   nsresult rv = NS_DispatchToMainThread(runnable);
   if (NS_FAILED(rv)) {
     BT_WARNING("NS_DispatchToMainThread failed: %X", rv);
   }
   return rv;
 }
 
+// Notification handling
+//
+
+BluetoothHandsfreeNotificationHandler::
+  ~BluetoothHandsfreeNotificationHandler()
+{ }
+
+static BluetoothHandsfreeNotificationHandler* sHandsfreeNotificationHandler;
+
+struct BluetoothHandsfreeCallback
+{
+  class HandsfreeNotificationHandlerWrapper
+  {
+  public:
+    typedef BluetoothHandsfreeNotificationHandler ObjectType;
+
+    static ObjectType* GetInstance()
+    {
+      MOZ_ASSERT(NS_IsMainThread());
+
+      return sHandsfreeNotificationHandler;
+    }
+  };
+
+  // Notifications
+
+  typedef BluetoothNotificationRunnable2<HandsfreeNotificationHandlerWrapper,
+                                         void,
+                                         BluetoothHandsfreeConnectionState,
+                                         nsString,
+                                         BluetoothHandsfreeConnectionState,
+                                         const nsAString&>
+    ConnectionStateNotification;
+
+  typedef BluetoothNotificationRunnable2<HandsfreeNotificationHandlerWrapper,
+                                         void,
+                                         BluetoothHandsfreeAudioState,
+                                         nsString,
+                                         BluetoothHandsfreeAudioState,
+                                         const nsAString&>
+    AudioStateNotification;
+
+  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
+                                         void,
+                                         BluetoothHandsfreeVoiceRecognitionState>
+    VoiceRecognitionNotification;
+
+  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
+                                         void>
+    AnswerCallNotification;
+
+  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
+                                         void>
+    HangupCallNotification;
+
+  typedef BluetoothNotificationRunnable2<HandsfreeNotificationHandlerWrapper,
+                                         void,
+                                         BluetoothHandsfreeVolumeType, int>
+    VolumeNotification;
+
+  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
+                                         void, nsString, const nsAString&>
+    DialCallNotification;
+
+  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
+                                         void, char>
+    DtmfNotification;
+
+  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
+                                         void,
+                                         BluetoothHandsfreeNRECState>
+    NRECNotification;
+
+  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
+                                         void,
+                                         BluetoothHandsfreeCallHoldType>
+    CallHoldNotification;
+
+  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
+                                         void>
+    CnumNotification;
+
+  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
+                                         void>
+    CindNotification;
+
+  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
+                                         void>
+    CopsNotification;
+
+  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
+                                         void>
+    ClccNotification;
+
+  typedef BluetoothNotificationRunnable1<HandsfreeNotificationHandlerWrapper,
+                                         void, nsCString, const nsACString&>
+    UnknownAtNotification;
+
+  typedef BluetoothNotificationRunnable0<HandsfreeNotificationHandlerWrapper,
+                                         void>
+    KeyPressedNotification;
+
+  // Bluedroid Handsfree callbacks
+
+  static void
+  ConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddr)
+  {
+    ConnectionStateNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::ConnectionStateNotification,
+      aState, aBdAddr);
+  }
+
+  static void
+  AudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddr)
+  {
+    AudioStateNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::AudioStateNotification,
+      aState, aBdAddr);
+  }
+
+  static void
+  VoiceRecognition(bthf_vr_state_t aState)
+  {
+    VoiceRecognitionNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::VoiceRecognitionNotification,
+      aState);
+  }
+
+  static void
+  AnswerCall()
+  {
+    AnswerCallNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::AnswerCallNotification);
+  }
+
+  static void
+  HangupCall()
+  {
+    HangupCallNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::HangupCallNotification);
+  }
+
+  static void
+  Volume(bthf_volume_type_t aType, int aVolume)
+  {
+    VolumeNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::VolumeNotification,
+      aType, aVolume);
+  }
+
+  static void
+  DialCall(char* aNumber)
+  {
+    DialCallNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::DialCallNotification, aNumber);
+  }
+
+  static void
+  Dtmf(char aDtmf)
+  {
+    DtmfNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::DtmfNotification, aDtmf);
+  }
+
+  static void
+  NoiseReductionEchoCancellation(bthf_nrec_t aNrec)
+  {
+    NRECNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::NRECNotification, aNrec);
+  }
+
+  static void
+  CallHold(bthf_chld_type_t aChld)
+  {
+    CallHoldNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::CallHoldNotification, aChld);
+  }
+
+  static void
+  Cnum()
+  {
+    CnumNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::CnumNotification);
+  }
+
+  static void
+  Cind()
+  {
+    CindNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::CindNotification);
+  }
+
+  static void
+  Cops()
+  {
+    CopsNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::CopsNotification);
+  }
+
+  static void
+  Clcc()
+  {
+    ClccNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::ClccNotification);
+  }
+
+  static void
+  UnknownAt(char* aAtString)
+  {
+    UnknownAtNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::UnknownAtNotification,
+      aAtString);
+  }
+
+  static void
+  KeyPressed()
+  {
+    KeyPressedNotification::Dispatch(
+      &BluetoothHandsfreeNotificationHandler::KeyPressedNotification);
+  }
+};
+
+// Interface
+//
+
 BluetoothHandsfreeInterface::BluetoothHandsfreeInterface(
   const bthf_interface_t* aInterface)
 : mInterface(aInterface)
 {
   MOZ_ASSERT(mInterface);
 }
 
 BluetoothHandsfreeInterface::~BluetoothHandsfreeInterface()
 { }
 
 void
-BluetoothHandsfreeInterface::Init(bthf_callbacks_t* aCallbacks,
-                                  BluetoothHandsfreeResultHandler* aRes)
+BluetoothHandsfreeInterface::Init(
+  BluetoothHandsfreeNotificationHandler* aNotificationHandler,
+  BluetoothHandsfreeResultHandler* aRes)
 {
-  bt_status_t status = mInterface->init(aCallbacks);
+  static bthf_callbacks_t sCallbacks = {
+    .size = sizeof(sCallbacks),
+    .connection_state_cb = BluetoothHandsfreeCallback::ConnectionState,
+    .audio_state_cb = BluetoothHandsfreeCallback::AudioState,
+    .vr_cmd_cb = BluetoothHandsfreeCallback::VoiceRecognition,
+    .answer_call_cmd_cb = BluetoothHandsfreeCallback::AnswerCall,
+    .hangup_call_cmd_cb = BluetoothHandsfreeCallback::HangupCall,
+    .volume_cmd_cb = BluetoothHandsfreeCallback::Volume,
+    .dial_call_cmd_cb = BluetoothHandsfreeCallback::DialCall,
+    .dtmf_cmd_cb = BluetoothHandsfreeCallback::Dtmf,
+    .nrec_cmd_cb = BluetoothHandsfreeCallback::NoiseReductionEchoCancellation,
+    .chld_cmd_cb = BluetoothHandsfreeCallback::CallHold,
+    .cnum_cmd_cb = BluetoothHandsfreeCallback::Cnum,
+    .cind_cmd_cb = BluetoothHandsfreeCallback::Cind,
+    .cops_cmd_cb = BluetoothHandsfreeCallback::Cops,
+    .clcc_cmd_cb = BluetoothHandsfreeCallback::Clcc,
+    .unknown_at_cmd_cb = BluetoothHandsfreeCallback::UnknownAt,
+    .key_pressed_cmd_cb = BluetoothHandsfreeCallback::KeyPressed
+  };
+
+  sHandsfreeNotificationHandler = aNotificationHandler;
+
+  bt_status_t status = mInterface->init(&sCallbacks);
 
   if (aRes) {
     DispatchBluetoothHandsfreeResult(aRes,
                                      &BluetoothHandsfreeResultHandler::Init,
                                      ConvertDefault(status, STATUS_FAIL));
   }
 }
 
--- a/dom/bluetooth2/bluedroid/BluetoothInterface.h
+++ b/dom/bluetooth2/bluedroid/BluetoothInterface.h
@@ -72,16 +72,92 @@ protected:
 private:
   const btsock_interface_t* mInterface;
 };
 
 //
 // Handsfree Interface
 //
 
+class BluetoothHandsfreeNotificationHandler
+{
+public:
+  virtual ~BluetoothHandsfreeNotificationHandler();
+
+  virtual void
+  ConnectionStateNotification(BluetoothHandsfreeConnectionState aState,
+                              const nsAString& aBdAddr)
+  { }
+
+  virtual void
+  AudioStateNotification(BluetoothHandsfreeAudioState aState,
+                         const nsAString& aBdAddr)
+  { }
+
+  virtual void
+  VoiceRecognitionNotification(BluetoothHandsfreeVoiceRecognitionState aState)
+  { }
+
+  virtual void
+  AnswerCallNotification()
+  { }
+
+  virtual void
+  HangupCallNotification()
+  { }
+
+  virtual void
+  VolumeNotification(BluetoothHandsfreeVolumeType aType, int aVolume)
+  { }
+
+  virtual void
+  DialCallNotification(const nsAString& aNumber)
+  { }
+
+  virtual void
+  DtmfNotification(char aDtmf)
+  { }
+
+  virtual void
+  NRECNotification(BluetoothHandsfreeNRECState aNrec)
+  { }
+
+  virtual void
+  CallHoldNotification(BluetoothHandsfreeCallHoldType aChld)
+  { }
+
+  virtual void
+  CnumNotification()
+  { }
+
+  virtual void
+  CindNotification()
+  { }
+
+  virtual void
+  CopsNotification()
+  { }
+
+  virtual void
+  ClccNotification()
+  { }
+
+  virtual void
+  UnknownAtNotification(const nsACString& aAtString)
+  { }
+
+  virtual void
+  KeyPressedNotification()
+  { }
+
+protected:
+  BluetoothHandsfreeNotificationHandler()
+  { }
+};
+
 class BluetoothHandsfreeResultHandler
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BluetoothHandsfreeResultHandler)
 
   virtual ~BluetoothHandsfreeResultHandler() { }
 
   virtual void OnError(BluetoothStatus aStatus)
@@ -112,17 +188,17 @@ public:
   virtual void PhoneStateChange() { }
 };
 
 class BluetoothHandsfreeInterface
 {
 public:
   friend class BluetoothInterface;
 
-  void Init(bthf_callbacks_t* aCallbacks,
+  void Init(BluetoothHandsfreeNotificationHandler* aNotificationHandler,
             BluetoothHandsfreeResultHandler* aRes);
   void Cleanup(BluetoothHandsfreeResultHandler* aRes);
 
   /* Connect / Disconnect */
 
   void Connect(const nsAString& aBdAddr,
                BluetoothHandsfreeResultHandler* aRes);
   void Disconnect(const nsAString& aBdAddr,
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -26,31 +26,16 @@
 #include "nsITelephonyService.h"
 #include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 #define MOZSETTINGS_CHANGED_ID               "mozsettings-changed"
 #define AUDIO_VOLUME_BT_SCO_ID               "audio.volume.bt_sco"
 
-/**
- * Dispatch task with arguments to main thread.
- */
-#define BT_HF_DISPATCH_MAIN(args...) \
-  NS_DispatchToMainThread(new MainThreadTask(args))
-
-/**
- * Process bluedroid callbacks with corresponding handlers.
- */
-#define BT_HF_PROCESS_CB(func, args...)          \
-  do {                                           \
-    NS_ENSURE_TRUE_VOID(sBluetoothHfpManager);   \
-    sBluetoothHfpManager->func(args);            \
-  } while(0)
-
 using namespace mozilla;
 using namespace mozilla::ipc;
 USING_BLUETOOTH_NAMESPACE
 
 namespace {
   StaticRefPtr<BluetoothHfpManager> sBluetoothHfpManager;
   static BluetoothHandsfreeInterface* sBluetoothHfpInterface = nullptr;
 
@@ -62,141 +47,16 @@ namespace {
 
   // Wait 3.7 seconds until Dialer stops playing busy tone. '3' seconds is the
   // time window set in Dialer and the extra '0.7' second is a magic number.
   // The mechanism should be revised once we know the exact time at which
   // Dialer stops playing.
   static int sBusyToneInterval = 3700; //unit: ms
 } // anonymous namespace
 
-// Main thread task commands
-enum MainThreadTaskCmd {
-  NOTIFY_CONN_STATE_CHANGED,
-  NOTIFY_DIALER,
-  NOTIFY_SCO_VOLUME_CHANGED,
-  POST_TASK_RESPOND_TO_BLDN,
-  POST_TASK_CLOSE_SCO
-};
-
-static void
-ConnectionStateCallback(bthf_connection_state_t state, bt_bdaddr_t* bd_addr)
-{
-  BT_HF_PROCESS_CB(ProcessConnectionState, state, bd_addr);
-}
-
-static void
-AudioStateCallback(bthf_audio_state_t state, bt_bdaddr_t* bd_addr)
-{
-  BT_HF_PROCESS_CB(ProcessAudioState, state, bd_addr);
-}
-
-static void
-VoiceRecognitionCallback(bthf_vr_state_t state)
-{
-  // No support
-}
-
-static void
-AnswerCallCallback()
-{
-  BT_HF_PROCESS_CB(ProcessAnswerCall);
-}
-
-static void
-HangupCallCallback()
-{
-  BT_HF_PROCESS_CB(ProcessHangupCall);
-}
-
-static void
-VolumeControlCallback(bthf_volume_type_t type, int volume)
-{
-  BT_HF_PROCESS_CB(ProcessVolumeControl, type, volume);
-}
-
-static void
-DialCallCallback(char *number)
-{
-  BT_HF_PROCESS_CB(ProcessDialCall, number);
-}
-
-static void
-DtmfCmdCallback(char dtmf)
-{
-  BT_HF_PROCESS_CB(ProcessDtmfCmd, dtmf);
-}
-
-static void
-NoiceReductionCallback(bthf_nrec_t nrec)
-{
-  // No support
-}
-
-static void
-AtChldCallback(bthf_chld_type_t chld)
-{
-  BT_HF_PROCESS_CB(ProcessAtChld, chld);
-}
-
-static void
-AtCnumCallback()
-{
-  BT_HF_PROCESS_CB(ProcessAtCnum);
-}
-
-static void
-AtCindCallback()
-{
-  BT_HF_PROCESS_CB(ProcessAtCind);
-}
-
-static void
-AtCopsCallback()
-{
-  BT_HF_PROCESS_CB(ProcessAtCops);
-}
-
-static void
-AtClccCallback()
-{
-  BT_HF_PROCESS_CB(ProcessAtClcc);
-}
-
-static void
-UnknownAtCallback(char *at_string)
-{
-  BT_HF_PROCESS_CB(ProcessUnknownAt, at_string);
-}
-
-static void
-KeyPressedCallback()
-{
-  BT_HF_PROCESS_CB(ProcessKeyPressed);
-}
-
-static bthf_callbacks_t sBluetoothHfpCallbacks = {
-  sizeof(sBluetoothHfpCallbacks),
-  ConnectionStateCallback,
-  AudioStateCallback,
-  VoiceRecognitionCallback,
-  AnswerCallCallback,
-  HangupCallCallback,
-  VolumeControlCallback,
-  DialCallCallback,
-  DtmfCmdCallback,
-  NoiceReductionCallback,
-  AtChldCallback,
-  AtCnumCallback,
-  AtCindCallback,
-  AtCopsCallback,
-  AtClccCallback,
-  UnknownAtCallback,
-  KeyPressedCallback
-};
-
 static bool
 IsValidDtmf(const char aChar) {
   // Valid DTMF: [*#0-9ABCD]
   return (aChar == '*' || aChar == '#') ||
          (aChar >= '0' && aChar <= '9') ||
          (aChar >= 'A' && aChar <= 'D');
 }
 
@@ -237,84 +97,44 @@ class BluetoothHfpManager::CloseScoTask 
 private:
   void Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(sBluetoothHfpManager);
     sBluetoothHfpManager->DisconnectSco();
   }
 };
 
+class BluetoothHfpManager::CloseScoRunnable : public nsRunnable
+{
+public:
+  NS_IMETHOD Run() MOZ_OVERRIDE
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    MessageLoop::current()->PostDelayedTask(
+      FROM_HERE, new CloseScoTask(), sBusyToneInterval);
+
+    return NS_OK;
+  }
+};
+
 class BluetoothHfpManager::RespondToBLDNTask : public Task
 {
 private:
   void Run() MOZ_OVERRIDE
   {
     MOZ_ASSERT(sBluetoothHfpManager);
 
     if (!sBluetoothHfpManager->mDialingRequestProcessed) {
       sBluetoothHfpManager->mDialingRequestProcessed = true;
       sBluetoothHfpManager->SendResponse(HFP_AT_RESPONSE_ERROR);
     }
   }
 };
 
-class BluetoothHfpManager::MainThreadTask : public nsRunnable
-{
-public:
-  MainThreadTask(const int aCommand,
-                 const nsAString& aParameter = EmptyString())
-    : mCommand(aCommand), mParameter(aParameter)
-  {
-  }
-
-  nsresult Run()
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-    MOZ_ASSERT(sBluetoothHfpManager);
-
-    switch (mCommand) {
-      case MainThreadTaskCmd::NOTIFY_CONN_STATE_CHANGED:
-        sBluetoothHfpManager->NotifyConnectionStateChanged(mParameter);
-        break;
-      case MainThreadTaskCmd::NOTIFY_DIALER:
-        sBluetoothHfpManager->NotifyDialer(mParameter);
-        break;
-      case MainThreadTaskCmd::NOTIFY_SCO_VOLUME_CHANGED:
-        {
-          nsCOMPtr<nsIObserverService> os =
-            mozilla::services::GetObserverService();
-          NS_ENSURE_TRUE(os, NS_OK);
-
-          os->NotifyObservers(nullptr, "bluetooth-volume-change",
-                              mParameter.get());
-        }
-        break;
-      case MainThreadTaskCmd::POST_TASK_RESPOND_TO_BLDN:
-        MessageLoop::current()->
-          PostDelayedTask(FROM_HERE, new RespondToBLDNTask(),
-                          sWaitingForDialingInterval);
-        break;
-      case MainThreadTaskCmd::POST_TASK_CLOSE_SCO:
-        MessageLoop::current()->
-          PostDelayedTask(FROM_HERE, new CloseScoTask(),
-                          sBusyToneInterval);
-        break;
-      default:
-        BT_WARNING("MainThreadTask: Unknown command %d", mCommand);
-        break;
-    }
-
-    return NS_OK;
-  }
-
-private:
-  int mCommand;
-  nsString mParameter;
-};
-
 NS_IMPL_ISUPPORTS(BluetoothHfpManager::GetVolumeTask,
                   nsISettingsServiceCallback);
 
 /**
  *  Call
  */
 Call::Call()
 {
@@ -464,17 +284,19 @@ public:
      * |BluetoothHandsfreeInterface| has now been cleaned
      * up, so we start initialization.
      */
     RunInit();
   }
 
   void RunInit()
   {
-    mInterface->Init(&sBluetoothHfpCallbacks, this);
+    BluetoothHfpManager* hfpManager = BluetoothHfpManager::Get();
+
+    mInterface->Init(hfpManager, this);
   }
 
 private:
   BluetoothHandsfreeInterface* mInterface;
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
 class InitResultHandlerRunnable MOZ_FINAL : public nsRunnable
@@ -659,287 +481,16 @@ BluetoothHfpManager::Notify(const hal::B
 {
   // Range of battery level: [0, 1], double
   // Range of CIND::BATTCHG: [0, 5], int
   mBattChg = (int) round(aBatteryInfo.level() * 5.0);
   UpdateDeviceCIND();
 }
 
 void
-BluetoothHfpManager::ProcessConnectionState(bthf_connection_state_t aState,
-                                            bt_bdaddr_t* aBdAddress)
-{
-  BT_LOGR("state %d", aState);
-
-  mPrevConnectionState = mConnectionState;
-  mConnectionState = aState;
-
-  if (aState == BTHF_CONNECTION_STATE_SLC_CONNECTED) {
-    BdAddressTypeToString(aBdAddress, mDeviceAddress);
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_CONN_STATE_CHANGED,
-                        NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
-  } else if (aState == BTHF_CONNECTION_STATE_DISCONNECTED) {
-    DisconnectSco();
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_CONN_STATE_CHANGED,
-                        NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
-  }
-}
-
-void
-BluetoothHfpManager::ProcessAudioState(bthf_audio_state_t aState,
-                                       bt_bdaddr_t* aBdAddress)
-{
-  BT_LOGR("state %d", aState);
-
-  mAudioState = aState;
-
-  if (aState == BTHF_AUDIO_STATE_CONNECTED ||
-      aState == BTHF_AUDIO_STATE_DISCONNECTED) {
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_CONN_STATE_CHANGED,
-                        NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
-  }
-}
-
-void
-BluetoothHfpManager::ProcessAnswerCall()
-{
-  BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
-                      NS_LITERAL_STRING("ATA"));
-}
-
-void
-BluetoothHfpManager::ProcessHangupCall()
-{
-  BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
-                      NS_LITERAL_STRING("CHUP"));
-}
-
-void
-BluetoothHfpManager::ProcessVolumeControl(bthf_volume_type_t aType,
-                                          int aVolume)
-{
-  NS_ENSURE_TRUE_VOID(aVolume >= 0 && aVolume <= 15);
-
-  if (aType == BTHF_VOLUME_TYPE_MIC) {
-    mCurrentVgm = aVolume;
-  } else if (aType == BTHF_VOLUME_TYPE_SPK) {
-    mReceiveVgsFlag = true;
-
-    if (aVolume == mCurrentVgs) {
-      // Keep current volume
-      return;
-    }
-
-    nsString data;
-    data.AppendInt(aVolume);
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_SCO_VOLUME_CHANGED, data);
-  }
-}
-
-void
-BluetoothHfpManager::ProcessDtmfCmd(char aDtmf)
-{
-  NS_ENSURE_TRUE_VOID(IsValidDtmf(aDtmf));
-
-  nsAutoCString message("VTS=");
-  message += aDtmf;
-  BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
-                      NS_ConvertUTF8toUTF16(message));
-}
-
-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(HFP_AT_RESPONSE_OK);
-}
-
-void BluetoothHfpManager::ProcessDialCall(char *aNumber)
-{
-  nsAutoCString message(aNumber);
-
-  // There are three cases based on aNumber,
-  // 1) Empty value:    Redial, BLDN
-  // 2) >xxx:           Memory dial, ATD>xxx
-  // 3) xxx:            Normal dial, ATDxxx
-  // We need to respond OK/Error for dial requests for every case listed above,
-  // 1) and 2):         Respond in either RespondToBLDNTask or
-  //                    HandleCallStateChanged()
-  // 3):                Respond here
-  if (message.IsEmpty()) {
-    mDialingRequestProcessed = false;
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
-                        NS_LITERAL_STRING("BLDN"));
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::POST_TASK_RESPOND_TO_BLDN);
-  } else if (message[0] == '>') {
-    mDialingRequestProcessed = false;
-    nsAutoCString newMsg("ATD");
-    newMsg += StringHead(message, message.Length() - 1);
-    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(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(HFP_AT_RESPONSE_OK);
-}
-
-class CindResponseResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
-{
-public:
-  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);
-  BluetoothHandsfreeCallState callState =
-    ConvertToBluetoothHandsfreeCallState(GetCallSetupState());
-
-  sBluetoothHfpInterface->CindResponse(mService, numActive, numHeld,
-                                       callState, mSignal, mRoam, mBattChg,
-                                       new CindResponseResultHandler());
-}
-
-class CopsResponseResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
-{
-public:
-  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
-  {
-    BT_WARNING("BluetoothHandsfreeInterface::CopsResponse failed: %d",
-               (int)aStatus);
-  }
-};
-
-void
-BluetoothHfpManager::ProcessAtCops()
-{
-  NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
-
-  sBluetoothHfpInterface->CopsResponse(
-    NS_ConvertUTF16toUTF8(mOperatorName).get(),
-    new CopsResponseResultHandler());
-}
-
-void
-BluetoothHfpManager::ProcessAtClcc()
-{
-  uint32_t callNumbers = mCurrentCallArray.Length();
-  uint32_t i;
-  for (i = 1; i < callNumbers; i++) {
-    SendCLCC(mCurrentCallArray[i], i);
-  }
-
-  if (!mCdmaSecondCall.mNumber.IsEmpty()) {
-    MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
-    MOZ_ASSERT(i == 2);
-
-    SendCLCC(mCdmaSecondCall, 2);
-  }
-
-  SendResponse(HFP_AT_RESPONSE_OK);
-}
-
-class AtResponseResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
-{
-public:
-  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(HFP_AT_RESPONSE_ERROR, 0,
-                                     new AtResponseResultHandler());
-}
-
-void
-BluetoothHfpManager::ProcessKeyPressed()
-{
-  bool hasActiveCall =
-    (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED) > 0);
-
-  // Refer to AOSP HeadsetStateMachine.processKeyPressed
-  if (FindFirstCall(nsITelephonyService::CALL_STATE_INCOMING)
-      && !hasActiveCall) {
-    /**
-     * Bluetooth HSP spec 4.2.2
-     * There is an incoming call, notify Dialer to pick up the phone call
-     * and SCO will be established after we get the CallStateChanged event
-     * indicating the call is answered successfully.
-     */
-    ProcessAnswerCall();
-  } else if (hasActiveCall) {
-    if (!IsScoConnected()) {
-      /**
-       * Bluetooth HSP spec 4.3
-       * If there's no SCO, set up a SCO link.
-       */
-      ConnectSco();
-    } else {
-      /**
-       * Bluetooth HSP spec 4.5
-       * There are two ways to release SCO: sending CHUP to dialer or closing
-       * SCO socket directly. We notify dialer only if there is at least one
-       * active call.
-       */
-      ProcessHangupCall();
-    }
-  } else {
-    // BLDN
-    mDialingRequestProcessed = false;
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::NOTIFY_DIALER,
-                        NS_LITERAL_STRING("BLDN"));
-    BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::POST_TASK_RESPOND_TO_BLDN);
-  }
-}
-
-void
 BluetoothHfpManager::NotifyConnectionStateChanged(const nsAString& aType)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Notify Gecko observers
   nsCOMPtr<nsIObserverService> obs =
     do_GetService("@mozilla.org/observer-service;1");
   NS_ENSURE_TRUE_VOID(obs);
@@ -1202,16 +753,27 @@ void
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->FormattedAtResponse(
     aMessage, new FormattedAtResponseResultHandler());
 }
 
+class AtResponseResultHandler MOZ_FINAL
+: public BluetoothHandsfreeResultHandler
+{
+public:
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
+  {
+    BT_WARNING("BluetoothHandsfreeInterface::AtResponse failed: %d",
+               (int)aStatus);
+  }
+};
+
 void
 BluetoothHfpManager::SendResponse(BluetoothHandsfreeAtResponse aResponseCode)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->AtResponse(
     aResponseCode, 0, new AtResponseResultHandler());
 }
@@ -1419,17 +981,17 @@ BluetoothHfpManager::HandleCallStateChan
       // -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,
         // we postpone the timing of dropping SCO.
         if (aError.Equals(NS_LITERAL_STRING("BusyError"))) {
           // FIXME: UpdatePhoneCIND later since it causes SCO close but
           // Dialer is still playing busy tone via HF.
-          BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::POST_TASK_CLOSE_SCO);
+          NS_DispatchToMainThread(new CloseScoRunnable());
         }
 
         ResetCallArray();
       }
       break;
     default:
       break;
   }
@@ -1715,9 +1277,307 @@ BluetoothHfpManager::OnGetServiceChannel
 }
 
 void
 BluetoothHfpManager::GetAddress(nsAString& aDeviceAddress)
 {
   aDeviceAddress = mDeviceAddress;
 }
 
+//
+// Bluetooth notifications
+//
+
+void
+BluetoothHfpManager::ConnectionStateNotification(
+  BluetoothHandsfreeConnectionState aState, const nsAString& aBdAddress)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BT_LOGR("state %d", aState);
+
+  mPrevConnectionState = mConnectionState;
+  mConnectionState = aState;
+
+  if (aState == HFP_CONNECTION_STATE_SLC_CONNECTED) {
+    mDeviceAddress = aBdAddress;
+    NotifyConnectionStateChanged(
+      NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
+
+  } else if (aState == HFP_CONNECTION_STATE_DISCONNECTED) {
+    DisconnectSco();
+    NotifyConnectionStateChanged(
+      NS_LITERAL_STRING(BLUETOOTH_HFP_STATUS_CHANGED_ID));
+  }
+}
+
+void
+BluetoothHfpManager::AudioStateNotification(
+  BluetoothHandsfreeAudioState aState, const nsAString& aBdAddress)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BT_LOGR("state %d", aState);
+
+  mAudioState = aState;
+
+  if (aState == HFP_AUDIO_STATE_CONNECTED ||
+      aState == HFP_AUDIO_STATE_DISCONNECTED) {
+    NotifyConnectionStateChanged(
+      NS_LITERAL_STRING(BLUETOOTH_SCO_STATUS_CHANGED_ID));
+  }
+}
+
+void
+BluetoothHfpManager::AnswerCallNotification()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  NotifyDialer(NS_LITERAL_STRING("ATA"));
+}
+
+void
+BluetoothHfpManager::HangupCallNotification()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  NotifyDialer(NS_LITERAL_STRING("CHUP"));
+}
+
+void
+BluetoothHfpManager::VolumeNotification(
+  BluetoothHandsfreeVolumeType aType, int aVolume)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  NS_ENSURE_TRUE_VOID(aVolume >= 0 && aVolume <= 15);
+
+  if (aType == HFP_VOLUME_TYPE_MICROPHONE) {
+    mCurrentVgm = aVolume;
+  } else if (aType == HFP_VOLUME_TYPE_SPEAKER) {
+    mReceiveVgsFlag = true;
+
+    if (aVolume == mCurrentVgs) {
+      // Keep current volume
+      return;
+    }
+
+    nsString data;
+    data.AppendInt(aVolume);
+
+    nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+    NS_ENSURE_TRUE_VOID(os);
+
+    os->NotifyObservers(nullptr, "bluetooth-volume-change", data.get());
+  }
+}
+
+void
+BluetoothHfpManager::DtmfNotification(char aDtmf)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  NS_ENSURE_TRUE_VOID(IsValidDtmf(aDtmf));
+
+  nsAutoCString message("VTS=");
+  message += aDtmf;
+  NotifyDialer(NS_ConvertUTF8toUTF16(message));
+}
+
+void
+BluetoothHfpManager::CallHoldNotification(BluetoothHandsfreeCallHoldType aChld)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  SendResponse(HFP_AT_RESPONSE_OK);
+
+  nsAutoCString message("CHLD=");
+  message.AppendInt((int)aChld);
+  NotifyDialer(NS_ConvertUTF8toUTF16(message));
+}
+
+void BluetoothHfpManager::DialCallNotification(const nsAString& aNumber)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCString message = NS_ConvertUTF16toUTF8(aNumber);
+
+  // There are three cases based on aNumber,
+  // 1) Empty value:    Redial, BLDN
+  // 2) >xxx:           Memory dial, ATD>xxx
+  // 3) xxx:            Normal dial, ATDxxx
+  // We need to respond OK/Error for dial requests for every case listed above,
+  // 1) and 2):         Respond in either RespondToBLDNTask or
+  //                    HandleCallStateChanged()
+  // 3):                Respond here
+  if (message.IsEmpty()) {
+    mDialingRequestProcessed = false;
+    NotifyDialer(NS_LITERAL_STRING("BLDN"));
+
+    MessageLoop::current()->PostDelayedTask(FROM_HERE,
+                                            new RespondToBLDNTask(),
+                                            sWaitingForDialingInterval);
+  } else if (message[0] == '>') {
+    mDialingRequestProcessed = false;
+
+    nsAutoCString newMsg("ATD");
+    newMsg += StringHead(message, message.Length() - 1);
+    NotifyDialer(NS_ConvertUTF8toUTF16(newMsg));
+
+    MessageLoop::current()->PostDelayedTask(FROM_HERE,
+                                            new RespondToBLDNTask(),
+                                            sWaitingForDialingInterval);
+  } else {
+    SendResponse(HFP_AT_RESPONSE_OK);
+
+    nsAutoCString newMsg("ATD");
+    newMsg += StringHead(message, message.Length() - 1);
+    NotifyDialer(NS_ConvertUTF8toUTF16(newMsg));
+  }
+}
+
+void
+BluetoothHfpManager::CnumNotification()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  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(HFP_AT_RESPONSE_OK);
+}
+
+class CindResponseResultHandler MOZ_FINAL
+: public BluetoothHandsfreeResultHandler
+{
+public:
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
+  {
+    BT_WARNING("BluetoothHandsfreeInterface::CindResponse failed: %d",
+               (int)aStatus);
+  }
+};
+
+void
+BluetoothHfpManager::CindNotification()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
+
+  int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
+  int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
+  BluetoothHandsfreeCallState callState =
+    ConvertToBluetoothHandsfreeCallState(GetCallSetupState());
+
+  sBluetoothHfpInterface->CindResponse(mService, numActive, numHeld,
+                                       callState, mSignal, mRoam, mBattChg,
+                                       new CindResponseResultHandler());
+}
+
+class CopsResponseResultHandler MOZ_FINAL
+: public BluetoothHandsfreeResultHandler
+{
+public:
+  void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
+  {
+    BT_WARNING("BluetoothHandsfreeInterface::CopsResponse failed: %d",
+               (int)aStatus);
+  }
+};
+
+void
+BluetoothHfpManager::CopsNotification()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
+
+  sBluetoothHfpInterface->CopsResponse(
+    NS_ConvertUTF16toUTF8(mOperatorName).get(),
+    new CopsResponseResultHandler());
+}
+
+void
+BluetoothHfpManager::ClccNotification()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  uint32_t callNumbers = mCurrentCallArray.Length();
+  uint32_t i;
+  for (i = 1; i < callNumbers; i++) {
+    SendCLCC(mCurrentCallArray[i], i);
+  }
+
+  if (!mCdmaSecondCall.mNumber.IsEmpty()) {
+    MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
+    MOZ_ASSERT(i == 2);
+
+    SendCLCC(mCdmaSecondCall, 2);
+  }
+
+  SendResponse(HFP_AT_RESPONSE_OK);
+}
+
+void
+BluetoothHfpManager::UnknownAtNotification(const nsACString& aAtString)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  BT_LOGR("[%s]", nsCString(aAtString).get());
+
+  SendResponse(HFP_AT_RESPONSE_ERROR);
+}
+
+void
+BluetoothHfpManager::KeyPressedNotification()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  bool hasActiveCall =
+    (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED) > 0);
+
+  // Refer to AOSP HeadsetStateMachine.processKeyPressed
+  if (FindFirstCall(nsITelephonyService::CALL_STATE_INCOMING)
+      && !hasActiveCall) {
+    /**
+     * Bluetooth HSP spec 4.2.2
+     * There is an incoming call, notify Dialer to pick up the phone call
+     * and SCO will be established after we get the CallStateChanged event
+     * indicating the call is answered successfully.
+     */
+    NotifyDialer(NS_LITERAL_STRING("ATA"));
+  } else if (hasActiveCall) {
+    if (!IsScoConnected()) {
+      /**
+       * Bluetooth HSP spec 4.3
+       * If there's no SCO, set up a SCO link.
+       */
+      ConnectSco();
+    } else {
+      /**
+       * Bluetooth HSP spec 4.5
+       * There are two ways to release SCO: sending CHUP to dialer or closing
+       * SCO socket directly. We notify dialer only if there is at least one
+       * active call.
+       */
+      NotifyDialer(NS_LITERAL_STRING("CHUP"));
+    }
+  } else {
+    // BLDN
+    mDialingRequestProcessed = false;
+
+    NotifyDialer(NS_LITERAL_STRING("BLDN"));
+
+    MessageLoop::current()->PostDelayedTask(FROM_HERE,
+                                            new RespondToBLDNTask(),
+                                            sWaitingForDialingInterval);
+  }
+}
+
 NS_IMPL_ISUPPORTS(BluetoothHfpManager, nsIObserver)
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.h
@@ -66,16 +66,17 @@ public:
 
   uint16_t mState;
   nsString mNumber;
   BluetoothHandsfreeCallDirection mDirection;
   BluetoothHandsfreeCallAddressType mType;
 };
 
 class BluetoothHfpManager : public BluetoothHfpManagerBase
+                          , public BluetoothHandsfreeNotificationHandler
                           , public BatteryObserver
 {
 public:
   BT_DECL_HFP_MGR_BASE
 
   void OnConnectError();
   void OnDisconnectError();
 
@@ -97,43 +98,49 @@ public:
    */
   void HandleCallStateChanged(uint32_t aCallIndex, uint16_t aCallState,
                               const nsAString& aError, const nsAString& aNumber,
                               const bool aIsOutgoing, const bool aIsConference,
                               bool aSend);
   void HandleIccInfoChanged(uint32_t aClientId);
   void HandleVoiceConnectionChanged(uint32_t aClientId);
 
-  // Bluedroid hfp callback handlers
-  void ProcessConnectionState(bthf_connection_state_t aState, bt_bdaddr_t* aBdAddress);
-  void ProcessAudioState(bthf_audio_state_t aState, bt_bdaddr_t* aBdAddress);
-  void ProcessAnswerCall();
-  void ProcessHangupCall();
-  void ProcessVolumeControl(bthf_volume_type_t aType, int aVolume);
-  void ProcessDialCall(char *aNumber);
-  void ProcessDtmfCmd(char aDtmf);
-  void ProcessAtChld(bthf_chld_type_t aChld);
-  void ProcessAtCnum();
-  void ProcessAtCind();
-  void ProcessAtCops();
-  void ProcessAtClcc();
-  void ProcessUnknownAt(char *aAtString);
-  void ProcessKeyPressed();
-
   // CDMA-specific functions
   void UpdateSecondNumber(const nsAString& aNumber);
   void AnswerWaitingCall();
   void IgnoreWaitingCall();
   void ToggleCalls();
 
+  //
+  // Bluetooth notifications
+  //
+
+  void ConnectionStateNotification(BluetoothHandsfreeConnectionState aState,
+                                   const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void AudioStateNotification(BluetoothHandsfreeAudioState aState,
+                              const nsAString& aBdAddress) MOZ_OVERRIDE;
+  void AnswerCallNotification() MOZ_OVERRIDE;
+  void HangupCallNotification() MOZ_OVERRIDE;
+  void VolumeNotification(BluetoothHandsfreeVolumeType aType,
+                          int aVolume) MOZ_OVERRIDE;
+  void DtmfNotification(char aDtmf) MOZ_OVERRIDE;
+  void CallHoldNotification(BluetoothHandsfreeCallHoldType aChld) MOZ_OVERRIDE;
+  void DialCallNotification(const nsAString& aNumber) MOZ_OVERRIDE;
+  void CnumNotification() MOZ_OVERRIDE;
+  void CindNotification() MOZ_OVERRIDE;
+  void CopsNotification() MOZ_OVERRIDE;
+  void ClccNotification() MOZ_OVERRIDE;
+  void UnknownAtNotification(const nsACString& aAtString) MOZ_OVERRIDE;
+  void KeyPressedNotification() MOZ_OVERRIDE;
+
 private:
   class GetVolumeTask;
   class CloseScoTask;
+  class CloseScoRunnable;
   class RespondToBLDNTask;
-  class MainThreadTask;
 
   friend class BluetoothHfpManagerObserver;
   friend class GetVolumeTask;
   friend class CloseScoTask;
   friend class RespondToBLDNTask;
   friend class MainThreadTask;
 
   BluetoothHfpManager();