merge b2g-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 12 May 2015 11:56:32 +0200
changeset 274042 8b64c75b0b86b63acc48d2cafb49bcfe79a3426e
parent 273992 502e1a5e722f10b2fd53db0c8bfccef239dd3ef9 (current diff)
parent 274041 70cee73f3db50c1ae5d86b020601134d53f9c368 (diff)
child 274091 0ca37b3cb73dcc1f087e4fea3193900efb423136
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone41.0a1
first release with
nightly linux32
8b64c75b0b86 / 41.0a1 / 20150512030215 / files
nightly linux64
8b64c75b0b86 / 41.0a1 / 20150512030215 / files
nightly mac
8b64c75b0b86 / 41.0a1 / 20150512030215 / files
nightly win32
8b64c75b0b86 / 41.0a1 / 20150512030215 / files
nightly win64
8b64c75b0b86 / 41.0a1 / 20150512030215 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge b2g-inbound to mozilla-central a=merge
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
+  <project name="platform_build" path="build" remote="b2g" revision="a8ace1361d702eef293e48f2ea525dac686daa86">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
@@ -107,17 +107,17 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="aac6c4bb59a6577c97cbda68699829b507b7490d"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="fbeca55f4695dd07c0291213403533b8fbca4885"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="92605aa35361ae4ae1e473781e40c1f6929f4ec4"/>
   <project name="platform/libcore" path="libcore" revision="e195beab082c09217318fc19250caeaf4c1bd800"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="feeb36c2bd4adfe285f98f5de92e0f3771b2c115"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="23404f05422c6bf3c39573325a4f4909167671b4"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="6a1bb59af65b6485b1090522f66fac95c3f9e22c"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="48d2332e6d8400cdc0de273ceff2abe8aaababf8"/>
   <project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
   <project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3c5405863d2002f665ef2b901abb3853c420129b"/>
   <project name="platform/system/netd" path="system/netd" revision="3ae56364946d4a5bf5a5f83f12f9a45a30398e33"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
--- 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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- 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="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <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
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
+  <project name="platform_build" path="build" remote="b2g" revision="a8ace1361d702eef293e48f2ea525dac686daa86">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
@@ -107,32 +107,34 @@
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="eb6077f10ae6255a72337124188f0e08dcd10e3e"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="3b80c725cea54132df05d208930d91e00d19f999"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="01f436c51dc68aec7cc1c85fda6e6792b2a95066"/>
   <project name="platform/libcore" path="libcore" revision="9877ade9617bb0db6e59aa2a54719a9bc92600f3"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="46c96ace65eb1ccab05bf15b9bf8e53e443039af"/>
   <project name="platform/ndk" path="ndk" revision="cb5519af32ae7b4a9c334913a612462ecd04c5d0"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="23404f05422c6bf3c39573325a4f4909167671b4"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="6aa61f8557a22039a30b42b7f283996381fd625d"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="6a1bb59af65b6485b1090522f66fac95c3f9e22c"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="48d2332e6d8400cdc0de273ceff2abe8aaababf8"/>
   <project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
   <project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3c5405863d2002f665ef2b901abb3853c420129b"/>
   <project name="platform/system/netd" path="system/netd" revision="36704b0da24debcab8090156568ac236315036bb"/>
   <project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
   <project name="platform/external/icu4c" path="external/icu4c" remote="aosp" revision="b4c6379528887dc25ca9991a535a8d92a61ad6b6"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="f3cedd7fd9b1649aa5107d466be9078bb7602af6"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/>
   <default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
-  <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="0c967fc587b614ffe391eb24e0b7f9f3bc31147b"/>
+  <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="d4377e11659d54b41c51526547e971ba0cb11754"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="fbd2becab3825c49e756db5149552f85049c66e2"/>
+  <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="f37bd545063039e30a92f2550ae78c0e6e4e2d08"/>
   <project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="9a725b0f5aa715282f8854ac56e5b63efc9cd077"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="0c2ffe181ca64a6cad9c5f93ddea623f080c6434"/>
+  <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="d82e00fb6380b4f6cea7a96213913ee9eb441239"/>
   <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/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="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
--- 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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- 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
@@ -7,20 +7,20 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
+  <project name="platform_build" path="build" remote="b2g" revision="a8ace1361d702eef293e48f2ea525dac686daa86">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
@@ -101,17 +101,17 @@
   <project name="platform/external/zlib" path="external/zlib" revision="6eb3570ff8fa71bd83bb375b4bf09804c6089fed"/>
   <project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="dbbe673145107e99883f62bafd70c5f43f11065c"/>
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="f0c3b4edf597c40aae4ea311575f39c8bcf203df"/>
   <project name="platform/libcore" path="libcore" revision="baf7d8068dd501cfa338d3a8b1b87216d6ce0571"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="50c4430e32849530ced32680fd6ee98963b3f7ac"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
   <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="23404f05422c6bf3c39573325a4f4909167671b4"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
-  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
+  <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="6a1bb59af65b6485b1090522f66fac95c3f9e22c"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="48d2332e6d8400cdc0de273ceff2abe8aaababf8"/>
   <project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3c5405863d2002f665ef2b901abb3853c420129b"/>
   <project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
   <project name="platform/system/security" path="system/security" revision="ee8068b9e7bfb2770635062fc9c2035be2142bd8"/>
   <project name="platform/system/vold" path="system/vold" revision="42fa2a0f14f965970a4b629a176bbd2666edf017"/>
--- 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="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <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": "6089234ace8b294a8feef064387604bae16254e3", 
+        "git_revision": "3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "4bcdce164d361f57742d042ff2742e3e6d53d7dd", 
+    "revision": "68c31354e0dec7651bb120f3429a83b224a40821", 
     "repo_path": "integration/gaia-central"
 }
