[iOS] Playback does not pause when deselecting route and locking screen.
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Sep 2015 23:53:33 +0000 (23:53 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Sep 2015 23:53:33 +0000 (23:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=148724

Reviewed by Eric Carlson.

When deselecting a route, the route change notification can be delayed for some amount
of time. If the screen is locked before the notification is fired, the PlatformMediaSessionManager
can refuse to pause the video when entering the background due to a wireless playback route
still being active.

When the media element transitions from having an active route to not having one (or vice versa),
re-run the interruption check. In order to correctly determine, when that occurs, whether
we are in an 'application background' state, cache that value to an ivar when handling
application{Will,Did}Enter{Background,Foreground}.

Because we only want to run this step during an actual transition between playing to a route ->
playing locally, cache the value of isPlayingToWirelessPlayback to another ivar, and only
inform the PlatformMediaSessionManager when that value actually changes.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged):
* platform/audio/PlatformMediaSession.cpp:
(WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTargetChanged): Set or clear m_isPlayingToWirelessPlaybackTarget.
* platform/audio/PlatformMediaSession.h:
(WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTarget): Simple getter.
* platform/audio/PlatformMediaSessionManager.cpp:
(WebCore::PlatformMediaSessionManager::applicationWillEnterBackground): Set m_isApplicationInBackground.
(WebCore::PlatformMediaSessionManager::applicationDidEnterBackground): Ditto.
(WebCore::PlatformMediaSessionManager::applicationWillEnterForeground): Clear m_isApplicationInBackground.
(WebCore::PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged): Run interruption
    if application is in background.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@189322 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/platform/audio/PlatformMediaSession.cpp
Source/WebCore/platform/audio/PlatformMediaSession.h
Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp
Source/WebCore/platform/audio/PlatformMediaSessionManager.h

index 09ba732..9a5a1ed 100644 (file)
@@ -1,3 +1,37 @@
+2015-09-03  Jer Noble  <jer.noble@apple.com>
+
+        [iOS] Playback does not pause when deselecting route and locking screen.
+        https://bugs.webkit.org/show_bug.cgi?id=148724
+
+        Reviewed by Eric Carlson.
+
+        When deselecting a route, the route change notification can be delayed for some amount
+        of time. If the screen is locked before the notification is fired, the PlatformMediaSessionManager
+        can refuse to pause the video when entering the background due to a wireless playback route
+        still being active.
+
+        When the media element transitions from having an active route to not having one (or vice versa),
+        re-run the interruption check. In order to correctly determine, when that occurs, whether
+        we are in an 'application background' state, cache that value to an ivar when handling
+        application{Will,Did}Enter{Background,Foreground}.
+
+        Because we only want to run this step during an actual transition between playing to a route ->
+        playing locally, cache the value of isPlayingToWirelessPlayback to another ivar, and only
+        inform the PlatformMediaSessionManager when that value actually changes.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged):
+        * platform/audio/PlatformMediaSession.cpp:
+        (WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTargetChanged): Set or clear m_isPlayingToWirelessPlaybackTarget.
+        * platform/audio/PlatformMediaSession.h:
+        (WebCore::PlatformMediaSession::isPlayingToWirelessPlaybackTarget): Simple getter.
+        * platform/audio/PlatformMediaSessionManager.cpp:
+        (WebCore::PlatformMediaSessionManager::applicationWillEnterBackground): Set m_isApplicationInBackground.
+        (WebCore::PlatformMediaSessionManager::applicationDidEnterBackground): Ditto.
+        (WebCore::PlatformMediaSessionManager::applicationWillEnterForeground): Clear m_isApplicationInBackground.
+        (WebCore::PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged): Run interruption
+            if application is in background.
+
 2015-09-03  Brady Eidson  <beidson@apple.com>
 
         Move SecurityOriginData from WK2 to WebCore.
index 7490619..7409a51 100644 (file)
@@ -5031,9 +5031,10 @@ void HTMLMediaElement::wirelessRoutesAvailableDidChange()
 void HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*)
 {
     LOG(Media, "HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(%p) - webkitCurrentPlaybackTargetIsWireless = %s", this, boolString(webkitCurrentPlaybackTargetIsWireless()));
-
+    ASSERT(m_player);
     configureMediaControls();
     scheduleEvent(eventNames().webkitcurrentplaybacktargetiswirelesschangedEvent);
+    m_mediaSession->isPlayingToWirelessPlaybackTargetChanged(m_player->isCurrentPlaybackTargetWireless());
     updateMediaState(UpdateMediaState::Asynchronously);
 }
 
