Merge b2g-inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 26 Jun 2014 16:55:43 -0400
changeset 190996 398a5f3142c150f26a2b41a53f5b8b22b4966e78
parent 190995 1b16fb9ff3529839823501f46017ea726516554b (current diff)
parent 190963 8efe02f2f988db0232ed4bff2086654541a81e79 (diff)
child 191065 3519e987aa3bba37b00dfe70e1382b4a5832d374
push id8417
push userryanvm@gmail.com
push dateThu, 26 Jun 2014 21:15:47 +0000
treeherderb2g-inbound@3bef42144aab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone33.0a1
Merge b2g-inbound to m-c. a=merge
--- 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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <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="3326b51017252e09ccdd715dec6c5e12a7d1ecfe"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- 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="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <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="276ce45e78b09c4a4ee643646f691d22804754c1">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <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="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
--- 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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <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="3326b51017252e09ccdd715dec6c5e12a7d1ecfe"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <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": "c2a75dc08b6c97aa2fb7cdf547f7231d96381106", 
+    "revision": "849cd3df00bea01e00f9d19a272c8e88c9571830", 
     "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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <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="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <!-- 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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <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="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <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="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="87a7746568ac5708e828026160c0732ba252300f"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="122325e6bf9ddc0a0ac07f5148880f159b9ad023"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <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="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7f9ec13a30f1b2cc8bdb1a199b7da54b9ab8860f"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/content/media/omx/RtspOmxDecoder.cpp
+++ b/content/media/omx/RtspOmxDecoder.cpp
@@ -18,10 +18,30 @@ MediaDecoder* RtspOmxDecoder::Clone()
 
 MediaDecoderStateMachine* RtspOmxDecoder::CreateStateMachine()
 {
   return new MediaDecoderStateMachine(this,
                                       new RtspOmxReader(this),
                                       mResource->IsRealTime());
 }
 
+void RtspOmxDecoder::ApplyStateToStateMachine(PlayState aState)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  MediaDecoder::ApplyStateToStateMachine(aState);
+
+  // Notify RTSP controller if the play state is ended.
+  // This is necessary for RTSP controller to transit its own state.
+  if (aState == PLAY_STATE_ENDED) {
+    nsRefPtr<RtspMediaResource> resource = mResource->GetRtspPointer();
+    if (resource) {
+      nsIStreamingProtocolController* controller =
+        resource->GetMediaStreamController();
+      if (controller) {
+        controller->PlaybackEnded();
+      }
+    }
+  }
+}
+
 } // namespace mozilla
 
--- a/content/media/omx/RtspOmxDecoder.h
+++ b/content/media/omx/RtspOmxDecoder.h
@@ -25,15 +25,17 @@ public:
   : MediaDecoder() {
     MOZ_COUNT_CTOR(RtspOmxDecoder);
   }
 
   ~RtspOmxDecoder() {
     MOZ_COUNT_DTOR(RtspOmxDecoder);
   }
 
-  virtual MediaDecoder* Clone() MOZ_OVERRIDE;
-  virtual MediaDecoderStateMachine* CreateStateMachine() MOZ_OVERRIDE;
+  virtual MediaDecoder* Clone() MOZ_OVERRIDE MOZ_FINAL;
+  virtual MediaDecoderStateMachine* CreateStateMachine() MOZ_OVERRIDE MOZ_FINAL;
+  virtual void ApplyStateToStateMachine(PlayState aState)
+                                        MOZ_OVERRIDE MOZ_FINAL;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/mobileconnection/interfaces/moz.build
+++ b/dom/mobileconnection/interfaces/moz.build
@@ -4,11 +4,12 @@
 # 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/.
 
 XPIDL_SOURCES += [
     'nsIMobileCellInfo.idl',
     'nsIMobileConnectionInfo.idl',
     'nsIMobileConnectionProvider.idl',
     'nsIMobileNetworkInfo.idl',
+    'nsINeighboringCellInfo.idl',
 ]
 
 XPIDL_MODULE = 'dom_mobileconnection'