--- 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="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <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/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/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="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6089234ace8b294a8feef064387604bae16254e3"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3654ec1d7ce1e0a56a34d5c3b06f6a9b33ff79ad"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
--- a/dom/bluetooth/BluetoothInterface.cpp
+++ b/dom/bluetooth/BluetoothInterface.cpp
@@ -133,31 +133,22 @@ BluetoothInterface::GetInstance()
   /* We pick a default backend from the available ones. The options are
    * ordered by preference. If a backend is supported but not available
    * on the current system, we pick the next one. The selected default
    * can be overriden manually by storing the respective string in the
    * system property 'ro.moz.bluetooth.backend'.
    */
 
   static const char* const sDefaultBackend[] = {
-#if MOZ_B2G_BT_API_V2
-#ifdef MOZ_B2G_BT_BLUEDROID
-    "bluedroid",
-#endif
-#ifdef MOZ_B2G_BT_DAEMON
-    "bluetoothd",
-#endif
-#else
 #ifdef MOZ_B2G_BT_DAEMON
     "bluetoothd",
 #endif
 #ifdef MOZ_B2G_BT_BLUEDROID
     "bluedroid",
 #endif
-#endif
     nullptr // no default backend; must be final element in array
   };
 
   const char* defaultBackend;
 
   for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDefaultBackend); ++i) {
 
     /* select current backend */
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -198,26 +198,33 @@ nsresult
 TelephonyListener::HandleCallInfo(nsITelephonyCallInfo* aInfo, bool aSend)
 {
   BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
   NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
 
   uint32_t callIndex;
   uint16_t callState;
   nsAutoString number;
+  nsAutoString disconnectedReason;
   bool isOutgoing;
   bool isConference;
 
   aInfo->GetCallIndex(&callIndex);
   aInfo->GetCallState(&callState);
   aInfo->GetNumber(number);
+  aInfo->GetDisconnectedReason(disconnectedReason);
   aInfo->GetIsOutgoing(&isOutgoing);
   aInfo->GetIsConference(&isConference);
 
-  hfp->HandleCallStateChanged(callIndex, callState, EmptyString(), number,
+  // The disconnectedReason of a disconnected call must be nonempty no matter
+  // the call is disconnected for a normal reason or an error.
+  MOZ_ASSERT((callState != nsITelephonyService::CALL_STATE_DISCONNECTED ||
+              !disconnectedReason.IsEmpty()),
+             "disconnectedReason of an disconnected call must be nonempty.");
+  hfp->HandleCallStateChanged(callIndex, callState, disconnectedReason, number,
                               isOutgoing, isConference, aSend);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelephonyListener::CallStateChanged(uint32_t aLength,
                                     nsITelephonyCallInfo** aAllInfo)
 {
@@ -229,40 +236,16 @@ TelephonyListener::CallStateChanged(uint
 
 NS_IMETHODIMP
 TelephonyListener::EnumerateCallState(nsITelephonyCallInfo* aInfo)
 {
   return HandleCallInfo(aInfo, false);
 }
 
 NS_IMETHODIMP
-TelephonyListener::NotifyError(uint32_t aServiceId,
-                               int32_t aCallIndex,
-                               const nsAString& aError)
-{
-  BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
-  NS_ENSURE_TRUE(hfp, NS_ERROR_FAILURE);
-
-  if (aCallIndex > 0) {
-    // In order to not miss any related call state transition.
-    // It's possible that 3G network signal lost for unknown reason.
-    // If a call is released abnormally, NotifyError() will be called,
-    // instead of CallStateChanged(). We need to reset the call array state
-    // via setting CALL_STATE_DISCONNECTED
-    hfp->HandleCallStateChanged(aCallIndex,
-                                nsITelephonyService::CALL_STATE_DISCONNECTED,
-                                aError, EmptyString(), false, false, true);
-    BT_WARNING("Reset the call state due to call transition ends abnormally");
-  }
-
-  BT_WARNING(NS_ConvertUTF16toUTF8(aError).get());
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 TelephonyListener::ConferenceCallStateChanged(uint16_t aCallState)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelephonyListener::EnumerateCallStateComplete()
 {
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
@@ -718,16 +718,29 @@ BluetoothA2dpManager::HandleSinkProperty
       mDeviceAddress.Truncate();
       OnDisconnect(EmptyString());
       break;
     default:
       break;
   }
 }
 
+/*
+ * Reset connection state to DISCONNECTED to handle backend error. The state
+ * change triggers UI status bar update as ordinary bluetooth turn-off sequence.
+ */
+void
+BluetoothA2dpManager::HandleBackendError()
+{
+  if (mSinkState != SinkState::SINK_DISCONNECTED) {
+    ConnectionStateNotification(A2DP_CONNECTION_STATE_DISCONNECTED,
+      mDeviceAddress);
+  }
+}
+
 void
 BluetoothA2dpManager::NotifyConnectionStatusChanged()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Notify Gecko observers
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE_VOID(obs);
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.h
@@ -58,16 +58,17 @@ public:
   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);
+  void HandleBackendError();
 
 protected:
   virtual ~BluetoothA2dpManager();
 
 private:
   class CleanupA2dpResultHandler;
   class CleanupA2dpResultHandlerRunnable;
   class CleanupAvrcpResultHandler;
--- a/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothServiceBluedroid.cpp
@@ -2477,18 +2477,19 @@ BluetoothServiceBluedroid::AdapterProper
   }
 #endif
 }
 
 /**
  * RemoteDevicePropertiesNotification will be called
  *
  *   (1) automatically by Bluedroid when BT is turning on, or
- *   (2) as result of GetRemoteDeviceProperties, or
- *   (3) as result of GetRemoteServices.
+ *   (2) as result of remote device properties update during discovery, or
+ *   (3) as result of GetRemoteDeviceProperties, or
+ *   (4) as result of GetRemoteServices.
  */
 void
 BluetoothServiceBluedroid::RemoteDevicePropertiesNotification(
   BluetoothStatus aStatus, const nsAString& aBdAddr,
   int aNumProperties, const BluetoothProperty* aProperties)
 {
 #ifdef MOZ_B2G_BT_API_V2
   MOZ_ASSERT(NS_IsMainThread());
@@ -2649,18 +2650,28 @@ BluetoothServiceBluedroid::RemoteDeviceP
     }
   }
 
   // BlueDroid wouldn't notify the status of connection, therefore, query the
   // connection state and append to properties array
   BT_APPEND_NAMED_VALUE(props, "Connected", IsConnected(aBdAddr));
 
   if (sRequestedDeviceCountArray.IsEmpty()) {
-    // This is possible because the callback would be called after turning
-    // Bluetooth on.
+    /**
+     * This is possible when
+     *
+     *  (1) the callback is called after Bluetooth is turned on, or
+     *  (2) remote device properties get updated during discovery.
+     *
+     * For (2), fire 'devicefound' again to update device name.
+     * See bug 1076553 for more information.
+     */
+    DistributeSignal(BluetoothSignal(NS_LITERAL_STRING("DeviceFound"),
+                                     NS_LITERAL_STRING(KEY_ADAPTER),
+                                     BluetoothValue(props)));
     return;
   }
 
   // Use address as the index
   sRemoteDevicesPack.AppendElement(
     BluetoothNamedValue(nsString(aBdAddr), props));
 
   if (--sRequestedDeviceCountArray[0] == 0) {
@@ -3124,27 +3135,40 @@ BluetoothServiceBluedroid::EnergyInfoNot
   // FIXME: This will be implemented in the later patchset
 }
 #endif
 
 void
 BluetoothServiceBluedroid::BackendErrorNotification(bool aCrashed)
 {
   MOZ_ASSERT(NS_IsMainThread());
- // Recovery step 2 stop bluetooth
- if (aCrashed) {
-  BT_LOGR("Set aRestart = true");
+
+  if (!aCrashed) {
+    return;
+  }
+
+  /*
+   * Reset following profile manager states for unexpected backend crash.
+   * - HFP: connection state and audio state
+   * - A2DP: connection state
+   */
+  BluetoothHfpManager* hfp = BluetoothHfpManager::Get();
+  NS_ENSURE_TRUE_VOID(hfp);
+  hfp->HandleBackendError();
+  BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
+  NS_ENSURE_TRUE_VOID(a2dp);
+  a2dp->HandleBackendError();
+
   sIsRestart = true;
-  BT_LOGR("Reocvery step2: stop bluetooth");
+  BT_LOGR("Recovery step2: stop bluetooth");
 #ifdef MOZ_B2G_BT_API_V2
   StopBluetooth(false, nullptr);
 #else
   StopBluetooth(false);
 #endif
- }
 }
 
 void
 BluetoothServiceBluedroid::CompleteToggleBt(bool aEnabled)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (sIsRestart && !aEnabled && sIsFirstTimeToggleOffBt) {
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -1116,16 +1116,36 @@ BluetoothHfpManager::ToggleCalls()
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Toggle acitve and held calls
   mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
                              nsITelephonyService::CALL_STATE_HELD :
                              nsITelephonyService::CALL_STATE_CONNECTED;
 }
 
+/*
+ * Reset connection state and audio state to DISCONNECTED to handle backend
+ * error. The state change triggers UI status bar update as ordinary bluetooth
+ * turn-off sequence.
+ */
+void
+BluetoothHfpManager::HandleBackendError()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (mConnectionState != HFP_CONNECTION_STATE_DISCONNECTED) {
+    ConnectionStateNotification(HFP_CONNECTION_STATE_DISCONNECTED,
+      mDeviceAddress);
+  }
+
+  if (mAudioState != HFP_AUDIO_STATE_DISCONNECTED) {
+    AudioStateNotification(HFP_AUDIO_STATE_DISCONNECTED, mDeviceAddress);
+  }
+}
+
 class BluetoothHfpManager::ConnectAudioResultHandler final
   : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) override
   {
     BT_WARNING("BluetoothHandsfreeInterface::ConnectAudio failed: %d",
                (int)aStatus);
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
@@ -104,16 +104,19 @@ public:
   void HandleVoiceConnectionChanged(uint32_t aClientId);
 
   // CDMA-specific functions
   void UpdateSecondNumber(const nsAString& aNumber);
   void AnswerWaitingCall();
   void IgnoreWaitingCall();
   void ToggleCalls();
 
+  // Handle unexpected backend crash
+  void HandleBackendError();
+
   //
   // Bluetooth notifications
   //
 
   void ConnectionStateNotification(BluetoothHandsfreeConnectionState aState,
                                    const nsAString& aBdAddress) override;
   void AudioStateNotification(BluetoothHandsfreeAudioState aState,
                               const nsAString& aBdAddress) override;
--- a/dom/bluetooth/bluetooth2/ipc/BluetoothMessageUtils.h
+++ b/dom/bluetooth/bluetooth2/ipc/BluetoothMessageUtils.h
@@ -116,22 +116,24 @@ template <>
 struct ParamTraits<mozilla::dom::bluetooth::BluetoothGattCharAttribute>
 {
   typedef mozilla::dom::bluetooth::BluetoothGattCharAttribute paramType;
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mId);
     WriteParam(aMsg, aParam.mProperties);
+    WriteParam(aMsg, aParam.mWriteType);
   }
 
   static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mId)) ||