index d980f4d..eae8273 100644 (file)
@@ -255,6 +255,15 @@ bool PlatformMediaSession::isHidden() const
     return m_client.elementIsHidden();
 }
 
+void PlatformMediaSession::isPlayingToWirelessPlaybackTargetChanged(bool isWireless)
+{
+    if (isWireless == m_isPlayingToWirelessPlaybackTarget)
+        return;
+
+    m_isPlayingToWirelessPlaybackTarget = isWireless;
+    PlatformMediaSessionManager::sharedManager().sessionIsPlayingToWirelessPlaybackTargetChanged(*this);
+}
+
 PlatformMediaSession::DisplayType PlatformMediaSession::displayType() const
 {
     return m_client.displayType();
index 820eadf..5a3cf3c 100644 (file)
@@ -125,7 +125,8 @@ public:
     bool isHidden() const;
 
     virtual bool canPlayToWirelessPlaybackTarget() const { return false; }
-    virtual bool isPlayingToWirelessPlaybackTarget() const { return false; }
+    virtual bool isPlayingToWirelessPlaybackTarget() const { return m_isPlayingToWirelessPlaybackTarget; }
+    void isPlayingToWirelessPlaybackTargetChanged(bool);
 
 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
     // MediaPlaybackTargetClient
@@ -151,6 +152,7 @@ private:
     State m_stateToRestore;
     int m_interruptionCount { 0 };
     bool m_notifyingClient;
+    bool m_isPlayingToWirelessPlaybackTarget { false };
 
     friend class PlatformMediaSessionManager;
 };
index 2256461..1a58cb5 100644 (file)
@@ -275,6 +275,12 @@ bool PlatformMediaSessionManager::sessionCanLoadMedia(const PlatformMediaSession
 void PlatformMediaSessionManager::applicationWillEnterBackground() const
 {
     LOG(Media, "PlatformMediaSessionManager::applicationWillEnterBackground");
+
+    if (m_isApplicationInBackground)
+        return;
+
+    m_isApplicationInBackground = true;
+    
     Vector<PlatformMediaSession*> sessions = m_sessions;
     for (auto* session : sessions) {
         if (m_restrictions[session->mediaType()] & BackgroundProcessPlaybackRestricted)
@@ -299,6 +305,12 @@ void PlatformMediaSessionManager::applicationDidEnterBackground(bool isSuspended
 void PlatformMediaSessionManager::applicationWillEnterForeground() const
 {
     LOG(Media, "PlatformMediaSessionManager::applicationWillEnterForeground");
+
+    if (!m_isApplicationInBackground)
+        return;
+
+    m_isApplicationInBackground = false;
+
     Vector<PlatformMediaSession*> sessions = m_sessions;
     for (auto* session : sessions) {
         if (m_restrictions[session->mediaType()] & BackgroundProcessPlaybackRestricted)
@@ -306,6 +318,15 @@ void PlatformMediaSessionManager::applicationWillEnterForeground() const
     }
 }
 
+void PlatformMediaSessionManager::sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession& session)
+{
+    if (!m_isApplicationInBackground || !(m_restrictions[session.mediaType()] & BackgroundProcessPlaybackRestricted))
+        return;
+
+    if (session.state() != PlatformMediaSession::Interrupted && session.shouldDoInterruption(PlatformMediaSession::EnteringBackground))
+        session.doInterruption();
+}
+
 #if !PLATFORM(COCOA)
 void PlatformMediaSessionManager::updateSessionState()
 {
index 59c25f6..1f7603a 100644 (file)
@@ -88,6 +88,8 @@ public:
     void setCurrentSession(PlatformMediaSession&);
     PlatformMediaSession* currentSession();
 
+    void sessionIsPlayingToWirelessPlaybackTargetChanged(PlatformMediaSession&);
+
 protected:
     friend class PlatformMediaSession;
     explicit PlatformMediaSessionManager();
@@ -126,6 +128,7 @@ private:
 #endif
 
     bool m_interrupted { false };
+    mutable bool m_isApplicationInBackground { false };
 };
 
 }