new file mode 100644
--- /dev/null
+++ b/dom/mobileconnection/interfaces/nsINeighboringCellInfo.idl
@@ -0,0 +1,64 @@
+/* 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(909f5972-c74e-44dd-b72a-7ddb62aae617)]
+interface nsINeighboringCellIdsCallback : nsISupports
+{
+  /**
+   * result is an array of nsINeighboringCellInfo.
+   */
+  void notifyGetNeighboringCellIds(in jsval result);
+
+  /**
+   * Callback function with error message.
+   */
+  void notifyGetNeighboringCellIdsFailed(in DOMString error);
+};
+
+[scriptable, uuid(87dc222e-abb3-4342-95bf-626aa19fa20e)]
+interface nsINeighboringCellInfo: nsISupports
+{
+  /**
+   * Type of radio technology.
+   *
+   * Possible values: 'gsm', 'gprs', 'edge', 'umts', 'hsdpa', 'hsupa', 'hspa',
+   *                  'hspa+' or null (unknown).
+   */
+  readonly attribute DOMString networkType;
+
+  /**
+   * Mobile Location Area Code (LAC) for GSM networks.
+   *
+   * Possible ranges from 0x0000 to 0xffff.
+   * -1 if the LAC is unknown.
+   */
+  readonly attribute long gsmLocationAreaCode;
+
+  /**
+   * Mobile Cell ID for GSM networks.
+   *
+   * Possible ranges from 0x00000000 to 0xffffffff.
+   * -1 if the cell id is unknown.
+   */
+  readonly attribute long long gsmCellId;
+
+  /**
+   * Primary Scrambling Code (PSC) for WCDMA networks.
+   *
+   * Possible ranges from 0x0000 to 0x01ff.
+   * -1 if the psc is unknown.
+   */
+  readonly attribute long wcdmaPsc;
+
+  /**
+   * For GSM networks, signalStrength is the received rssi, ranging from 0 to 31.
+   * For WCDMA networks, signalStrength is the CPICH Received Signal Code Power,
+   * ranging from -120 to -25.
+   *
+   * 99 if signalStrength is unknown.
+   */
+  readonly attribute long signalStrength;
+};
\ No newline at end of file
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -49,16 +49,18 @@ const RADIOINTERFACELAYER_CID =
 const RADIOINTERFACE_CID =
   Components.ID("{6a7c91f0-a2b3-4193-8562-8969296c0b54}");
 const RILNETWORKINTERFACE_CID =
   Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
 const GSMICCINFO_CID =
   Components.ID("{d90c4261-a99d-47bc-8b05-b057bb7e8f8a}");
 const CDMAICCINFO_CID =
   Components.ID("{39ba3c08-aacc-46d0-8c04-9b619c387061}");
+const NEIGHBORINGCELLINFO_CID =
+  Components.ID("{f9dfe26a-851e-4a8b-a769-cbb1baae7ded}");
 
 const NS_XPCOM_SHUTDOWN_OBSERVER_ID      = "xpcom-shutdown";
 const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
 const kNetworkConnStateChangedTopic      = "network-connection-state-changed";
 const kNetworkActiveChangedTopic         = "network-active-changed";
 const kSmsReceivedObserverTopic          = "sms-received";
 const kSilentSmsReceivedObserverTopic    = "silent-sms-received";
 const kSmsSendingObserverTopic           = "sms-sending";
@@ -1050,16 +1052,35 @@ CdmaIccInfo.prototype = {
   }),
 
   // nsIDOMMozCdmaIccInfo
 
   mdn: null,
   prlVersion: 0
 };
 
