Bug 1357639 - part9 : wait tab event to make sure media started successfully. draft
authorAlastor Wu <alwu@mozilla.com>
Mon, 08 May 2017 14:10:59 +0800
changeset 573971 b406b449d986f8384823b525c723b7de54ca0a56
parent 573970 b42d9cef62892dba67d5e6c9f5d3336ee4aeeb0a
child 573972 bbffa22978cdff48df1e938f032ac64c943ea33f
child 574618 394ed038ce22ea763d3285cdd0fb7f18c2052a5a
push id57550
push useralwu@mozilla.com
push dateMon, 08 May 2017 07:06:13 +0000
bugs1357639
milestone55.0a1
Bug 1357639 - part9 : wait tab event to make sure media started successfully. Since the robocop tests would run on super slow emulator on try, and then we can't wait the tab's audible state change within the MAX_WAIT_MS time. It might need more time. So, we should check the media has been started by waiting the "Tab:MediaPlaybackChange" event, and then to check other tab's attribute. In addition, move the tab attribute checking independently into new functions, so that we would clearly see that we have four things need to check in function checkIfMediaPlayingSuccess(). - tab's media playing state - media notification UI - tab's audio playing state - audio focus state MozReview-Commit-ID: 8S0Ems23iPX
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MediaPlaybackTest.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAudioFocus.java
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMediaControl.java
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MediaPlaybackTest.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/MediaPlaybackTest.java
@@ -21,17 +21,16 @@ import android.graphics.drawable.Icon;
 import android.os.Build;
 import android.service.notification.StatusBarNotification;
 
 import com.robotium.solo.Condition;
 
 abstract class MediaPlaybackTest extends BaseTest {
     private Context mContext;
     private int mPrevIcon = 0;
-    private boolean mPrevTabAudioPlaying = false;
 
     protected final void info(String msg) {
         mAsserter.dumpLog(msg);
     }
 
     protected final Context getContext() {
         if (mContext == null) {
             mContext = getInstrumentation().getTargetContext();
@@ -67,70 +66,116 @@ abstract class MediaPlaybackTest extends
                     return true;
                 }
                 return false;
             }
         }, MAX_WAIT_MS);
     }
 
     /**
-     * Get the selected tab and check whether tab's audio playing state has
-     * been changed.
+     * Use these methods to wait the tab playing related states changed.
      */