-        !ReadParam(aMsg, aIter, &(aResult->mProperties))) {
+        !ReadParam(aMsg, aIter, &(aResult->mProperties)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mWriteType))) {
       return false;
     }
 
     return true;
   }
 };
 } // namespace IPC
 
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -35,16 +35,17 @@ try {
   kMaxPendingMessages =
     Services.prefs.getIntPref("dom.messages.maxPendingMessages");
 } catch(e) {
   // getIntPref throws when the pref is not set.
   kMaxPendingMessages = 5;
 }
 
 const kMessages =["SystemMessageManager:GetPendingMessages",
+                  "SystemMessageManager:HasPendingMessages",
                   "SystemMessageManager:Register",
                   "SystemMessageManager:Unregister",
                   "SystemMessageManager:Message:Return:OK",
                   "SystemMessageManager:AskReadyToRegister",
                   "SystemMessageManager:HandleMessagesDone",
                   "SystemMessageManager:HandleMessageDone",
                   "child-process-shutdown"];
 
@@ -414,16 +415,17 @@ SystemMessageInternal.prototype = {
     let msg = aMessage.json;
 
     // To prevent the hacked child process from sending commands to parent
     // to manage system messages, we need to check its manifest URL.
     if (["SystemMessageManager:Register",
          // TODO: fix bug 988142 to re-enable.
          // "SystemMessageManager:Unregister",
          "SystemMessageManager:GetPendingMessages",
+         "SystemMessageManager:HasPendingMessages",
          "SystemMessageManager:Message:Return:OK",
          "SystemMessageManager:HandleMessagesDone",
          "SystemMessageManager:HandleMessageDone"].indexOf(aMessage.name) != -1) {
       if (!aMessage.target.assertContainApp(msg.manifestURL)) {
         debug("Got message from a child process containing illegal manifest URL.");
         return null;
       }
     }
@@ -514,16 +516,35 @@ SystemMessageInternal.prototype = {
                 .sendAsyncMessage("SystemMessageManager:GetPendingMessages:Return",
                                   { type: msg.type,
                                     manifestURL: msg.manifestURL,
                                     pageURL: msg.pageURL,
                                     msgQueue: pendingMessages });
         this._refreshCacheInternal(aMessage.target, msg.manifestURL);
         break;
       }
+      case "SystemMessageManager:HasPendingMessages":
+      {
+        debug("received SystemMessageManager:HasPendingMessages " + msg.type +
+              " for " + msg.pageURL + " @ " + msg.manifestURL);
+
+        // NB: Sync message SystemMessageManager:HasPendingMessages
+        // should only be used by in-process app. For out-of-process
+        // app, SystemMessageCache should be used.
+
+        // This is a sync call used to return if a page has pending messages.
+        // Find the right page to get its corresponding pending messages.
+        let page = this._findPage(msg.type, msg.pageURL, msg.manifestURL);
+        if (!page) {
+          return false;
+        }
+
+        return page.pendingMessages.length != 0;
+        break;
+      }
       case "SystemMessageManager:Message:Return:OK":
       {
         debug("received SystemMessageManager:Message:Return:OK " + msg.type +
           " for " + msg.pageURL + " @ " + msg.manifestURL);
 
         // We need to clean up the pending message since the app has already
         // received it, thus avoiding the re-lanunched app handling it again.
         let page = this._findPage(msg.type, msg.pageURL, msg.manifestURL);
--- a/dom/messages/SystemMessageManager.js
+++ b/dom/messages/SystemMessageManager.js
@@ -189,16 +189,24 @@ SystemMessageManager.prototype = {
     }
 
     // If we have a handler for this type, we can't have any pending message.
     if (aType in this._dispatchers) {
       return false;
     }
 
 
+    // Use SystemMessageManager directly when we are in the same process.
+    if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_DEFAULT) {
+      return cpmm.sendSyncMessage("SystemMessageManager:HasPendingMessages",
+                                  { type: aType,
+                                    pageURL: this._pageURL,
+                                    manifestURL: this._manifestURL })[0];
+    }
+
     /*
      * NB: If the system message is fired after we received the cache
      *     and before we registered the pageURL we will get false
      *     negative however this is unlikely and will do no harm.
      */
     let cache = Cc["@mozilla.org/system-message-cache;1"]
                   .getService(Ci.nsISystemMessageCache);
 
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -2829,18 +2829,21 @@ DataCall.prototype = {
       // Notify the DISCONNECTED event immediately after network interface is
       // removed from requestedNetworkIfaces, to make the DataCall, shared or
       // not, to have the same behavior.
       Services.tm.currentThread.dispatch(() => {
         // Do not notify if state changed while this event was being dispatched,
         // the state probably was notified already or need not to be notified.
         if (networkInterface.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) {
           networkInterface.notifyRILNetworkInterface();
+
           // Clear link info after notifying NetworkManager.
-          this.resetLinkInfo();
+          if (this.requestedNetworkIfaces.length === 0) {
+            this.resetLinkInfo();
+          }
         }
       }, Ci.nsIEventTarget.DISPATCH_NORMAL);
     }
 
     // Only deactivate data call if no more network interface needs this
     // DataCall and if state is CONNECTED, for other states, we simply remove
     // the network interface from requestedNetworkIfaces.
     if (this.requestedNetworkIfaces.length > 0 ||
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -162,18 +162,16 @@ Telephony::IsValidServiceId(uint32_t aSe
   return aServiceId < GetNumServices();
 }
 
 // static
 bool
 Telephony::IsActiveState(uint16_t aCallState) {
   return aCallState == nsITelephonyService::CALL_STATE_DIALING ||
       aCallState == nsITelephonyService::CALL_STATE_ALERTING ||
-      aCallState == nsITelephonyService::CALL_STATE_HOLDING ||
-      aCallState == nsITelephonyService::CALL_STATE_DISCONNECTING ||
       aCallState == nsITelephonyService::CALL_STATE_CONNECTED;
 }
 
 uint32_t
 Telephony::GetServiceId(const Optional<uint32_t>& aServiceId,
                         bool aGetIfActiveCall)
 {
   if (aServiceId.WasPassed()) {
@@ -372,20 +370,24 @@ Telephony::HandleCallInfo(nsITelephonyCa
     call->UpdateSwitchable(isSwitchable);
     call->UpdateMergeable(isMergeable);
 
     nsAutoString number;
     aInfo->GetNumber(number);
     nsRefPtr<TelephonyCallId> id = call->Id();
     id->UpdateNumber(number);
 
+    nsAutoString disconnectedReason;
+    aInfo->GetDisconnectedReason(disconnectedReason);
+
     // State changed.
     if (call->CallState() != callState) {
       if (callState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
-        call->ChangeStateInternal(callState, true);
+        call->UpdateDisconnectedReason(disconnectedReason);
+        call->ChangeState(nsITelephonyService::CALL_STATE_DISCONNECTED);
         return NS_OK;
       }
 
       // We don't fire the statechange event on a call in conference here.
       // Instead, the event will be fired later in
       // TelephonyCallGroup::ChangeState(). Thus the sequence of firing the
       // statechange events is guaranteed: first on TelephonyCallGroup then on
       // individual TelephonyCall objects.
@@ -685,36 +687,16 @@ Telephony::SupplementaryServiceNotificat
       return NS_ERROR_UNEXPECTED;
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Telephony::NotifyError(uint32_t aServiceId,
-                       int32_t aCallIndex,
-                       const nsAString& aError)
-{
-  nsRefPtr<TelephonyCall> callToNotify =
-    GetCallFromEverywhere(aServiceId, aCallIndex);
-  if (!callToNotify) {
-    NS_ERROR("Don't call me with a bad call index!");
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  // Set the call state to 'disconnected' and remove it from the calls list.
-  callToNotify->UpdateDisconnectedReason(aError);
-  callToNotify->NotifyError(aError);
-  callToNotify->ChangeState(nsITelephonyService::CALL_STATE_DISCONNECTED);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 Telephony::NotifyCdmaCallWaiting(uint32_t aServiceId, const nsAString& aNumber,
                                  uint16_t aNumberPresentation,
                                  const nsAString& aName,
                                  uint16_t aNamePresentation)
 {
   MOZ_ASSERT(mCalls.Length() == 1);
 
   nsRefPtr<TelephonyCall> callToNotify = mCalls[0];
--- a/dom/telephony/TelephonyCall.cpp
+++ b/dom/telephony/TelephonyCall.cpp
@@ -82,33 +82,18 @@ TelephonyCall::WrapObject(JSContext* aCx
   return TelephonyCallBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
 {
   nsRefPtr<TelephonyCall> kungFuDeathGrip(this);
 
-  // Update the internal state.
   mCallState = aCallState;
-
-  // Indicate whether the external state have been changed.
-  bool externalStateChanged = true;
   switch (aCallState) {
-    // These states are used internally to mark this call is currently being
-    // controlled, and we should block consecutive requests of the same type
-    // according to these states.
-    case nsITelephonyService::CALL_STATE_CONNECTING:
-    case nsITelephonyService::CALL_STATE_DISCONNECTING:
-    case nsITelephonyService::CALL_STATE_HOLDING:
-    case nsITelephonyService::CALL_STATE_RESUMING:
-      externalStateChanged = false;
-      break;
-    // These states will be translated into literal strings which are used to
-    // show the current status of this call.
     case nsITelephonyService::CALL_STATE_DIALING:
       mState.AssignLiteral("dialing");
       break;
     case nsITelephonyService::CALL_STATE_ALERTING:
       mState.AssignLiteral("alerting");
       break;
     case nsITelephonyService::CALL_STATE_CONNECTED:
       mState.AssignLiteral("connected");
@@ -129,27 +114,26 @@ TelephonyCall::ChangeStateInternal(uint1
   if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     NS_ASSERTION(mLive, "Should be live!");
     mLive = false;
     if (mGroup) {
       mGroup->RemoveCall(this);
     } else {
       mTelephony->RemoveCall(this);
     }
-    UpdateDisconnectedReason(NS_LITERAL_STRING("NormalCallClearingError"));
   } else if (!mLive) {
     mLive = true;
     if (mGroup) {
       mGroup->AddCall(this);
     } else {
       mTelephony->AddCall(this);
     }
   }
 
-  if (aFireEvents && externalStateChanged) {
+  if (aFireEvents) {
     nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), this);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch specific event!");
     }
 
     // This can change if the statechange handler called back here... Need to
     // figure out something smarter.
     if (mCallState == aCallState) {
@@ -206,26 +190,33 @@ TelephonyCall::NotifyError(const nsAStri
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to dispatch error event!");
   }
 }
 
 void
 TelephonyCall::UpdateDisconnectedReason(const nsAString& aDisconnectedReason)
 {
-  NS_ASSERTION(Substring(aDisconnectedReason, aDisconnectedReason.Length() - 5).EqualsLiteral("Error"),
+  NS_ASSERTION(Substring(aDisconnectedReason,
+                         aDisconnectedReason.Length() - 5).EqualsLiteral("Error"),
                "Disconnected reason should end with 'Error'");
 
-  if (mDisconnectedReason.IsNull()) {
-    // There is no 'Error' suffix in the corresponding enum. We should skip
-    // that part for comparison.
-    CONVERT_STRING_TO_NULLABLE_ENUM(
-        Substring(aDisconnectedReason, 0, aDisconnectedReason.Length() - 5),
-        TelephonyCallDisconnectedReason,
-        mDisconnectedReason);
+  if (!mDisconnectedReason.IsNull()) {
+    return;
+  }
+
+  // There is no 'Error' suffix in the corresponding enum. We should skip
+  // that part for comparison.
+  CONVERT_STRING_TO_NULLABLE_ENUM(
+      Substring(aDisconnectedReason, 0, aDisconnectedReason.Length() - 5),
+      TelephonyCallDisconnectedReason,
+      mDisconnectedReason);
+
+  if (!aDisconnectedReason.EqualsLiteral("NormalCallClearingError")) {
+    NotifyError(aDisconnectedReason);
   }
 }
 
 void
 TelephonyCall::ChangeGroup(TelephonyCallGroup* aGroup)
 {
   mGroup = aGroup;
 
@@ -293,43 +284,40 @@ TelephonyCall::Answer(ErrorResult& aRv)
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mTelephony->Service()->AnswerCall(mServiceId, mCallIndex, callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_CONNECTING, false);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCall::HangUp(ErrorResult& aRv)
 {
   nsRefPtr<Promise> promise = CreatePromise(aRv);
   if (!promise) {
     return nullptr;
   }
 
-  if (mCallState == nsITelephonyService::CALL_STATE_DISCONNECTING ||
-      mCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
+  if (mCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     NS_WARNING(nsPrintfCString("HangUp on previously disconnected call"
                                " is rejected! (State: %u)", mCallState).get());
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mCallState == nsITelephonyService::CALL_STATE_INCOMING ?
     mTelephony->Service()->RejectCall(mServiceId, mCallIndex, callback) :
     mTelephony->Service()->HangUpCall(mServiceId, mCallIndex, callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_DISCONNECTING, false);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCall::Hold(ErrorResult& aRv)
 {
   nsRefPtr<Promise> promise = CreatePromise(aRv);
   if (!promise) {
@@ -361,17 +349,16 @@ TelephonyCall::Hold(ErrorResult& aRv)
 
   if (mSecondId) {
     // No state transition when we switch two numbers within one TelephonyCall
     // object. Otherwise, the state here will be inconsistent with the backend
     // RIL and will never be right.
     return promise.forget();
   }
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_HOLDING, false);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCall::Resume(ErrorResult& aRv)
 {
   nsRefPtr<Promise> promise = CreatePromise(aRv);
   if (!promise) {
@@ -396,11 +383,10 @@ TelephonyCall::Resume(ErrorResult& aRv)
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mTelephony->Service()->ResumeCall(mServiceId, mCallIndex, callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
-  ChangeStateInternal(nsITelephonyService::CALL_STATE_RESUMING, false);
   return promise.forget();
 }
--- a/dom/telephony/TelephonyCallGroup.cpp
+++ b/dom/telephony/TelephonyCallGroup.cpp
@@ -82,57 +82,43 @@ TelephonyCallGroup::NotifyError(const ns
 }
 
 void
 TelephonyCallGroup::ChangeState(uint16_t aCallState)
 {
   if (mCallState == aCallState) {
     return;
   }
-  // Update the internal state.
+
   mCallState = aCallState;
-
-  // Indicate whether the external state should be changed.
-  bool externalStateChanged = true;
   switch (aCallState) {
-    // These states are used internally to mark this CallGroup is currently
-    // being controlled, and we should block consecutive requests of the same
-    // type according to these states.
-    case nsITelephonyService::CALL_STATE_HOLDING:
-    case nsITelephonyService::CALL_STATE_RESUMING:
-      externalStateChanged = false;
-      break;
-    // These states will be translated into literal strings which are used to
-    // show the current status of this CallGroup.
     case nsITelephonyService::CALL_STATE_UNKNOWN:
       mState.AssignLiteral("");
       break;
     case nsITelephonyService::CALL_STATE_CONNECTED:
       mState.AssignLiteral("connected");
       break;
     case nsITelephonyService::CALL_STATE_HELD:
       mState.AssignLiteral("held");
       break;
     default:
       NS_NOTREACHED("Unknown state!");
   }
 
-  if (externalStateChanged) {
-    nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr);
-    if (NS_FAILED(rv)) {
-      NS_WARNING("Failed to dispatch specific event!");
-    }
-    if (!mState.IsEmpty()) {
-      // This can change if the statechange handler called back here... Need to
-      // figure out something smarter.
-      if (mCallState == aCallState) {
-        rv = DispatchCallEvent(mState, nullptr);
-        if (NS_FAILED(rv)) {
-          NS_WARNING("Failed to dispatch specific event!");
-        }
+  nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("statechange"), nullptr);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Failed to dispatch specific event!");
+  }
+  if (!mState.IsEmpty()) {
+    // This can change if the statechange handler called back here... Need to
+    // figure out something smarter.
+    if (mCallState == aCallState) {
+      rv = DispatchCallEvent(mState, nullptr);
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Failed to dispatch specific event!");
       }
     }
   }
 
   for (uint32_t index = 0; index < mCalls.Length(); index++) {
     nsRefPtr<TelephonyCall> call = mCalls[index];
     call->ChangeState(aCallState);
 
@@ -343,17 +329,16 @@ TelephonyCallGroup::HangUp(ErrorResult& 
   if (!promise) {
     return nullptr;
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mTelephony->Service()->HangUpConference(mCalls[0]->ServiceId(),
                                                 callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
-
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCallGroup::Hold(ErrorResult& aRv)
 {
   MOZ_ASSERT(!mCalls.IsEmpty());
 
@@ -367,18 +352,16 @@ TelephonyCallGroup::Hold(ErrorResult& aR
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mTelephony->Service()->HoldConference(mCalls[0]->ServiceId(),
                                               callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
-
-  ChangeState(nsITelephonyService::CALL_STATE_HOLDING);
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 TelephonyCallGroup::Resume(ErrorResult& aRv)
 {
   MOZ_ASSERT(!mCalls.IsEmpty());
 
@@ -392,12 +375,10 @@ TelephonyCallGroup::Resume(ErrorResult& 
     promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback = new TelephonyCallback(promise);
   aRv = mTelephony->Service()->ResumeConference(mCalls[0]->ServiceId(),
                                                 callback);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
-
-  ChangeState(nsITelephonyService::CALL_STATE_RESUMING);
   return promise.forget();
 }
--- a/dom/telephony/TelephonyCallInfo.cpp
+++ b/dom/telephony/TelephonyCallInfo.cpp
@@ -10,32 +10,38 @@ namespace mozilla {
 namespace dom {
 namespace telephony {
 
 NS_IMPL_ISUPPORTS(TelephonyCallInfo, nsITelephonyCallInfo)
 
 TelephonyCallInfo::TelephonyCallInfo(uint32_t aClientId,
                                      uint32_t aCallIndex,
                                      uint16_t aCallState,
+                                     const nsAString& aDisconnectedReason,
+
                                      const nsAString& aNumber,
                                      uint16_t aNumberPresentation,
                                      const nsAString& aName,
                                      uint16_t aNamePresentation,
+
                                      bool aIsOutgoing,
                                      bool aIsEmergency,
                                      bool aIsConference,
                                      bool aIsSwitchable,
                                      bool aIsMergeable)
   : mClientId(aClientId),
     mCallIndex(aCallIndex),
     mCallState(aCallState),
+    mDisconnectedReason(aDisconnectedReason),
+
     mNumber(aNumber),
     mNumberPresentation(aNumberPresentation),
     mName(aName),
     mNamePresentation(aNamePresentation),
+
     mIsOutgoing(aIsOutgoing),
     mIsEmergency(aIsEmergency),
     mIsConference(aIsConference),
     mIsSwitchable(aIsSwitchable),
     mIsMergeable(aIsMergeable)
 {
 }
 
@@ -56,16 +62,23 @@ TelephonyCallInfo::GetCallIndex(uint32_t
 NS_IMETHODIMP
 TelephonyCallInfo::GetCallState(uint16_t* aCallState)
 {
   *aCallState = mCallState;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+TelephonyCallInfo::GetDisconnectedReason(nsAString& aDisconnectedReason)
+{
+  aDisconnectedReason = mDisconnectedReason;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 TelephonyCallInfo::GetNumber(nsAString& aNumber)
 {
   aNumber = mNumber;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelephonyCallInfo::GetNumberPresentation(uint16_t* aNumberPresentation)
--- a/dom/telephony/TelephonyCallInfo.h
+++ b/dom/telephony/TelephonyCallInfo.h
@@ -16,36 +16,48 @@ namespace dom {
 namespace telephony {
 
 class TelephonyCallInfo final : public nsITelephonyCallInfo
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSITELEPHONYCALLINFO
 
-  TelephonyCallInfo(uint32_t aClientId, uint32_t aCallIndex,
-                    uint16_t aCallState, const nsAString& aNumber,
-                    uint16_t aNumberPresentation, const nsAString& aName,
-                    uint16_t aNamePresentation, bool aIsOutgoing,
-                    bool aIsEmergency, bool aIsConference,
-                    bool aIsSwitchable, bool aIsMergeable);
+  TelephonyCallInfo(uint32_t aClientId,
+                    uint32_t aCallIndex,
+                    uint16_t aCallState,
+                    const nsAString& aDisconnectedReason,
+
+                    const nsAString& aNumber,
+                    uint16_t aNumberPresentation,
+                    const nsAString& aName,
+                    uint16_t aNamePresentation,
+
+                    bool aIsOutgoing,
+                    bool aIsEmergency,
+                    bool aIsConference,
+                    bool aIsSwitchable,
+                    bool aIsMergeable);
 
 private:
   // Don't try to use the default constructor.
   TelephonyCallInfo() {}
 
   ~TelephonyCallInfo() {}
 
   uint32_t mClientId;
   uint32_t mCallIndex;
   uint16_t mCallState;
+  nsString mDisconnectedReason;
+
   nsString mNumber;
   uint16_t mNumberPresentation;
   nsString mName;
   uint16_t mNamePresentation;
+
   bool mIsOutgoing;
   bool mIsEmergency;
   bool mIsConference;
   bool mIsSwitchable;
   bool mIsMergeable;
 };
 
 } // namespace telephony
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -125,20 +125,23 @@ MobileCallForwardingOptions.prototype = 
   timeSeconds: -1,
   serviceClass: nsIMobileConnection.ICC_SERVICE_CLASS_NONE
 };
 
 function TelephonyCallInfo(aCall) {
   this.clientId = aCall.clientId;
   this.callIndex = aCall.callIndex;
   this.callState = aCall.state;
+  this.disconnectedReason = aCall.disconnectedReason || "";
+
   this.number = aCall.number;
   this.numberPresentation = aCall.numberPresentation;
   this.name = aCall.name;
   this.namePresentation = aCall.namePresentation;
+
   this.isOutgoing = aCall.isOutgoing;
   this.isEmergency = aCall.isEmergency;
   this.isConference = aCall.isConference;
   this.isSwitchable = aCall.isSwitchable;
   this.isMergeable = aCall.isMergeable;
 }
 TelephonyCallInfo.prototype = {
   QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyCallInfo]),
@@ -149,20 +152,23 @@ TelephonyCallInfo.prototype = {
     interfaces:       [Ci.nsITelephonyCallInfo]
   }),
 
   // nsITelephonyCallInfo
 
   clientId: 0,
   callIndex: 0,
   callState: nsITelephonyService.CALL_STATE_UNKNOWN,
+  disconnectedReason: "",
+
   number: "",
   numberPresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED,
   name: "",
   namePresentation: nsITelephonyService.CALL_PRESENTATION_ALLOWED,
+
   isOutgoing: true,
   isEmergency: false,
   isConference: false,
   isSwitchable: true,
   isMergeable: true
 };
 
 function Call(aClientId, aCallIndex) {
@@ -1439,20 +1445,16 @@ TelephonyService.prototype = {
     this._cdmaCallWaitingNumber = null;
   },
 
   /**
    * Disconnect calls by updating their states. Sometimes, it may cause other
    * calls being disconnected as well.
    *
    * @return Array a list of calls we need to fire callStateChange
-   *
-   * TODO: The list currently doesn't contain calls that we fire notifyError
-   * for them. However, after Bug 1147736, notifyError is replaced by
-   * callStateChanged and those calls should be included in the list.
    */
   _disconnectCalls: function(aClientId, aCalls,
                              aFailCause = RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) {
     if (DEBUG) debug("_disconnectCalls: " + JSON.stringify(aCalls));
 
     // Child cannot live without parent. Let's find all the calls that need to
     // be disconnected.
     let disconnectedCalls = aCalls.slice();
@@ -1466,32 +1468,26 @@ TelephonyService.prototype = {
 
     // Store unique value in the list.
     disconnectedCalls = [...Set(disconnectedCalls)];
 
     let callsForStateChanged = [];
 
     disconnectedCalls.forEach(call => {
       call.state = nsITelephonyService.CALL_STATE_DISCONNECTED;
-      call.failCause = aFailCause;
+      call.disconnectedReason = aFailCause;
 
       if (call.parentId) {
         let parentCall = this._currentCalls[aClientId][call.parentId];
         delete parentCall.childId;
       }
 
       this._notifyCallEnded(call);
 
-      if (call.hangUpLocal || !call.failCause ||
-          call.failCause === RIL.GECKO_CALL_ERROR_NORMAL_CALL_CLEARING) {
-        callsForStateChanged.push(call);
-      } else {
-        this._notifyAllListeners("notifyError",
-                                 [aClientId, call.callIndex, call.failCause]);
-      }
+      callsForStateChanged.push(call);
 
       delete this._currentCalls[aClientId][call.callIndex];
     });
 
     return callsForStateChanged;
   },
 
   /**
--- a/dom/telephony/ipc/PTelephony.ipdl
+++ b/dom/telephony/ipc/PTelephony.ipdl
@@ -120,18 +120,16 @@ union IPCTelephonyRequest
   SendTonesRequest;
 };
 
 sync protocol PTelephony {
   manager PContent;
   manages PTelephonyRequest;
 
 child:
-  NotifyCallError(uint32_t aClientId, int32_t aCallIndex, nsString aError);
-
   NotifyCallStateChanged(nsTelephonyCallInfo[] aAllInfo);
 
   NotifyCdmaCallWaiting(uint32_t aClientId, IPCCdmaWaitingCallData aData);
 
   NotifyConferenceCallStateChanged(uint16_t aCallState);
 
   NotifyConferenceError(nsString aName, nsString aMessage);
 
--- a/dom/telephony/ipc/TelephonyChild.cpp
+++ b/dom/telephony/ipc/TelephonyChild.cpp
@@ -43,27 +43,16 @@ TelephonyChild::AllocPTelephonyRequestCh
 bool
 TelephonyChild::DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor)
 {
   delete aActor;
   return true;
 }
 
 bool
-TelephonyChild::RecvNotifyCallError(const uint32_t& aClientId,
-                                    const int32_t& aCallIndex,
-                                    const nsString& aError)
-{
-  MOZ_ASSERT(mService);
-
-  mService->NotifyError(aClientId, aCallIndex, aError);
-  return true;
-}
-
-bool
 TelephonyChild::RecvNotifyCallStateChanged(nsTArray<nsITelephonyCallInfo*>&& aAllInfo)
 {
   uint32_t length = aAllInfo.Length();
   nsTArray<nsCOMPtr<nsITelephonyCallInfo>> results;
   for (uint32_t i = 0; i < length; ++i) {
     // Use dont_AddRef here because this instance has already been AddRef-ed in
     // TelephonyIPCSerializer.h
     nsCOMPtr<nsITelephonyCallInfo> info = dont_AddRef(aAllInfo[i]);
--- a/dom/telephony/ipc/TelephonyChild.h
+++ b/dom/telephony/ipc/TelephonyChild.h
@@ -30,20 +30,16 @@ protected:
 
   virtual PTelephonyRequestChild*
   AllocPTelephonyRequestChild(const IPCTelephonyRequest& aRequest) override;
 
   virtual bool
   DeallocPTelephonyRequestChild(PTelephonyRequestChild* aActor) override;
 
   virtual bool
-  RecvNotifyCallError(const uint32_t& aClientId, const int32_t& aCallIndex,
-                      const nsString& aError) override;
-
-  virtual bool
   RecvNotifyCallStateChanged(nsTArray<nsITelephonyCallInfo*>&& aAllInfo) override;
 
   virtual bool
   RecvNotifyCdmaCallWaiting(const uint32_t& aClientId,
                             const IPCCdmaWaitingCallData& aData) override;
 
   virtual bool
   RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState) override;
--- a/dom/telephony/ipc/TelephonyIPCSerializer.h
+++ b/dom/telephony/ipc/TelephonyIPCSerializer.h
@@ -85,47 +85,64 @@ struct ParamTraits<nsITelephonyCallInfo*
     if (isNull) {
       *aResult = nullptr;
       return true;
     }
 
     uint32_t clientId;
     uint32_t callIndex;
     uint16_t callState;
+    nsString disconnectedReason;
+
     nsString number;
     uint16_t numberPresentation;
     nsString name;
     uint16_t namePresentation;
+
     bool isOutgoing;
     bool isEmergency;
     bool isConference;
     bool isSwitchable;
     bool isMergeable;
 
     // It's not important to us where it fails, but rather if it fails
     if (!(ReadParam(aMsg, aIter, &clientId) &&
           ReadParam(aMsg, aIter, &callIndex) &&
           ReadParam(aMsg, aIter, &callState) &&
+          ReadParam(aMsg, aIter, &disconnectedReason) &&
+
           ReadParam(aMsg, aIter, &number) &&
           ReadParam(aMsg, aIter, &numberPresentation) &&
           ReadParam(aMsg, aIter, &name) &&
           ReadParam(aMsg, aIter, &namePresentation) &&
+
           ReadParam(aMsg, aIter, &isOutgoing) &&
           ReadParam(aMsg, aIter, &isEmergency) &&
           ReadParam(aMsg, aIter, &isConference) &&
           ReadParam(aMsg, aIter, &isSwitchable) &&
           ReadParam(aMsg, aIter, &isMergeable))) {
       return false;
     }
 
     nsCOMPtr<nsITelephonyCallInfo> info =
-        new TelephonyCallInfo(clientId, callIndex, callState, number,
-                              numberPresentation, name, namePresentation,
-                              isOutgoing, isEmergency, isConference,
-                              isSwitchable, isMergeable);
+        new TelephonyCallInfo(clientId,
+                              callIndex,
+                              callState,
+                              disconnectedReason,
+
+                              number,
+                              numberPresentation,
+                              name,
+                              namePresentation,
+
+                              isOutgoing,
+                              isEmergency,
+                              isConference,
+                              isSwitchable,
+                              isMergeable);
 
     info.forget(aResult);
 
     return true;
   }
 };
 
 
--- a/dom/telephony/ipc/TelephonyIPCService.cpp
+++ b/dom/telephony/ipc/TelephonyIPCService.cpp
@@ -417,26 +417,16 @@ TelephonyIPCService::NotifyConferenceErr
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->NotifyConferenceError(aName, aMessage);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCService::NotifyError(uint32_t aClientId, int32_t aCallIndex,
-                                  const nsAString& aError)
-{
-  for (uint32_t i = 0; i < mListeners.Length(); i++) {
-    mListeners[i]->NotifyError(aClientId, aCallIndex, aError);
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 TelephonyIPCService::SupplementaryServiceNotification(uint32_t aClientId,
                                                        int32_t aCallIndex,
                                                        uint16_t aNotification)
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->SupplementaryServiceNotification(aClientId, aCallIndex,
                                                     aNotification);
   }
--- a/dom/telephony/ipc/TelephonyParent.cpp
+++ b/dom/telephony/ipc/TelephonyParent.cpp
@@ -327,27 +327,16 @@ TelephonyParent::NotifyConferenceError(c
 {
   NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
 
   return SendNotifyConferenceError(nsString(aName), nsString(aMessage)) ? NS_OK
                                                                         : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-TelephonyParent::NotifyError(uint32_t aClientId,
-                             int32_t aCallIndex,
-                             const nsAString& aError)
-{
-  NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
-
-  return SendNotifyCallError(aClientId, aCallIndex, nsString(aError))
-      ? NS_OK : NS_ERROR_FAILURE;
-}
-
-NS_IMETHODIMP
 TelephonyParent::SupplementaryServiceNotification(uint32_t aClientId,
                                                   int32_t aCallIndex,
                                                   uint16_t aNotification)
 {
   NS_ENSURE_TRUE(!mActorDestroyed, NS_ERROR_FAILURE);
 
   return SendNotifySupplementaryService(aClientId, aCallIndex, aNotification)
       ? NS_OK : NS_ERROR_FAILURE;
@@ -427,24 +416,16 @@ TelephonyRequestParent::NotifyCdmaCallWa
 NS_IMETHODIMP
 TelephonyRequestParent::NotifyConferenceError(const nsAString& aName,
                                               const nsAString& aMessage)
 {
   MOZ_CRASH("Not a TelephonyParent!");
 }
 
 NS_IMETHODIMP
-TelephonyRequestParent::NotifyError(uint32_t aClientId,
-                                    int32_t aCallIndex,
-                                    const nsAString& aError)
-{
-  MOZ_CRASH("Not a TelephonyParent!");
-}
-
-NS_IMETHODIMP
 TelephonyRequestParent::SupplementaryServiceNotification(uint32_t aClientId,
                                                          int32_t aCallIndex,
                                                          uint16_t aNotification)
 {
   MOZ_CRASH("Not a TelephonyParent!");
 }
 
 // nsITelephonyDialCallback
--- a/dom/telephony/nsIGonkTelephonyService.idl
+++ b/dom/telephony/nsIGonkTelephonyService.idl
@@ -5,17 +5,17 @@
 
 #include "nsITelephonyService.idl"
 
 %{C++
 #define GONK_TELEPHONY_SERVICE_CONTRACTID \
         "@mozilla.org/telephony/gonktelephonyservice;1"
 %}
 
-[scriptable, uuid(d287e11a-0a65-4456-b481-c63d62afdb5d)]
+[scriptable, uuid(8653d76b-6805-41d2-8ea5-3b14fb4e682d)]
 interface nsIGonkTelephonyService : nsITelephonyService
 {
   void notifyCallRing();
 
   void notifyCurrentCalls(in unsigned long clientId, in jsval calls);
 
   void notifyCdmaCallWaiting(in unsigned long clientId, in jsval waitingCall);
 
--- a/dom/telephony/nsITelephonyCallInfo.idl
+++ b/dom/telephony/nsITelephonyCallInfo.idl
@@ -1,15 +1,15 @@
 /* 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 "nsISupports.idl"
 
-[scriptable, uuid(3ea2d155-8ea2-42be-85d7-bd8ede8afc40)]
+[scriptable, uuid(e5e1be26-a3d4-49b3-8d9f-c1df5192b364)]
 interface nsITelephonyCallInfo : nsISupports
 {
   /**
    * Indicate the RIL client, 0 ~ (number of client - 1).
    */
   readonly attribute unsigned long clientId;
 
   /**
@@ -18,16 +18,24 @@ interface nsITelephonyCallInfo : nsISupp
   readonly attribute unsigned long callIndex;
 
   /**
    * One of the nsITelephonyService::CALL_STATE_* values.
    */
   readonly attribute unsigned short callState;
 
   /**
+   * The disconnectedReason of a call is defualt to an empty string when the
+   * call is "not disconnected", but once the call becomes "disconnected" the
+   * disconnectedReason should be a non-empty string no matter the call is
+   * disconnected for a noraml reason or an error.
+   */
+  readonly attribute DOMString disconnectedReason;
+
+  /**
    * Number of the other party.
    */
   readonly attribute DOMString number;
 
   /**
    * Presentation of the call number.
    * One of the nsITelephonyService::CALL_PRESENTATION_* values.
    */
--- a/dom/telephony/nsITelephonyService.idl
+++ b/dom/telephony/nsITelephonyService.idl
@@ -2,17 +2,17 @@
  * 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 "nsISupports.idl"
 
 interface nsIMobileCallForwardingOptions;
 interface nsITelephonyCallInfo;
 
-[scriptable, uuid(37fb45bb-ae10-4cfd-b24e-d656a9787a0a)]
+[scriptable, uuid(80faf34e-286b-4487-bd55-135bd92668b9)]
 interface nsITelephonyListener : nsISupports
 {
   /**
    * Called when enumeration asked by nsITelephonyService::enumerateCalls
    * is completed.
    */
   void enumerateCallStateComplete();
 
@@ -50,30 +50,16 @@ interface nsITelephonyListener : nsISupp
    * @param notification
    *        One of the nsITelephonyService::NOTIFICATION_* values.
    */
   void supplementaryServiceNotification(in unsigned long clientId,
                                         in long callIndex,
                                         in unsigned short notification);
 
   /**
-   * Called when RIL error occurs.
-   *
-   * @param clientId
-            Indicate the RIL client, 0 ~ (number of client - 1).
-   * @param callIndex
-   *        Call identifier assigned by the RIL. -1 if no connection
-   * @param error
-   *        Error from RIL.
-   */
-  void notifyError(in unsigned long clientId,
-                   in long callIndex,
-                   in AString error);
-
-  /**
    * Called when a waiting call comes in CDMA networks.
    *
    * @param clientId
             Indicate the RIL client, 0 ~ (number of client - 1).
    * @param number
    *        Number of the other party.
    * @param numberPresentation
    *        Presentation of the call number.
@@ -170,30 +156,26 @@ interface nsITelephonyDialCallback : nsI
 #define TELEPHONY_SERVICE_CONTRACTID \
   "@mozilla.org/telephony/telephonyservice;1"
 %}
 
 /**
  * XPCOM component (in the content process) that provides the telephony
  * information.
  */
-[scriptable, uuid(2b7b3fe7-f1d9-48be-8fd6-aaf890fa73af)]
+[scriptable, uuid(75e4b5e3-6710-4156-bdaa-ba1081f390f4)]
 interface nsITelephonyService : nsISupports
 {
   const unsigned short CALL_STATE_UNKNOWN = 0;
   const unsigned short CALL_STATE_DIALING = 1;
   const unsigned short CALL_STATE_ALERTING = 2;
-  const unsigned short CALL_STATE_CONNECTING = 3;
-  const unsigned short CALL_STATE_CONNECTED = 4;
-  const unsigned short CALL_STATE_HOLDING = 5;
-  const unsigned short CALL_STATE_HELD = 6;
-  const unsigned short CALL_STATE_RESUMING = 7;
-  const unsigned short CALL_STATE_DISCONNECTING = 8;
-  const unsigned short CALL_STATE_DISCONNECTED = 9;
-  const unsigned short CALL_STATE_INCOMING = 10;
+  const unsigned short CALL_STATE_CONNECTED = 3;
+  const unsigned short CALL_STATE_HELD = 4;
+  const unsigned short CALL_STATE_DISCONNECTED = 5;
+  const unsigned short CALL_STATE_INCOMING = 6;
 
   const unsigned short NOTIFICATION_REMOTE_HELD = 0;
   const unsigned short NOTIFICATION_REMOTE_RESUMED = 1;
 
   const unsigned short CALL_PRESENTATION_ALLOWED = 0;
   const unsigned short CALL_PRESENTATION_RESTRICTED = 1;
   const unsigned short CALL_PRESENTATION_UNKNOWN = 2;
   const unsigned short CALL_PRESENTATION_PAYPHONE = 3;
--- a/dom/telephony/test/marionette/manifest.ini
+++ b/dom/telephony/test/marionette/manifest.ini
@@ -11,16 +11,17 @@ qemu = true
 [test_conference_remove_error.js]
 [test_conference_three_hangup_one.js]
 [test_conference_three_remove_one.js]
 [test_conference_two_calls.js]
 [test_conference_two_hangup_all.js]
 [test_conference_two_hangup_one.js]
 [test_conference_two_hold_resume.js]
 [test_conference_two_remove_one.js]
+[test_consecutive_hold.js]
 [test_crash_emulator.js]
 [test_dsds_connection_conflict.js]
 [test_dsds_default_service_id.js]
 [test_dsds_normal_call.js]
 [test_dtmf.js]
 [test_emergency.js]
 [test_emergency_label.js]
 [test_incall_mmi_call_hold.js]
new file mode 100644
--- /dev/null
+++ b/dom/telephony/test/marionette/test_consecutive_hold.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 90000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
+
+startTest(function() {
+  Promise.resolve()
+
+    // Incoming
+    .then(() => gRemoteDial(inNumber))
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+    .then(() => is(inCall.disconnectedReason, null))
+
+    // Answer
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+    .then(() => is(inCall.disconnectedReason, null))
+
+    // Disable the Hold function of the emulator, then hold the active call,
+    // where the hold request will fail and the call will remain active.
+    .then(() => emulator.runCmd("gsm disable hold"))
+    .then(() => gHold(inCall))
+    .then(() => ok(false, "This hold request should be rejected."),
+          () => log("This hold request is rejected as expected."))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+    .then(() => is(inCall.disconnectedReason, null))
+
+    // Enable the Hold function of the emulator, then hold the active call,
+    // where the hold request should succeed and the call should become held.
+    .then(() => emulator.runCmd("gsm enable hold"))
+    .then(() => gHold(inCall))
+    .then(() => log("This hold request is resolved as expected."),
+          () => ok(false, "This hold request should be resolved."))
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
+    .then(() => is(inCall.disconnectedReason, null))
+
+    // Hang up the call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+    .then(() => is(inCall.disconnectedReason, "NormalCallClearing"))
+
+    // Clean Up
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(() => emulator.runCmd("gsm enable hold"))
+    .then(finish);
+});
--- a/toolkit/webapps/MacNativeApp.js
+++ b/toolkit/webapps/MacNativeApp.js
@@ -289,29 +289,31 @@ NativeApp.prototype = {
    *
    * @param aMimeType     the icon mimetype
    * @param aImageStream  the stream for the image data
    * @param aDir          the directory where the icon should be stored
    */
   _processIcon: function(aMimeType, aIcon, aDir) {
     let deferred = Promise.defer();
 
-    let tmpIconPath = OS.Path.join(aDir, this.iconFile);
+    let finalIconPath = OS.Path.join(aDir, this.iconFile);
+    let tmpIconPath = OS.Path.join(OS.Constants.Path.tmpDir, "appicon.icns");
 
     function conversionDone(aSubject, aTopic) {
       if (aTopic != "process-finished") {
         deferred.reject("Failure converting icon, exit code: " + aSubject.exitValue);
         return;
       }
 
       // SIPS silently fails to convert the icon, so we need to verify if the
       // icon was successfully converted.
       OS.File.exists(tmpIconPath).then((aExists) => {
         if (aExists) {
-          deferred.resolve();
+          OS.File.move(tmpIconPath, finalIconPath).then(
+            deferred.resolve, err => deferred.reject(err));
         } else {
           deferred.reject("Failure converting icon, unrecognized image format");
         }
       });
     }
 
     let process = Cc["@mozilla.org/process/util;1"].
                   createInstance(Ci.nsIProcess);
--- a/toolkit/webapps/tests/chrome.ini
+++ b/toolkit/webapps/tests/chrome.ini
@@ -31,8 +31,9 @@ skip-if = asan
 skip-if = asan
 [test_hosted_icons.xul]
 [test_hosted_checkforupdates_from_webapp_runtime.xul]
 skip-if = asan
 [test_packaged_icons.xul]
 [test_packaged_checkforupdates_from_webapp_runtime.xul]
 skip-if = asan
 [test_webapp_runtime_executable_update.xul]
+[test_non_ascii_app_name.xul]
new file mode 100644
--- /dev/null
+++ b/toolkit/webapps/tests/test_non_ascii_app_name.xul
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
+<?xml-stylesheet type="text/css" href="/tests/SimpleTest/test.css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1152552
+-->
+<window title="Mozilla Bug 1152552"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="head.js"/>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=898647"
+     target="_blank">Mozilla Bug 898647</a>
+  </body>
+
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 1152552 **/
+
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NativeApp.jsm");
+Cu.import("resource://gre/modules/WebappOSUtils.jsm");
+
+let manifest = {
+  // Test unicode app names, the hyphen being \u2013
+  name: "Sample hosted app – \u2603 \u26a0",
+};
+
+let app = {
+  name: "Sample hosted app – \u2603 \u26a0",
+  manifestURL: "http://example.com/sample.manifest",
+  manifest: manifest,
+  origin: "http://example.com/",
+  categories: [],
+  installOrigin: "http://example.com/",
+  receipts: [],
+  installTime: Date.now(),
+};
+
+let testAppInfo = new TestAppInfo(app);
+
+let runTest = Task.async(function*() {
+  // Get to a clean state before the test
+  yield testAppInfo.cleanup();
+
+  SimpleTest.registerCleanupFunction(() => testAppInfo.cleanup());
+
+  setDryRunPref();
+
+  let nativeApp = new NativeApp(app, manifest, app.categories);
+  ok(nativeApp, "NativeApp object created");
+
+  info("Test update for an uninstalled application");
+  try {
+    yield nativeApp.prepareUpdate(app, manifest);
+    ok(false, "Didn't thrown");
+  } catch (ex) {
+    is(ex, "The application isn't installed", "Exception thrown");
+  }
+
+  testAppInfo.profileDir = nativeApp.createProfile();
+  ok(testAppInfo.profileDir && testAppInfo.profileDir.exists(), "Profile directory created");
+  ok((yield OS.File.exists(testAppInfo.profilesIni)), "profiles.ini file created");
+
+  // On Mac build servers, we don't have enough privileges to write to /Applications,
+  // so we install apps in a user-owned directory.
+  if (MAC) {
+    yield setMacRootInstallDir(OS.Path.join(OS.Constants.Path.homeDir, "Applications"));
+  }
+
+  // Install application
+  info("Test installation");
+  yield nativeApp.install(app, manifest);
+  while (!WebappOSUtils.isLaunchable(app)) {
+    yield wait(1000);
+  }
+  ok(true, "App launchable");
+  ok((yield checkFiles(testAppInfo.installedFiles)), "Files correctly written");
+  is(WebappOSUtils.getInstallPath(app), testAppInfo.installPath, "getInstallPath == installPath");
+
+  let stat = yield OS.File.stat(testAppInfo.installPath);
+  let installTime = stat.lastModificationDate;
+
+  // Wait one second, otherwise the last modification date is the same.
+  yield wait(1000);
+
+  // Reinstall application
+  info("Test reinstallation");
+  yield nativeApp.install(app, manifest);
+  while (!WebappOSUtils.isLaunchable(app)) {
+    yield wait(1000);
+  }
+  ok(true, "App launchable");
+  ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
+  ok((yield checkFiles(testAppInfo.tempUpdatedFiles)), "Files correctly written in the update subdirectory");
+
+  yield nativeApp.applyUpdate(app);
+  while (!WebappOSUtils.isLaunchable(app)) {
+    yield wait(1000);
+  }
+  ok(true, "App launchable");
+
+  if (MAC) {
+    stat = yield OS.File.stat(testAppInfo.webappINI);
+    is(stat.unixMode, 0o644, "Configuration file permissions correct");
+  } else if (LINUX) {
+    stat = yield OS.File.stat(testAppInfo.desktopINI);
+    is(stat.unixMode, 0o744, "Configuration file permissions correct");
+  }
+
+  ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
+  ok(!(yield OS.File.exists(OS.Path.join(testAppInfo.installPath, "update"))), "Update directory removed");
+  ok((yield checkDateHigherThan(testAppInfo.updatedFiles, installTime)), "Modification date higher");
+
+  stat = yield OS.File.stat(testAppInfo.installPath);
+  installTime = stat.lastModificationDate;
+
+  // Wait one second, otherwise the last modification date is the same.
+  yield wait(1000);
+
+  // Update application
+  info("Test update");
+  yield nativeApp.prepareUpdate(app, manifest);
+  while (!WebappOSUtils.isLaunchable(app)) {
+    yield wait(1000);
+  }
+  ok(true, "App launchable");
+  ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
+  ok((yield checkFiles(testAppInfo.tempUpdatedFiles)), "Files correctly written in the update subdirectory");
+
+  yield nativeApp.applyUpdate(app);
+  while (!WebappOSUtils.isLaunchable(app)) {
+    yield wait(1000);
+  }
+  ok(true, "App launchable");
+  ok((yield checkFiles(testAppInfo.installedFiles)), "Installation not corrupted");
+  ok(!(yield OS.File.exists(OS.Path.join(testAppInfo.installPath, "update"))), "Update directory removed");
+  ok((yield checkDateHigherThan(testAppInfo.updatedFiles, installTime)), "Modification date higher");
+
+  SimpleTest.finish();
+});
+
+runTest().catch((e) => {
+  ok(false, "Error during test: " + e);
+  SimpleTest.finish();
+});
+
+]]>
+</script>
+</window>
--- a/widget/gonk/nsAppShell.cpp
+++ b/widget/gonk/nsAppShell.cpp
@@ -44,16 +44,17 @@
 #include "mozilla/MouseEvents.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Services.h"
 #include "mozilla/TextEvents.h"
 #if ANDROID_VERSION >= 18
 #include "nativewindow/FakeSurfaceComposer.h"
 #endif
 #include "nsAppShell.h"
+#include "mozilla/DebugOnly.h"
 #include "mozilla/dom/Touch.h"
 #include "nsGkAtoms.h"
 #include "nsIObserverService.h"
 #include "nsIScreen.h"
 #include "nsScreenManagerGonk.h"
 #include "nsThreadUtils.h"
 #include "nsWindow.h"
 #include "OrientationObserver.h"
@@ -573,17 +574,17 @@ GeckoInputReaderPolicy::setDisplayInfo()
                   "Orientation enums not matched!");
     static_assert(nsIScreen::ROTATION_270_DEG ==
                   DISPLAY_ORIENTATION_270,
                   "Orientation enums not matched!");
 
     nsRefPtr<nsScreenGonk> screen = nsScreenManagerGonk::GetPrimaryScreen();
 
     uint32_t rotation = nsIScreen::ROTATION_0_DEG;
-    nsresult rv = screen->GetRotation(&rotation);
+    DebugOnly<nsresult> rv = screen->GetRotation(&rotation);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     nsIntRect screenBounds = screen->GetNaturalBounds();
 
     DisplayViewport viewport;
     viewport.displayId = 0;
     viewport.orientation = rotation;
     viewport.physicalRight = viewport.deviceWidth = screenBounds.width;
     viewport.physicalBottom = viewport.deviceHeight = screenBounds.height;