+function NeighboringCellInfo() {}
+NeighboringCellInfo.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINeighboringCellInfo]),
+  classID:        NEIGHBORINGCELLINFO_CID,
+  classInfo:      XPCOMUtils.generateCI({
+    classID:          NEIGHBORINGCELLINFO_CID,
+    classDescription: "NeighboringCellInfo",
+    interfaces:       [Ci.nsINeighboringCellInfo]
+  }),
+
+  // nsINeighboringCellInfo
+
+  networkType: null,
+  gsmLocationAreaCode: -1,
+  gsmCellId: -1,
+  wcdmaPsc: -1,
+  signalStrength: 99
+};
+
 function DataConnectionHandler(clientId, radioInterface) {
   // Initial owning attributes.
   this.clientId = clientId;
   this.radioInterface = radioInterface;
   this.dataCallSettings = {
     oldEnabled: false,
     enabled: false,
     roamingEnabled: false
@@ -4347,16 +4368,38 @@ RadioInterface.prototype = {
   sendWorkerMessage: function(rilMessageType, message, callback) {
     if (callback) {
       this.workerMessenger.send(rilMessageType, message, function(response) {
         return callback.handleResponse(response);
       });
     } else {
       this.workerMessenger.send(rilMessageType, message);
     }
+  },
+
+  getNeighboringCellIds: function(callback) {
+    this.workerMessenger.send("getNeighboringCellIds",
+                              null,
+                              function(response) {
+      if (response.errorMsg) {
+        callback.notifyGetNeighboringCellIdsFailed(response.errorMsg);
+        return;
+      }
+
+      let neighboringCellIds = [];
+      let count = response.result.length;
+      for (let i = 0; i < count; i++) {
+        let srcCellInfo = response.result[i];
+        let cellInfo = new NeighboringCellInfo();
+        this.updateInfo(srcCellInfo, cellInfo);
+        neighboringCellIds.push(cellInfo);
+      }
+      callback.notifyGetNeighboringCellIds(neighboringCellIds);
+
+    }.bind(this));
   }
 };
 
 function DataCall(clientId, apnSetting) {
   this.clientId = clientId;
   this.apnProfile = {
     apn: apnSetting.apn,
     user: apnSetting.user,
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "nsINetworkManager.idl"
 
 interface nsIDOMMozIccInfo;
 interface nsIMobileConnectionInfo;
 interface nsIMobileMessageCallback;
+interface nsINeighboringCellIdsCallback;
 
 [scriptable, uuid(6e0f45b8-410e-11e3-8c8e-b715b2cd0128)]
 interface nsIRilNetworkInterface : nsINetworkInterface
 {
   readonly attribute unsigned long serviceId;
   readonly attribute DOMString iccId;
 
   /* The following attributes are for MMS proxy settings. */
@@ -50,17 +51,17 @@ interface nsIRilContext : nsISupports
 };
 
 [scriptable, function, uuid(3bc96351-53b0-47a1-a888-c74c64b60f25)]
 interface nsIRilSendWorkerMessageCallback : nsISupports
 {
   boolean handleResponse(in jsval response);
 };
 
-[scriptable, uuid(181d460e-220e-4274-8ba4-43f122eb518d)]
+[scriptable, uuid(31ba65b6-05c7-4bc8-abdc-f1a219811fb4)]
 interface nsIRadioInterface : nsISupports
 {
   readonly attribute nsIRilContext rilContext;
 
   /**
    * PDP APIs
    */
   void setupDataCallByType(in DOMString apntype);
@@ -80,16 +81,21 @@ interface nsIRadioInterface : nsISupport
                in boolean silent,
                in nsIMobileMessageCallback request);
 
   void sendWorkerMessage(in DOMString type,
               [optional] in jsval message,
               [optional] in nsIRilSendWorkerMessageCallback callback);
 
   void getSmscAddress(in nsIMobileMessageCallback request);
+
+  /**
+   * Cell Info functionality.
+   */
+  void getNeighboringCellIds(in nsINeighboringCellIdsCallback callback);
 };
 
 [scriptable, uuid(d035c32e-b491-11e3-9f9d-c716fab88bd6)]
 interface nsIRadioInterfaceLayer : nsISupports
 {
   readonly attribute unsigned long numRadioInterfaces;
 
   nsIRadioInterface getRadioInterface(in unsigned long clientId);
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -1296,16 +1296,23 @@ RilObject.prototype = {
   /**
    * Get the preferred network type.
    */
   getPreferredNetworkType: function(options) {
     this.context.Buf.simpleRequest(REQUEST_GET_PREFERRED_NETWORK_TYPE, options);
   },
 
   /**
+   * Request neighboring cell ids in GSM network.
+   */
+  getNeighboringCellIds: function(options) {
+    this.context.Buf.simpleRequest(REQUEST_GET_NEIGHBORING_CELL_IDS, options);
+  },
+
+  /**
    * Request various states about the network.
    */
   requestNetworkInfo: function() {
     if (this._processingNetworkInfo) {
       if (DEBUG) {
         this.context.debug("Network info requested, but we're already " +
                            "requesting network info.");
       }
@@ -6376,17 +6383,78 @@ RilObject.prototype[REQUEST_GET_PREFERRE
     this.sendChromeMessage(options);
     return;
   }
 
   let networkType = this.context.Buf.readInt32List()[0];
   options.type = RIL_PREFERRED_NETWORK_TYPE_TO_GECKO[networkType];
   this.sendChromeMessage(options);
 };
-RilObject.prototype[REQUEST_GET_NEIGHBORING_CELL_IDS] = null;
+RilObject.prototype[REQUEST_GET_NEIGHBORING_CELL_IDS] = function REQUEST_GET_NEIGHBORING_CELL_IDS(length, options) {
+  if (options.rilRequestError) {
+    options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
+    this.sendChromeMessage(options);
+    return;
+  }
+
+  let radioTech = this.voiceRegistrationState.radioTech;
+  if (radioTech == undefined || radioTech == NETWORK_CREG_TECH_UNKNOWN) {
+    options.errorMsg = "RadioTechUnavailable";
+    this.sendChromeMessage(options);
+    return;
+  }
+  if (!this._isGsmTechGroup(radioTech) || radioTech == NETWORK_CREG_TECH_LTE) {
+    options.errorMsg = "UnsupportedRadioTech";
+    this.sendChromeMessage(options);
+    return;
+  }
+
+  let Buf = this.context.Buf;
+  let neighboringCellIds = [];
+  let num = Buf.readInt32();
+
+  for (let i = 0; i < num; i++) {
+    let cellId = {};
+    cellId.networkType = GECKO_RADIO_TECH[radioTech];
+    cellId.signalStrength = Buf.readInt32();
+
+    let cid = Buf.readString();
+    // pad cid string with leading "0"
+    let length = cid.length;
+    if (length > 8) {
+      continue;
+    }
+    if (length < 8) {
+      for (let j = 0; j < (8-length); j++) {
+        cid = "0" + cid;
+      }
+    }
+
+    switch (radioTech) {
+      case NETWORK_CREG_TECH_GPRS:
+      case NETWORK_CREG_TECH_EDGE:
+      case NETWORK_CREG_TECH_GSM:
+        cellId.gsmCellId = this.parseInt(cid.substring(4), -1, 16);
+        cellId.gsmLocationAreaCode = this.parseInt(cid.substring(0, 4), -1, 16);
+        break;
+      case NETWORK_CREG_TECH_UMTS:
+      case NETWORK_CREG_TECH_HSDPA:
+      case NETWORK_CREG_TECH_HSUPA:
+      case NETWORK_CREG_TECH_HSPA:
+      case NETWORK_CREG_TECH_HSPAP:
+        cellId.wcdmaPsc = this.parseInt(cid, -1, 16);
+        break;
+    }
+
+    neighboringCellIds.push(cellId);
+  }
+
+  options.result = neighboringCellIds;
+  this.sendChromeMessage(options);
+};
 RilObject.prototype[REQUEST_SET_LOCATION_UPDATES] = null;
 RilObject.prototype[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null;
 RilObject.prototype[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   this.sendChromeMessage(options);
 };
--- a/dom/system/gonk/tests/marionette/manifest.ini
+++ b/dom/system/gonk/tests/marionette/manifest.ini
@@ -7,8 +7,9 @@ qemu = true
 disabled = Bug 808783
 [test_fakevolume.js]
 [test_ril_code_quality.py]
 [test_screen_state.js]
 [test_dsds_numRadioInterfaces.js]
 [test_data_connection.js]
 [test_network_active_changed.js]
 [test_multiple_data_connection.js]
+[test_neighboring_cell_ids.js]
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/marionette/test_neighboring_cell_ids.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 30000;
+MARIONETTE_HEAD_JS = "head.js";
+
+function testGetNeighboringCellIds() {
+  log("Test getting neighboring cell ids");
+  let deferred = Promise.defer();
+
+  radioInterface.getNeighboringCellIds({
+    notifyGetNeighboringCellIds: function(aResult) {
+      deferred.resolve(aResult);
+    },
+    notifyGetNeighboringCellIdsFailed: function(aError) {
+      deferred.reject(aError);
+    }
+  });
+  return deferred.promise;
+}
+
+// Start tests
+startTestBase(function() {
+  // TODO: Bug 1028837 - B2G Emulator: support neighboring cell ids.
+  // Currently, emulator does not support RIL_REQUEST_NEIGHBORING_CELL_IDS,
+  // so we expect to get a 'RequestNotSupported' error here.
+  return testGetNeighboringCellIds()
+    .then(function resolve(aResult) {
+      ok(false, "getNeighboringCellIds should not success");
+    }, function reject(aError) {
+      is(aError, "RequestNotSupported", "failed to getNeighboringCellIds");
+    });
+});
--- a/dom/telephony/gonk/TelephonyService.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -434,36 +434,36 @@ TelephonyService.prototype = {
     if (!gPhoneNumberUtils.isPlainPhoneNumber(aNumber)) {
       // Note: isPlainPhoneNumber also accepts USSD and SS numbers
       if (DEBUG) debug("Number '" + aNumber + "' is not viable. Drop.");
       let errorMsg = RIL.RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[RIL.CALL_FAIL_UNOBTAINABLE_NUMBER];
       aTelephonyCallback.notifyDialError(errorMsg);
       return;
     }
 
-    function onCdmaDialSuccess() {
+    function onCdmaDialSuccess(aCallIndex) {
       let indexes = Object.keys(this._currentCalls[aClientId]);
-      if (indexes.length != 1 ) {
-        aTelephonyCallback.notifyDialSuccess();
+      if (indexes.length == 0) {
+        aTelephonyCallback.notifyDialSuccess(aCallIndex);
         return;
       }
 
       // RIL doesn't hold the 2nd call. We create one by ourselves.
       let childCall = {
         callIndex: CDMA_SECOND_CALL_INDEX,
         state: RIL.CALL_STATE_DIALING,
         number: aNumber,
         isOutgoing: true,
         isEmergency: false,
         isConference: false,
         isSwitchable: false,
         isMergeable: true,
         parentId: indexes[0]
       };
-      aTelephonyCallback.notifyDialSuccess();
+      aTelephonyCallback.notifyDialSuccess(CDMA_SECOND_CALL_INDEX);
 
       // Manual update call state according to the request response.
       this.notifyCallStateChanged(aClientId, childCall);
 
       childCall.state = RIL.CALL_STATE_ACTIVE;
       this.notifyCallStateChanged(aClientId, childCall);
 
       let parentCall = this._currentCalls[aClientId][childCall.parentId];
@@ -481,17 +481,17 @@ TelephonyService.prototype = {
     }, (function(response) {
       this.isDialing = false;
       if (!response.success) {
         aTelephonyCallback.notifyDialError(response.errorMsg);
         return false;
       }
 
       if (response.isCdma) {
-        onCdmaDialSuccess.call(this);
+        onCdmaDialSuccess.call(this, response.callIndex);
       } else {
         aTelephonyCallback.notifyDialSuccess(response.callIndex);
       }
       return false;
     }).bind(this));
   },
 
   hangUp: function(aClientId, aCallIndex) {
--- a/netwerk/base/public/nsIStreamingProtocolController.idl
+++ b/netwerk/base/public/nsIStreamingProtocolController.idl
@@ -110,17 +110,17 @@ interface nsIStreamingProtocolListener :
      * @param reason The reason of disconnection.
      */
     void onDisconnected(in uint8_t index, in nsresult reason);
 };
 
 /**
  * Media stream controller API: control and retrieve meta data from media stream.
  */
-[uuid(a9bdd4b0-8559-11e2-9e96-0800200c9a66)]
+[uuid(4ce040f0-c50d-461f-94e2-af5a77fe13a5)]
 interface nsIStreamingProtocolController : nsISupports
 {
     /**
      * Preprare the URI before we can start the connection.
      * @param aUri The URI of the media stream.
      */
     void init(in nsIURI aUri);
 
@@ -168,13 +168,19 @@ interface nsIStreamingProtocolController
     void seek(in unsigned long long seekTimeUs);
 
     /*
      * Tell the streaming server to stop the
      * media stream and close the connection.
      */
     void stop();
 
+    /*
+     * Notify the streaming controller that the playback has ended.
+     * The controller might have to perform certain internal state transition.
+     */
+    void playbackEnded();
+
     /**
      * Total number of audio/video tracks.
      */
     readonly attribute octet totalTracks;
 };
--- a/netwerk/ipc/PRtspController.ipdl
+++ b/netwerk/ipc/PRtspController.ipdl
@@ -39,16 +39,17 @@ async protocol PRtspController
 parent:
   AsyncOpen(URIParams aURI);
   Play();
   Pause();
   Resume();
   Suspend();
   Seek(uint64_t offset);
   Stop();
+  PlaybackEnded();
   __delete__();
 
 child:
   OnMediaDataAvailable(uint8_t index,
                        nsCString data,
                        uint32_t length,
                        uint32_t offset,
                        RtspMetadataParam[] meta);
--- a/netwerk/protocol/rtsp/controller/RtspController.cpp
+++ b/netwerk/protocol/rtsp/controller/RtspController.cpp
@@ -364,10 +364,23 @@ RtspController::Init(nsIURI *aURI)
   rv = aURI->GetAsciiSpec(mSpec);
   if (NS_FAILED(rv)) return rv;
 
   mURI = aURI;
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+RtspController::PlaybackEnded()
+{
+  LOG(("RtspController::PlaybackEnded()"));
+  if (!mRtspSource.get()) {
+    MOZ_ASSERT(mRtspSource.get(), "mRtspSource should not be null!");
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  mRtspSource->playbackEnded();
+  return NS_OK;
+}
+
 } // namespace mozilla::net
 } // namespace mozilla
--- a/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp
+++ b/netwerk/protocol/rtsp/controller/RtspControllerChild.cpp
@@ -232,17 +232,18 @@ RtspControllerChild::GetTrackMetaData(
 enum IPCEvent
 {
   SendNoneEvent = 0,
   SendPlayEvent,
   SendPauseEvent,
   SendSeekEvent,
   SendResumeEvent,
   SendSuspendEvent,
-  SendStopEvent
+  SendStopEvent,
+  SendPlaybackEndedEvent
 };
 
 class SendIPCEvent : public nsRunnable
 {
 public:
   SendIPCEvent(RtspControllerChild *aController, IPCEvent aEvent)
     : mController(aController)
     , mEvent(aEvent)
@@ -276,16 +277,18 @@ public:
     } else if (mEvent == SendSeekEvent) {
       rv = mController->SendSeek(mSeekTime);
     } else if (mEvent == SendResumeEvent) {
       rv = mController->SendResume();
     } else if (mEvent == SendSuspendEvent) {
       rv = mController->SendSuspend();
     } else if (mEvent == SendStopEvent) {
       rv = mController->SendStop();
+    } else if (mEvent == SendPlaybackEndedEvent) {
+      rv = mController->SendPlaybackEnded();
     } else {
       LOG(("RtspControllerChild::SendIPCEvent"));
     }
     if (!rv) {
       return NS_ERROR_FAILURE;
     }
     return NS_OK;
   }
@@ -419,16 +422,34 @@ RtspControllerChild::GetTotalTracks(uint
   *aTracks = kRtspTotalTracks;
   if (mTotalTracks) {
     *aTracks = mTotalTracks;
   }
   LOG(("RtspControllerChild::GetTracks() %d", *aTracks));
   return NS_OK;
 }
 
+NS_IMETHODIMP
+RtspControllerChild::PlaybackEnded()
+{
+  LOG(("RtspControllerChild::PlaybackEnded"));
+
+  if (NS_IsMainThread()) {
+    if (!OKToSendIPC() || !SendPlaybackEnded()) {
+      return NS_ERROR_FAILURE;
+    }
+  } else {
+    nsresult rv = NS_DispatchToMainThread(
+                    new SendIPCEvent(this, SendPlaybackEndedEvent));
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return NS_OK;
+}
+
 //-----------------------------------------------------------------------------
 // RtspControllerChild::nsIStreamingProtocolListener
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP
 RtspControllerChild::OnMediaDataAvailable(uint8_t index,
                                           const nsACString & data,
                                           uint32_t length,
                                           uint32_t offset,
--- a/netwerk/protocol/rtsp/controller/RtspControllerParent.cpp
+++ b/netwerk/protocol/rtsp/controller/RtspControllerParent.cpp
@@ -162,16 +162,27 @@ RtspControllerParent::RecvStop()
   LOG(("RtspControllerParent::RecvStop()"));
   NS_ENSURE_TRUE(mController, true);
 
   nsresult rv = mController->Stop();
   NS_ENSURE_SUCCESS(rv, true);
   return true;
 }
 
+bool
+RtspControllerParent::RecvPlaybackEnded()
+{
+  LOG(("RtspControllerParent::RecvPlaybackEnded()"));
+  NS_ENSURE_TRUE(mController, true);
+
+  nsresult rv = mController->PlaybackEnded();
+  SEND_DISCONNECT_IF_ERROR(rv)
+  return true;
+}
+
 NS_IMETHODIMP
 RtspControllerParent::OnMediaDataAvailable(uint8_t index,
                                            const nsACString & data,
                                            uint32_t length,
                                            uint32_t offset,
                                            nsIStreamingProtocolMetaData *meta)
 {
   NS_ENSURE_ARG_POINTER(meta);
--- a/netwerk/protocol/rtsp/controller/RtspControllerParent.h
+++ b/netwerk/protocol/rtsp/controller/RtspControllerParent.h
@@ -32,16 +32,17 @@ class RtspControllerParent : public PRts
 
   bool RecvAsyncOpen(const URIParams& aURI);
   bool RecvPlay();
   bool RecvPause();
   bool RecvResume();
   bool RecvSuspend();
   bool RecvSeek(const uint64_t& offset);
   bool RecvStop();
+  bool RecvPlaybackEnded();
 
  private:
   bool mIPCOpen;
   void ActorDestroy(ActorDestroyReason why);
   // RTSP URL refer to a stream or an aggregate of streams.
   nsCOMPtr<nsIURI> mURI;
   // The nsIStreamingProtocolController implementation.
   nsCOMPtr<nsIStreamingProtocolController> mController;
--- a/netwerk/protocol/rtsp/rtsp/RTSPSource.cpp
+++ b/netwerk/protocol/rtsp/rtsp/RTSPSource.cpp
@@ -127,16 +127,23 @@ void RTSPSource::suspend()
 }
 
 void RTSPSource::seek(uint64_t timeUs)
 {
     LOGI("RTSPSource::seek() %llu", timeUs);
     seekTo(timeUs);
 }
 
+void RTSPSource::playbackEnded()
+{
+    LOGI("RTSPSource::playbackEnded()");
+    sp<AMessage> msg = new AMessage(kWhatPerformPlaybackEnded, mReflector->id());
+    msg->post();
+}
+
 status_t RTSPSource::feedMoreTSData() {
     return mFinalResult;
 }
 
 sp<MetaData> RTSPSource::getFormat(bool audio) {
     sp<AnotherPacketSource> source = getSource(audio);
 
     if (source == NULL) {
@@ -241,16 +248,25 @@ void RTSPSource::performPause() {
 void RTSPSource::performResume() {
 // TODO, Bug 895753.
 }
 
 void RTSPSource::performSuspend() {
 // TODO, Bug 895753.
 }
 
+void RTSPSource::performPlaybackEnded() {
+    // Transition from PLAYING to CONNECTED state so that we are ready to
+    // perform an another play operation.
+    if (mState != PLAYING) {
+        return;
+    }
+    mState = CONNECTED;
+}
+
 void RTSPSource::performSeek(int64_t seekTimeUs) {
     if (mState != CONNECTED && mState != PLAYING && mState != PAUSING) {
         return;
     }
 
     int64_t duration = 0;
     getDuration(&duration);
     MOZ_ASSERT(seekTimeUs < duration,
@@ -305,16 +321,19 @@ void RTSPSource::onMessageReceived(const
         performPause();
         return;
     } else if (msg->what() == kWhatPerformResume) {
         performResume();
         return;
     } else if (msg->what() == kWhatPerformSuspend) {
         performSuspend();
         return;
+    } else if (msg->what() == kWhatPerformPlaybackEnded) {
+        performPlaybackEnded();
+        return;
     }
 
     CHECK_EQ(msg->what(), (uint32_t)kWhatNotify);
 
     int32_t what;
     int32_t isSeekable = 0;
     CHECK(msg->findInt32("what", &what));
 
@@ -670,17 +689,16 @@ void RTSPSource::onTrackDataAvailable(si
 
     if (mListener) {
         mListener->OnMediaDataAvailable(trackIndex, data, data.Length(), 0, meta.get());
     }
 }
 
 void RTSPSource::onTrackEndOfStream(size_t trackIndex)
 {
-    mState = CONNECTED;
     if (!mListener) {
         return;
     }
 
     nsRefPtr<nsIStreamingProtocolMetaData> meta;
     meta = new mozilla::net::RtspMetaData();
     meta->SetFrameType(MEDIASTREAM_FRAMETYPE_END_OF_STREAM);
 
--- a/netwerk/protocol/rtsp/rtsp/RTSPSource.h
+++ b/netwerk/protocol/rtsp/rtsp/RTSPSource.h
@@ -49,16 +49,17 @@ public:
     void start();
     void stop();
 
     void play();
     void pause();
     void seek(uint64_t timeUs);
     void resume();
     void suspend();
+    void playbackEnded();
 
     status_t feedMoreTSData();
 
     sp<MetaData> getFormat(bool audio);
     status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
 
     status_t getDuration(int64_t *durationUs);
     status_t seekTo(int64_t seekTimeUs);
@@ -66,23 +67,24 @@ public:
 
     void onMessageReceived(const sp<AMessage> &msg);
 
 protected:
     ~RTSPSource();
 
 private:
     enum {
-        kWhatNotify          = 'noti',
-        kWhatDisconnect      = 'disc',
-        kWhatPerformSeek     = 'seek',
-        kWhatPerformPlay     = 'play',
-        kWhatPerformPause    = 'paus',
-        kWhatPerformResume   = 'resu',
-        kWhatPerformSuspend  = 'susp',
+        kWhatNotify               = 'noti',
+        kWhatDisconnect           = 'disc',
+        kWhatPerformSeek          = 'seek',
+        kWhatPerformPlay          = 'play',
+        kWhatPerformPause         = 'paus',
+        kWhatPerformResume        = 'resu',
+        kWhatPerformSuspend       = 'susp',
+        kWhatPerformPlaybackEnded = 'ende',
     };
 
     enum State {
         DISCONNECTED,
         CONNECTING,
         CONNECTED,
         SEEKING,
         PAUSING,
@@ -135,16 +137,18 @@ private:
     void performPlay(int64_t playTimeUs);
 
     void performPause();
 
     void performResume();
 
     void performSuspend();
 
+    void performPlaybackEnded();
+
     void onTrackDataAvailable(size_t trackIndex);
 
     void onTrackEndOfStream(size_t trackIndex);
 
     nsMainThreadPtrHandle<nsIStreamingProtocolListener> mListener;
     int mPrintCount;
 
     DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);