-    protected final void waitUntilTabAudioPlayingStateChanged() {
+    protected final void waitUntilTabMediaStarted(final Tab tab) {
+        if (tab.isMediaPlaying()) {
+            return;
+        }
+        // Tab:MediaPlaybackChange would be dispatched when media started or
+        // ended, but it won't be dispatched when we pause/resume media via
+        // media control.
+        Actions.EventExpecter contentEventExpecter =
+                mActions.expectGlobalEvent(Actions.EventType.UI, "Tab:MediaPlaybackChange");
+        contentEventExpecter.blockForEvent();
+        contentEventExpecter.unregisterListener();
+    }
+
+    private final void waitUntilTabAudioPlayingStateChanged(final Tab tab,
+                                                            final boolean isTabPlaying) {
+        if (tab.isAudioPlaying() == isTabPlaying) {
+            return;
+        }
         waitForCondition(new Condition() {
             @Override
             public boolean isSatisfied() {
-                Tab tab = Tabs.getInstance().getSelectedTab();
-                if (tab.isAudioPlaying() != mPrevTabAudioPlaying) {
-                    mPrevTabAudioPlaying = tab.isAudioPlaying();
-                    return true;
-                }
-                return false;
+                return tab.isAudioPlaying() == isTabPlaying;
+            }
+        }, MAX_WAIT_MS);
+    }
+
+    private final void waitUntilTabMediaPlaybackChanged(final Tab tab,
+                                                        final boolean isTabPlaying) {
+        if (tab.isMediaPlaying() == isTabPlaying) {
+            return;
+        }
+        waitForCondition(new Condition() {
+            @Override
+            public boolean isSatisfied() {
+                return tab.isMediaPlaying() == isTabPlaying;
             }
         }, MAX_WAIT_MS);
     }
 
     /**
+     * These methods are used to check Tab's playing related attributes.
+     * isMediaPlaying : is any media playing (might be audible or non-audbile)
+     * isAudioPlaying : is any audible media playing
+     */
+    protected final void checkTabMediaPlayingState(final Tab tab,
+                                                   final boolean isTabPlaying) {
+        waitUntilTabMediaPlaybackChanged(tab, isTabPlaying);
+        mAsserter.ok(isTabPlaying == tab.isMediaPlaying(),
+                     "Checking the media playing state of tab, isTabPlaying = " + isTabPlaying,
+                     "Tab's media playing state is correct.");
+    }
+
+    protected final void checkTabAudioPlayingState(final Tab tab,
+                                                   final boolean isTabPlaying) {
+        waitUntilTabAudioPlayingStateChanged(tab, isTabPlaying);
+        mAsserter.ok(isTabPlaying == tab.isAudioPlaying(),
+                     "Checking the audio playing state of tab, isTabPlaying = " + isTabPlaying,
+                     "Tab's audio playing state is correct.");
+    }
+
+    /**
      * Since we can't testing media control via clicking the media control, we
      * directly send intent to service to simulate the behavior.
      */
     protected final void notifyMediaControlService(String action) {
         Intent intent = new Intent(getContext(), MediaControlService.class);
         intent.setAction(action);
         getContext().startService(intent);
     }
 
     /**
      * Use these methods when both media control and audio focus state should
      * be changed and you want to check whether the changing are correct or not.
+     * Checking selected tab is default option.
      */
     protected final void checkIfMediaPlayingSuccess(boolean isTabPlaying) {
         checkIfMediaPlayingSuccess(isTabPlaying, false);
     }
 
     protected final void checkIfMediaPlayingSuccess(boolean isTabPlaying,
                                                     boolean clearNotification) {
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        checkTabMediaPlayingState(tab, isTabPlaying);
+        checkMediaNotificationStatesAfterChanged(tab, isTabPlaying, clearNotification);
+
+        checkTabAudioPlayingState(tab, isTabPlaying);
         checkAudioFocusStateAfterChanged(isTabPlaying);
-        checkMediaNotificationStatesAfterChanged(isTabPlaying, clearNotification);
     }
 
     /**
      * This method is used to check whether notification states are correct or
      * not after notification UI changed.
      */
-    protected final void checkMediaNotificationStatesAfterChanged(boolean isTabPlaying,
-                                                                  boolean clearNotification) {
+    protected final void checkMediaNotificationStatesAfterChanged(final Tab tab,
+                                                                  final boolean isTabPlaying,
+                                                                  final boolean clearNotification) {
         waitUntilNotificationUIChanged();
 
-        final Tab tab = Tabs.getInstance().getSelectedTab();
-        mAsserter.ok(isTabPlaying == tab.isMediaPlaying(),
-                     "Checking the media playing state of tab, isTabPlaying = " + isTabPlaying,
-                     "Tab's media playing state is correct.");
-
         if (clearNotification) {
             checkIfMediaNotificationBeCleared();
         } else {
             checkMediaNotificationStates(tab, isTabPlaying);
         }
     }
 
     protected final void checkMediaNotificationStates(final Tab tab,
@@ -176,23 +221,16 @@ abstract class MediaPlaybackTest extends
                      "Should not have notification in system's status bar.");
     }
 
     /**
      * This method is used to check whether audio focus state are correct or
      * not after tab's audio playing state changed.
      */
     protected final void checkAudioFocusStateAfterChanged(boolean isTabPlaying) {
-        waitUntilTabAudioPlayingStateChanged();
-
-        final Tab tab = Tabs.getInstance().getSelectedTab();
-        mAsserter.ok(isTabPlaying == tab.isAudioPlaying(),
-                     "Checking the audio playing state of tab, isTabPlaying = " + isTabPlaying,
-                     "Tab's audio playing state is correct.");
-
         if (isTabPlaying) {
             mAsserter.is(AudioFocusAgent.getInstance().getAudioFocusState(),
                          State.OWN_FOCUS,
                          "Audio focus state is correct.");
         } else {
             boolean isLostFocus =
                 AudioFocusAgent.getInstance().getAudioFocusState().equals(State.LOST_FOCUS) ||
                 AudioFocusAgent.getInstance().getAudioFocusState().equals(State.LOST_FOCUS_TRANSIENT);
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAudioFocus.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testAudioFocus.java
@@ -1,14 +1,16 @@
 /* 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/. */
 
 package org.mozilla.gecko.tests;
 
+import org.mozilla.gecko.Tab;
+import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.media.AudioFocusAgent.State;
 
 import android.media.AudioManager;
 
 public class testAudioFocus extends MediaPlaybackTest {
     public void testAudioFocus() {
         info("- wait for gecko ready -");
         blockForGeckoReady();
@@ -83,60 +85,59 @@ public class testAudioFocus extends Medi
         mAsserter.is(getAudioFocusAgent().getAudioFocusState(),
                      State.LOST_FOCUS,
                      "Should not request audio focus before media starts.");
 
         info("- load URL with looping audio file -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
-        info("- wait audio starts playing -");
-        waitUntilTabAudioPlayingStateChanged();
-        mAsserter.is(getAudioFocusAgent().getAudioFocusState(),
-                     State.OWN_FOCUS,
-                     "Should request audio focus after media started playing.");
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
+        info("- wait tab becomes audible -");
+        checkTabAudioPlayingState(tab, true /* audible */);
+        checkAudioFocusStateAfterChanged(true);
 
         info("- simulate losing audio focus transiently -");
         getAudioFocusAgent().changeAudioFocus(AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
-        waitUntilTabAudioPlayingStateChanged();
-        mAsserter.is(getAudioFocusAgent().getAudioFocusState(),
-                     State.LOST_FOCUS_TRANSIENT,
-                     "Should lose audio focus.");
+        checkTabAudioPlayingState(tab, false /* non-audible */);
+        checkAudioFocusStateAfterChanged(false);
 
         info("- simulate gaining audio focus again -");
         getAudioFocusAgent().changeAudioFocus(AudioManager.AUDIOFOCUS_GAIN);
-        waitUntilTabAudioPlayingStateChanged();
-        mAsserter.is(getAudioFocusAgent().getAudioFocusState(),
-                     State.OWN_FOCUS,
-                     "Should own audio focus.");
+        checkTabAudioPlayingState(tab, true /* audible */);
+        checkAudioFocusStateAfterChanged(true);
 
         info("- simulate losing audio focus -");
         getAudioFocusAgent().changeAudioFocus(AudioManager.AUDIOFOCUS_LOSS);
-        waitUntilTabAudioPlayingStateChanged();
-        mAsserter.is(getAudioFocusAgent().getAudioFocusState(),
-                     State.LOST_FOCUS,
-                     "Should abandon audio focus after media stopped playing.");
+        checkTabAudioPlayingState(tab, false /* non-audible */);
+        checkAudioFocusStateAfterChanged(false);
 
         info("- close tab -");
         closeAllTabs();
     }
 
     private void testSwitchTab() {
         info("- load URL -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
-        info("- check whether audio starts playing -");
-        waitUntilTabAudioPlayingStateChanged();
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
+        info("- wait tab becomes audible -");
+        checkTabAudioPlayingState(tab, true /* audible */);
+        checkAudioFocusStateAfterChanged(true);
 
         info("- switch to the another tab -");
         final String BLANK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL);
         addTab(BLANK_URL);
 
         info("- should still own the audio focus -");
-        mAsserter.is(getAudioFocusAgent().getAudioFocusState(),
-                     State.OWN_FOCUS,
-                     "Should own audio focus.");
+        checkAudioFocusStateAfterChanged(true);
 
         info("- close tab -");
         closeAllTabs();
     }
 }
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMediaControl.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testMediaControl.java
@@ -34,16 +34,20 @@ public class testMediaControl extends Me
         testCloseTab();
     }
 
     private void testBasicBehaviors() {
         info("- load URL -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
         info("- check whether audio starts playing -");
         checkIfMediaPlayingSuccess(true /* playing */);
 
         info("- simulate media control pause -");
         notifyMediaControlService(MediaControlService.ACTION_PAUSE);
         checkIfMediaPlayingSuccess(false /* paused */);
 
         info("- simulate media control resume -");
@@ -58,16 +62,20 @@ public class testMediaControl extends Me
         closeAllTabs();
     }
 
     private void testNavigateOutThePage() {
         info("- load URL -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
         info("- check whether audio starts playing -");
         checkIfMediaPlayingSuccess(true /* playing */);
 
         info("- navigate out the present page -");
         final String BLANK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL);
         loadUrlAndWait(BLANK_URL);
         checkIfMediaPlayingSuccess(false /* paused */, true /* clear notification */);
 
@@ -78,16 +86,20 @@ public class testMediaControl extends Me
         testAudioFocusChanged();
     }
 
     private void testAudioFocusChanged() {
         info("- load URL -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
         info("- check whether audio starts playing -");
         checkIfMediaPlayingSuccess(true /* playing */);
 
         info("- simulate lose audio focus transiently -");
         getAudioFocusAgent().changeAudioFocus(AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
         checkIfMediaPlayingSuccess(false /* paused */);
 
         info("- simulate gain audio focus again -");
@@ -102,41 +114,47 @@ public class testMediaControl extends Me
         closeAllTabs();
     }
 
     private void testSwitchTab() {
         info("- load URL -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
         info("- check whether audio starts playing -");
         checkIfMediaPlayingSuccess(true /* playing */);
 
         info("- switch to the another tab -");
         final String BLANK_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_BLANK_PAGE_01_URL);
         addTab(BLANK_URL);
 
         info("- the media control shouldn't be changed and display the info of audible tab -");
-        final Tab tab = Tabs.getInstance().getFirstTabForUrl(MEDIA_URL);
         checkMediaNotificationStates(tab, true /* playing */);
 
         info("- close tab -");
         closeAllTabs();
     }
 
     private void testCloseTab() {
         info("- load URL -");
         final String MEDIA_URL = getAbsoluteUrl(mStringHelper.ROBOCOP_MEDIA_PLAYBACK_LOOP_URL);
         loadUrlAndWait(MEDIA_URL);
 
+        info("- wait until media starts playing -");
+        final Tab tab = Tabs.getInstance().getSelectedTab();
+        waitUntilTabMediaStarted(tab);
+
         info("- check whether audio starts playing -");
         checkIfMediaPlayingSuccess(true /* playing */);
 
         info("- close audible tab -");
-        final Tab tab = Tabs.getInstance().getFirstTabForUrl(MEDIA_URL);
         Tabs.getInstance().closeTab(tab);
 
         info("- media control should disappear -");
         waitUntilNotificationUIChanged();
         checkIfMediaNotificationBeCleared();
 
         info("- close tab -");
         closeAllTabs();