Title: [258263] trunk/Source
Revision
258263
Author
[email protected]
Date
2020-03-11 08:46:53 -0700 (Wed, 11 Mar 2020)

Log Message

Move AudioSession interruption listener code to AudioSession
https://bugs.webkit.org/show_bug.cgi?id=208714

Reviewed by Jer Noble.

Source/WebCore:

Move AudioSession interruption detection code from MediaSessionManagerIOS helper to AudioSessionIOS.
Add interruption observer capabilities to AudioSession and make MediaSessionManagerIOS an observer of it.
Manually tested.

* platform/audio/AudioSession.cpp:
(WebCore::AudioSession::addInterruptionObserver):
(WebCore::AudioSession::removeInterruptionObserver):
(WebCore::AudioSession::beginInterruption):
(WebCore::AudioSession::endInterruption):
* platform/audio/AudioSession.h:
* platform/audio/ios/AudioSessionIOS.mm:
(-[WebInterruptionObserverHelper initWithCallback:]):
(-[WebInterruptionObserverHelper dealloc]):
(-[WebInterruptionObserverHelper clearCallback]):
(-[WebInterruptionObserverHelper interruption:]):
(WebCore::AudioSessionPrivate::AudioSessionPrivate):
(WebCore::AudioSessionPrivate::~AudioSessionPrivate):
(WebCore::AudioSession::addInterruptionObserver):
(WebCore::AudioSession::removeInterruptionObserver):
(WebCore::AudioSession::beginInterruption):
(WebCore::AudioSession::endInterruption):
* platform/audio/ios/MediaSessionHelperIOS.h:
* platform/audio/ios/MediaSessionHelperIOS.mm:
(-[WebMediaSessionHelper initWithCallback:]):
* platform/audio/ios/MediaSessionManagerIOS.h:
* platform/audio/ios/MediaSessionManagerIOS.mm:
(WebCore::MediaSessionManageriOS::MediaSessionManageriOS):
(WebCore::MediaSessionManageriOS::~MediaSessionManageriOS):
(WebCore::MediaSessionManageriOS::providePresentingApplicationPIDIfNecessary):

Source/WebKit:

Make RemoteAudioSessionProxyManager an observer for AudioSession interruptions.
When being interrupted, notify all WebProcesses and trigger begin/end interruption mechanisms.
We only send interruption to sessions that are active in RemoteAudioSessionProxyManager.
Minor refactorting to move manager proxies from a map to a weak hash set.

* GPUProcess/GPUConnectionToWebProcess.cpp:
(WebKit::GPUConnectionToWebProcess::didClose):
(WebKit::GPUConnectionToWebProcess::audioSessionProxy):
* GPUProcess/media/RemoteAudioSessionProxy.cpp:
(WebKit::RemoteAudioSessionProxy::setCategory):
(WebKit::RemoteAudioSessionProxy::setPreferredBufferSize):
(WebKit::RemoteAudioSessionProxy::tryToSetActive):
* GPUProcess/media/RemoteAudioSessionProxyManager.cpp:
(WebKit::RemoteAudioSessionProxyManager::RemoteAudioSessionProxyManager):
(WebKit::RemoteAudioSessionProxyManager::~RemoteAudioSessionProxyManager):
(WebKit::RemoteAudioSessionProxyManager::addProxy):
(WebKit::RemoteAudioSessionProxyManager::removeProxy):
(WebKit::RemoteAudioSessionProxyManager::setCategoryForProcess):
(WebKit::RemoteAudioSessionProxyManager::setPreferredBufferSizeForProcess):
(WebKit::RemoteAudioSessionProxyManager::tryToSetActiveForProcess):
(WebKit::RemoteAudioSessionProxyManager::beginAudioSessionInterruption):
(WebKit::RemoteAudioSessionProxyManager::endAudioSessionInterruption):
* GPUProcess/media/RemoteAudioSessionProxyManager.h:
* GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp:
* GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h:
* WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp:
* WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h:
* WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (258262 => 258263)


--- trunk/Source/WebCore/ChangeLog	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/ChangeLog	2020-03-11 15:46:53 UTC (rev 258263)
@@ -1,3 +1,40 @@
+2020-03-11  youenn fablet  <[email protected]>
+
+        Move AudioSession interruption listener code to AudioSession
+        https://bugs.webkit.org/show_bug.cgi?id=208714
+
+        Reviewed by Jer Noble.
+
+        Move AudioSession interruption detection code from MediaSessionManagerIOS helper to AudioSessionIOS.
+        Add interruption observer capabilities to AudioSession and make MediaSessionManagerIOS an observer of it.
+        Manually tested.
+
+        * platform/audio/AudioSession.cpp:
+        (WebCore::AudioSession::addInterruptionObserver):
+        (WebCore::AudioSession::removeInterruptionObserver):
+        (WebCore::AudioSession::beginInterruption):
+        (WebCore::AudioSession::endInterruption):
+        * platform/audio/AudioSession.h:
+        * platform/audio/ios/AudioSessionIOS.mm:
+        (-[WebInterruptionObserverHelper initWithCallback:]):
+        (-[WebInterruptionObserverHelper dealloc]):
+        (-[WebInterruptionObserverHelper clearCallback]):
+        (-[WebInterruptionObserverHelper interruption:]):
+        (WebCore::AudioSessionPrivate::AudioSessionPrivate):
+        (WebCore::AudioSessionPrivate::~AudioSessionPrivate):
+        (WebCore::AudioSession::addInterruptionObserver):
+        (WebCore::AudioSession::removeInterruptionObserver):
+        (WebCore::AudioSession::beginInterruption):
+        (WebCore::AudioSession::endInterruption):
+        * platform/audio/ios/MediaSessionHelperIOS.h:
+        * platform/audio/ios/MediaSessionHelperIOS.mm:
+        (-[WebMediaSessionHelper initWithCallback:]):
+        * platform/audio/ios/MediaSessionManagerIOS.h:
+        * platform/audio/ios/MediaSessionManagerIOS.mm:
+        (WebCore::MediaSessionManageriOS::MediaSessionManageriOS):
+        (WebCore::MediaSessionManageriOS::~MediaSessionManageriOS):
+        (WebCore::MediaSessionManageriOS::providePresentingApplicationPIDIfNecessary):
+
 2020-03-11  Jack Lee  <[email protected]>
 
         Crash in KeyframeEffect::getAnimatedStyle

Modified: trunk/Source/WebCore/platform/audio/AudioSession.cpp (258262 => 258263)


--- trunk/Source/WebCore/platform/audio/AudioSession.cpp	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/platform/audio/AudioSession.cpp	2020-03-11 15:46:53 UTC (rev 258263)
@@ -63,6 +63,24 @@
     return true;
 }
 
+#if !PLATFORM(IOS)
+void AudioSession::addInterruptionObserver(InterruptionObserver&)
+{
+}
+
+void AudioSession::removeInterruptionObserver(InterruptionObserver&)
+{
+}
+
+void AudioSession::beginInterruption(PlatformMediaSession::InterruptionType)
+{
+}
+
+void AudioSession::endInterruption(PlatformMediaSession::EndInterruptionFlags)
+{
+}
+#endif
+
 #if !PLATFORM(COCOA)
 class AudioSessionPrivate {
     WTF_MAKE_FAST_ALLOCATED;

Modified: trunk/Source/WebCore/platform/audio/AudioSession.h (258262 => 258263)


--- trunk/Source/WebCore/platform/audio/AudioSession.h	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/platform/audio/AudioSession.h	2020-03-11 15:46:53 UTC (rev 258263)
@@ -27,11 +27,12 @@
 
 #if USE(AUDIO_SESSION)
 
+#include "PlatformMediaSession.h"
 #include <memory>
-#include <wtf/HashSet.h>
 #include <wtf/NeverDestroyed.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/UniqueRef.h>
+#include <wtf/WeakHashSet.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
@@ -93,6 +94,19 @@
     void addMutedStateObserver(MutedStateObserver*);
     void removeMutedStateObserver(MutedStateObserver*);
 
+    class InterruptionObserver : public CanMakeWeakPtr<InterruptionObserver> {
+    public:
+        virtual ~InterruptionObserver() = default;
+
+        // FIXME: Remove use of InterruptionType and EndInterruptionFlags in this interface.
+        virtual void beginAudioSessionInterruption(PlatformMediaSession::InterruptionType) = 0;
+        virtual void endAudioSessionInterruption(PlatformMediaSession::EndInterruptionFlags) = 0;
+    };
+    void addInterruptionObserver(InterruptionObserver&);
+    void removeInterruptionObserver(InterruptionObserver&);
+    void beginInterruption(PlatformMediaSession::InterruptionType);
+    void endInterruption(PlatformMediaSession::EndInterruptionFlags);
+
     virtual bool isMuted() const;
     virtual void handleMutedStateChange();
 
@@ -106,6 +120,9 @@
 
     std::unique_ptr<AudioSessionPrivate> m_private;
     HashSet<MutedStateObserver*> m_observers;
+#if PLATFORM(IOS)
+    WeakHashSet<InterruptionObserver> m_interruptionObservers;
+#endif
     bool m_active { false }; // Used only for testing.
 };
 

Modified: trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm (258262 => 258263)


--- trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/platform/audio/ios/AudioSessionIOS.mm	2020-03-11 15:46:53 UTC (rev 258263)
@@ -32,11 +32,71 @@
 #import <AVFoundation/AVAudioSession.h>
 #import <objc/runtime.h>
 #import <pal/spi/cocoa/AVFoundationSPI.h>
+#import <wtf/BlockObjCExceptions.h>
 #import <wtf/OSObjectPtr.h>
 #import <wtf/RetainPtr.h>
 
 #import <pal/cocoa/AVFoundationSoftLink.h>
 
+@interface WebInterruptionObserverHelper : NSObject {
+    WebCore::AudioSession* _callback;
+}
+
+- (id)initWithCallback:(WebCore::AudioSession*)callback;
+- (void)clearCallback;
+- (void)interruption:(NSNotification *)notification;
+@end
+
+@implementation WebInterruptionObserverHelper
+
+- (id)initWithCallback:(WebCore::AudioSession*)callback
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _callback = callback;
+
+    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+    [center addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:[PAL::getAVAudioSessionClass() sharedInstance]];
+
+    return self;
+}
+
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    [super dealloc];
+}
+
+- (void)clearCallback
+{
+    _callback = nil;
+}
+
+- (void)interruption:(NSNotification *)notification
+{
+    if (!_callback)
+        return;
+
+    NSUInteger type = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
+    WebCore::PlatformMediaSession::EndInterruptionFlags flags = WebCore::PlatformMediaSession::NoFlags;
+
+    if (type == AVAudioSessionInterruptionTypeEnded && [[[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey] unsignedIntegerValue] == AVAudioSessionInterruptionOptionShouldResume)
+        flags = WebCore::PlatformMediaSession::MayResumePlaying;
+
+    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), type, flags]() mutable {
+        auto* callback = protectedSelf->_callback;
+        if (!callback)
+            return;
+
+        if (type == AVAudioSessionInterruptionTypeBegan)
+            callback->beginInterruption(WebCore::PlatformMediaSession::SystemInterruption);
+        else
+            callback->endInterruption(flags);
+    });
+}
+@end
+
 namespace WebCore {
 
 #if !LOG_DISABLED
@@ -61,16 +121,27 @@
 class AudioSessionPrivate {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    AudioSessionPrivate(AudioSession*);
+    explicit AudioSessionPrivate(AudioSession*);
+    ~AudioSessionPrivate();
+
     AudioSession::CategoryType m_categoryOverride;
     OSObjectPtr<dispatch_queue_t> m_dispatchQueue;
+    RetainPtr<WebInterruptionObserverHelper> m_interruptionObserverHelper;
 };
 
-AudioSessionPrivate::AudioSessionPrivate(AudioSession*)
+AudioSessionPrivate::AudioSessionPrivate(AudioSession* session)
     : m_categoryOverride(AudioSession::None)
 {
+    BEGIN_BLOCK_OBJC_EXCEPTIONS
+    m_interruptionObserverHelper = adoptNS([[WebInterruptionObserverHelper alloc] initWithCallback:session]);
+    END_BLOCK_OBJC_EXCEPTIONS
 }
 
+AudioSessionPrivate::~AudioSessionPrivate()
+{
+    [m_interruptionObserverHelper clearCallback];
+}
+
 AudioSession::AudioSession()
     : m_private(makeUnique<AudioSessionPrivate>(this))
 {
@@ -252,6 +323,28 @@
 {
 }
 
+void AudioSession::addInterruptionObserver(InterruptionObserver& observer)
+{
+    m_interruptionObservers.add(observer);
 }
 
+void AudioSession::removeInterruptionObserver(InterruptionObserver& observer)
+{
+    m_interruptionObservers.remove(observer);
+}
+
+void AudioSession::beginInterruption(PlatformMediaSession::InterruptionType type)
+{
+    for (auto& observer : m_interruptionObservers)
+        observer.beginAudioSessionInterruption(type);
+}
+
+void AudioSession::endInterruption(PlatformMediaSession::EndInterruptionFlags flags)
+{
+    for (auto& observer : m_interruptionObservers)
+        observer.endAudioSessionInterruption(flags);
+}
+
+}
+
 #endif // USE(AUDIO_SESSION) && PLATFORM(IOS_FAMILY)

Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.h (258262 => 258263)


--- trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.h	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.h	2020-03-11 15:46:53 UTC (rev 258263)
@@ -37,10 +37,6 @@
 public:
     virtual ~MediaSessionHelperClient() = default;
 
-    enum class InterruptionType : bool { Begin, End };
-    enum class ShouldResume : bool { No, Yes };
-    virtual void receivedInterruption(InterruptionType, ShouldResume) = 0;
-
     enum class SuspendedUnderLock : bool { No, Yes };
     virtual void applicationWillEnterForeground(SuspendedUnderLock) = 0;
     virtual void applicationDidEnterBackground(SuspendedUnderLock) = 0;

Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm (258262 => 258263)


--- trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionHelperIOS.mm	2020-03-11 15:46:53 UTC (rev 258263)
@@ -79,7 +79,6 @@
 - (id)initWithCallback:(MediaSessionHelperiOS*)callback;
 
 - (void)clearCallback;
-- (void)interruption:(NSNotification *)notification;
 - (void)applicationWillEnterForeground:(NSNotification *)notification;
 - (void)applicationWillResignActive:(NSNotification *)notification;
 - (void)applicationDidEnterBackground:(NSNotification *)notification;
@@ -98,7 +97,6 @@
     ~MediaSessionHelperiOS();
 
     void externalOutputDeviceAvailableDidChange();
-    void receivedInterruption(MediaSessionHelperClient::InterruptionType, MediaSessionHelperClient::ShouldResume);
     void applicationWillEnterForeground(MediaSessionHelperClient::SuspendedUnderLock);
     void applicationDidEnterBackground(MediaSessionHelperClient::SuspendedUnderLock);
     void applicationWillBecomeInactive();
@@ -112,10 +110,8 @@
 
 private:
     using HasAvailableTargets = MediaSessionHelperClient::HasAvailableTargets;
-    using InterruptionType = MediaSessionHelperClient::InterruptionType;
     using PlayingToAutomotiveHeadUnit = MediaSessionHelperClient::PlayingToAutomotiveHeadUnit;
     using ShouldPause = MediaSessionHelperClient::ShouldPause;
-    using ShouldResume = MediaSessionHelperClient::ShouldResume;
     using SupportsAirPlayVideo = MediaSessionHelperClient::SupportsAirPlayVideo;
     using SuspendedUnderLock = MediaSessionHelperClient::SuspendedUnderLock;
 
@@ -278,12 +274,6 @@
 }
 #endif
 
-void MediaSessionHelperiOS::receivedInterruption(MediaSessionHelperClient::InterruptionType type, MediaSessionHelperClient::ShouldResume shouldResume)
-{
-    for (auto& client : m_clients)
-        client.receivedInterruption(type, shouldResume);
-}
-
 void MediaSessionHelperiOS::applicationDidBecomeActive()
 {
     for (auto& client : m_clients)
@@ -330,8 +320,6 @@
     _callback = callback;
 
     NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
-    [center addObserver:self selector:@selector(interruption:) name:AVAudioSessionInterruptionNotification object:[PAL::getAVAudioSessionClass() sharedInstance]];
-
     [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:PAL::get_UIKit_UIApplicationWillEnterForegroundNotification() object:nil];
     [center addObserver:self selector:@selector(applicationWillEnterForeground:) name:WebUIApplicationWillEnterForegroundNotification object:nil];
     [center addObserver:self selector:@selector(applicationDidBecomeActive:) name:PAL::get_UIKit_UIApplicationDidBecomeActiveNotification() object:nil];
@@ -445,26 +433,6 @@
 }
 #endif // !PLATFORM(WATCHOS)
 
-- (void)interruption:(NSNotification *)notification
-{
-    using InterruptionType = MediaSessionHelperClient::InterruptionType;
-    using ShouldResume = MediaSessionHelperClient::ShouldResume;
-
-    NSUInteger type = [[[notification userInfo] objectForKey:AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
-    InterruptionType interruptionType = (type == AVAudioSessionInterruptionTypeEnded ? InterruptionType::End : InterruptionType::Begin);
-    ShouldResume shouldResume = ShouldResume::No;
-
-    LOG(Media, "-[WebMediaSessionHelper interruption] - type = %i", (int)type);
-
-    if (interruptionType == InterruptionType::End && [[[notification userInfo] objectForKey:AVAudioSessionInterruptionOptionKey] unsignedIntegerValue] == AVAudioSessionInterruptionOptionShouldResume)
-        shouldResume = ShouldResume::Yes;
-
-    callOnWebThreadOrDispatchAsyncOnMainThread([protectedSelf = retainPtr(self), interruptionType, shouldResume]() mutable {
-        if (auto* callback = protectedSelf->_callback)
-            callback->receivedInterruption(interruptionType, shouldResume);
-    });
-}
-
 - (void)applicationWillEnterForeground:(NSNotification *)notification
 {
     using SuspendedUnderLock = MediaSessionHelperClient::SuspendedUnderLock;

Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h (258262 => 258263)


--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h	2020-03-11 15:46:53 UTC (rev 258263)
@@ -27,6 +27,7 @@
 
 #if PLATFORM(IOS_FAMILY)
 
+#include "AudioSession.h"
 #include "MediaSessionHelperIOS.h"
 #include "MediaSessionManagerCocoa.h"
 #include <wtf/RetainPtr.h>
@@ -44,7 +45,8 @@
 
 class MediaSessionManageriOS
     : public MediaSessionManagerCocoa
-    , public MediaSessionHelperClient {
+    , public MediaSessionHelperClient
+    , public AudioSession::InterruptionObserver {
 public:
     virtual ~MediaSessionManageriOS();
 
@@ -51,6 +53,9 @@
     bool hasWirelessTargetsAvailable() override;
     static WEBCORE_EXPORT void providePresentingApplicationPID();
 
+    using WeakValueType = MediaSessionHelperClient::WeakValueType;
+    using MediaSessionHelperClient::weakPtrFactory;
+
 private:
     friend class PlatformMediaSessionManager;
 
@@ -62,8 +67,11 @@
     void providePresentingApplicationPIDIfNecessary() final;
     void sessionWillEndPlayback(PlatformMediaSession&, DelayCallingUpdateNowPlaying) final;
 
+    // AudioSession::InterruptionObserver
+    void beginAudioSessionInterruption(PlatformMediaSession::InterruptionType type) final { beginInterruption(type); }
+    void endAudioSessionInterruption(PlatformMediaSession::EndInterruptionFlags flags) final { endInterruption(flags); }
+
     // MediaSessionHelperClient
-    void receivedInterruption(InterruptionType, ShouldResume) final;
     void applicationWillEnterForeground(SuspendedUnderLock) final;
     void applicationDidEnterBackground(SuspendedUnderLock) final;
     void applicationWillBecomeInactive() final;

Modified: trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm (258262 => 258263)


--- trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm	2020-03-11 15:46:53 UTC (rev 258263)
@@ -51,6 +51,7 @@
 MediaSessionManageriOS::MediaSessionManageriOS()
     : MediaSessionManagerCocoa()
 {
+    AudioSession::sharedSession().addInterruptionObserver(*this);
 }
 
 MediaSessionManageriOS::~MediaSessionManageriOS()
@@ -58,6 +59,7 @@
     if (m_isMonitoringWirelessRoutes)
         MediaSessionHelper::sharedHelper().stopMonitoringWirelessRoutes();
     MediaSessionHelper::sharedHelper().removeClient(*this);
+    AudioSession::sharedSession().removeInterruptionObserver(*this);
 }
 
 void MediaSessionManageriOS::resetRestrictions()
@@ -166,19 +168,6 @@
     nowPlayingSession->setPlaybackTarget(WTFMove(playbackTarget));
 }
 
-void MediaSessionManageriOS::receivedInterruption(InterruptionType type, ShouldResume shouldResume)
-{
-    if (willIgnoreSystemInterruptions())
-        return;
-
-    auto flags = shouldResume == ShouldResume::Yes ? PlatformMediaSession::MayResumePlaying : PlatformMediaSession::NoFlags;
-
-    if (type == InterruptionType::Begin)
-        beginInterruption(PlatformMediaSession::SystemInterruption);
-    else
-        endInterruption(flags);
-}
-
 void MediaSessionManageriOS::applicationWillEnterForeground(SuspendedUnderLock isSuspendedUnderLock)
 {
     if (willIgnoreSystemInterruptions())

Modified: trunk/Source/WebKit/ChangeLog (258262 => 258263)


--- trunk/Source/WebKit/ChangeLog	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/ChangeLog	2020-03-11 15:46:53 UTC (rev 258263)
@@ -1,3 +1,39 @@
+2020-03-11  youenn fablet  <[email protected]>
+
+        Move AudioSession interruption listener code to AudioSession
+        https://bugs.webkit.org/show_bug.cgi?id=208714
+
+        Reviewed by Jer Noble.
+
+        Make RemoteAudioSessionProxyManager an observer for AudioSession interruptions.
+        When being interrupted, notify all WebProcesses and trigger begin/end interruption mechanisms.
+        We only send interruption to sessions that are active in RemoteAudioSessionProxyManager.
+        Minor refactorting to move manager proxies from a map to a weak hash set.
+
+        * GPUProcess/GPUConnectionToWebProcess.cpp:
+        (WebKit::GPUConnectionToWebProcess::didClose):
+        (WebKit::GPUConnectionToWebProcess::audioSessionProxy):
+        * GPUProcess/media/RemoteAudioSessionProxy.cpp:
+        (WebKit::RemoteAudioSessionProxy::setCategory):
+        (WebKit::RemoteAudioSessionProxy::setPreferredBufferSize):
+        (WebKit::RemoteAudioSessionProxy::tryToSetActive):
+        * GPUProcess/media/RemoteAudioSessionProxyManager.cpp:
+        (WebKit::RemoteAudioSessionProxyManager::RemoteAudioSessionProxyManager):
+        (WebKit::RemoteAudioSessionProxyManager::~RemoteAudioSessionProxyManager):
+        (WebKit::RemoteAudioSessionProxyManager::addProxy):
+        (WebKit::RemoteAudioSessionProxyManager::removeProxy):
+        (WebKit::RemoteAudioSessionProxyManager::setCategoryForProcess):
+        (WebKit::RemoteAudioSessionProxyManager::setPreferredBufferSizeForProcess):
+        (WebKit::RemoteAudioSessionProxyManager::tryToSetActiveForProcess):
+        (WebKit::RemoteAudioSessionProxyManager::beginAudioSessionInterruption):
+        (WebKit::RemoteAudioSessionProxyManager::endAudioSessionInterruption):
+        * GPUProcess/media/RemoteAudioSessionProxyManager.h:
+        * GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp:
+        * GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h:
+        * WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp:
+        * WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h:
+        * WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in:
+
 2020-03-10  Don Olmstead  <[email protected]>
 
         [GPU Process] Work towards compiling out on non-Cocoa ports

Modified: trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp (258262 => 258263)


--- trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/GPUProcess/GPUConnectionToWebProcess.cpp	2020-03-11 15:46:53 UTC (rev 258263)
@@ -156,7 +156,7 @@
 {
 #if USE(AUDIO_SESSION)
     if (m_audioSessionProxy) {
-        gpuProcess().audioSessionManager().removeProxy(webProcessIdentifier());
+        gpuProcess().audioSessionManager().removeProxy(*m_audioSessionProxy);
         m_audioSessionProxy = nullptr;
     }
 #endif
@@ -263,7 +263,7 @@
 {
     if (!m_audioSessionProxy) {
         m_audioSessionProxy = RemoteAudioSessionProxy::create(*this).moveToUniquePtr();
-        gpuProcess().audioSessionManager().addProxy(makeWeakPtr(m_audioSessionProxy.get()));
+        gpuProcess().audioSessionManager().addProxy(*m_audioSessionProxy);
     }
     return *m_audioSessionProxy;
 }

Modified: trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.cpp (258262 => 258263)


--- trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.cpp	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.cpp	2020-03-11 15:46:53 UTC (rev 258263)
@@ -75,18 +75,18 @@
 {
     m_category = category;
     m_routeSharingPolicy = policy;
-    audioSessionManager().setCategoryForProcess(m_gpuConnection.webProcessIdentifier(), category, policy);
+    audioSessionManager().setCategoryForProcess(*this, category, policy);
 }
 
 void RemoteAudioSessionProxy::setPreferredBufferSize(uint64_t size)
 {
     m_preferredBufferSize = size;
-    audioSessionManager().setPreferredBufferSizeForProcess(m_gpuConnection.webProcessIdentifier(), size);
+    audioSessionManager().setPreferredBufferSizeForProcess(*this, size);
 }
 
 void RemoteAudioSessionProxy::tryToSetActive(bool active, SetActiveCompletion&& completion)
 {
-    m_active = audioSessionManager().tryToSetActiveForProcess(m_gpuConnection.webProcessIdentifier(), active);
+    m_active = audioSessionManager().tryToSetActiveForProcess(*this, active);
     completion(m_active);
 }
 

Modified: trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.cpp (258262 => 258263)


--- trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.cpp	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.cpp	2020-03-11 15:46:53 UTC (rev 258263)
@@ -28,6 +28,8 @@
 
 #if ENABLE(GPU_PROCESS) && USE(AUDIO_SESSION)
 
+#include "GPUProcess.h"
+#include "GPUProcessConnectionMessages.h"
 #include "RemoteAudioSessionProxy.h"
 #include <WebCore/AudioSession.h>
 #include <wtf/HashCountedSet.h>
@@ -44,46 +46,36 @@
 RemoteAudioSessionProxyManager::RemoteAudioSessionProxyManager()
     : m_session(AudioSession::create())
 {
+    m_session->addInterruptionObserver(*this);
 }
 
-RemoteAudioSessionProxyManager::~RemoteAudioSessionProxyManager() = default;
-
-void RemoteAudioSessionProxyManager::addProxy(WeakPtr<RemoteAudioSessionProxy>&& proxy)
+RemoteAudioSessionProxyManager::~RemoteAudioSessionProxyManager()
 {
-    auto id = proxy->processIdentifier();
-    ASSERT(!m_proxies.contains(id));
-    m_proxies.set(id, WTFMove(proxy));
+    m_session->removeInterruptionObserver(*this);
 }
 
-void RemoteAudioSessionProxyManager::removeProxy(const ProcessIdentifier& id)
+void RemoteAudioSessionProxyManager::addProxy(RemoteAudioSessionProxy& proxy)
 {
-    ASSERT(m_proxies.contains(id));
-    m_proxies.remove(id);
+    ASSERT(!m_proxies.contains(proxy));
+    m_proxies.add(proxy);
 }
 
-RemoteAudioSessionProxy* RemoteAudioSessionProxyManager::getProxy(const ProcessIdentifier& id)
+void RemoteAudioSessionProxyManager::removeProxy(RemoteAudioSessionProxy& proxy)
 {
-    auto results = m_proxies.find(id);
-    if (results != m_proxies.end())
-        return results->value.get();
-    return nullptr;
+    ASSERT(m_proxies.contains(proxy));
+    m_proxies.remove(proxy);
 }
 
-void RemoteAudioSessionProxyManager::setCategoryForProcess(const ProcessIdentifier& id, AudioSession::CategoryType category, RouteSharingPolicy policy)
+void RemoteAudioSessionProxyManager::setCategoryForProcess(RemoteAudioSessionProxy& proxy, AudioSession::CategoryType category, RouteSharingPolicy policy)
 {
-    ASSERT(m_proxies.contains(id));
-    auto proxy = getProxy(id);
-    if (!proxy)
+    if (proxy.category() == category && proxy.routeSharingPolicy() == policy)
         return;
 
-    if (proxy->category() == category && proxy->routeSharingPolicy() == policy)
-        return;
-
     HashCountedSet<AudioSession::CategoryType, WTF::IntHash<AudioSession::CategoryType>, WTF::StrongEnumHashTraits<AudioSession::CategoryType>> categoryCounts;
     HashCountedSet<RouteSharingPolicy, WTF::IntHash<RouteSharingPolicy>, WTF::StrongEnumHashTraits<RouteSharingPolicy>> policyCounts;
-    for (auto& otherProxy : m_proxies.values()) {
-        categoryCounts.add(otherProxy->category());
-        policyCounts.add(otherProxy->routeSharingPolicy());
+    for (auto& otherProxy : m_proxies) {
+        categoryCounts.add(otherProxy.category());
+        policyCounts.add(otherProxy.routeSharingPolicy());
     }
 
     if (categoryCounts.contains(AudioSession::PlayAndRecord))
@@ -113,30 +105,23 @@
     m_session->setCategory(category, policy);
 }
 
-void RemoteAudioSessionProxyManager::setPreferredBufferSizeForProcess(const ProcessIdentifier& id, size_t preferredBufferSize)
+void RemoteAudioSessionProxyManager::setPreferredBufferSizeForProcess(RemoteAudioSessionProxy& proxy, size_t preferredBufferSize)
 {
-    for (auto& otherProxy : m_proxies.values()) {
-        if (!otherProxy)
-            continue;
-        if (otherProxy->preferredBufferSize() < preferredBufferSize)
-            preferredBufferSize = otherProxy->preferredBufferSize();
+    for (auto& otherProxy : m_proxies) {
+        if (otherProxy.preferredBufferSize() < preferredBufferSize)
+            preferredBufferSize = otherProxy.preferredBufferSize();
     }
 
     m_session->setPreferredBufferSize(preferredBufferSize);
 }
 
-bool RemoteAudioSessionProxyManager::tryToSetActiveForProcess(const ProcessIdentifier& id, bool active)
+bool RemoteAudioSessionProxyManager::tryToSetActiveForProcess(RemoteAudioSessionProxy& proxy, bool active)
 {
-    ASSERT(m_proxies.contains(id));
-    auto proxy = getProxy(id);
-    if (!proxy)
-        return false;
+    ASSERT(m_proxies.contains(proxy));
 
     size_t activeProxyCount { 0 };
-    for (auto& otherProxy : m_proxies.values()) {
-        if (!otherProxy)
-            continue;
-        if (otherProxy->isActive())
+    for (auto& otherProxy : m_proxies) {
+        if (otherProxy.isActive())
             ++activeProxyCount;
     }
 
@@ -162,23 +147,21 @@
     // If this proxy is Ambient, and the session is already active, this
     // proxy will mix with the active proxies. No-op, and return activation
     // was sucessful.
-    if (categoryCanMixWithOthers(proxy->category()))
+    if (categoryCanMixWithOthers(proxy.category()))
         return true;
 
 #if PLATFORM(IOS_FAMILY)
     // Otherwise, this proxy wants to become active, but there are other
     // proxies who are already active. Walk over the proxies, and interrupt
-    // those proxies whose cateogries indicate they cannot mix with others.
-    for (auto& otherProxy : m_proxies.values()) {
-        if (!otherProxy)
+    // those proxies whose categories indicate they cannot mix with others.
+    for (auto& otherProxy : m_proxies) {
+        if (!otherProxy.isActive())
             continue;
-        if (!otherProxy->isActive())
-            continue;
 
-        if (categoryCanMixWithOthers(otherProxy->category()))
+        if (categoryCanMixWithOthers(otherProxy.category()))
             continue;
 
-        otherProxy->beginInterruption(PlatformMediaSession::InterruptionType::SystemInterruption);
+        otherProxy.beginInterruption(PlatformMediaSession::InterruptionType::SystemInterruption);
     }
 #endif
 
@@ -186,6 +169,22 @@
 
 }
 
+void RemoteAudioSessionProxyManager::beginAudioSessionInterruption(PlatformMediaSession::InterruptionType type)
+{
+    for (auto& proxy : m_proxies) {
+        if (proxy.isActive())
+            proxy.beginInterruption(type);
+    }
 }
 
+void RemoteAudioSessionProxyManager::endAudioSessionInterruption(PlatformMediaSession::EndInterruptionFlags flags)
+{
+    for (auto& proxy : m_proxies) {
+        if (proxy.isActive())
+            proxy.endInterruption(flags);
+    }
+}
+
+}
+
 #endif

Modified: trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.h (258262 => 258263)


--- trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.h	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.h	2020-03-11 15:46:53 UTC (rev 258263)
@@ -29,32 +29,36 @@
 
 #include <WebCore/AudioSession.h>
 #include <WebCore/ProcessIdentifier.h>
+#include <wtf/WeakHashSet.h>
 
 namespace WebKit {
 
+class GPUProcess;
 class RemoteAudioSessionProxy;
 
 class RemoteAudioSessionProxyManager
-    : public CanMakeWeakPtr<RemoteAudioSessionProxyManager> {
+    : public WebCore::AudioSession::InterruptionObserver {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     RemoteAudioSessionProxyManager();
     ~RemoteAudioSessionProxyManager();
 
-    void addProxy(WeakPtr<RemoteAudioSessionProxy>&&);
-    void removeProxy(const WebCore::ProcessIdentifier&);
-    RemoteAudioSessionProxy* getProxy(const WebCore::ProcessIdentifier&);
+    void addProxy(RemoteAudioSessionProxy&);
+    void removeProxy(RemoteAudioSessionProxy&);
 
-    void setCategoryForProcess(const WebCore::ProcessIdentifier&, WebCore::AudioSession::CategoryType, WebCore::RouteSharingPolicy);
-    void setPreferredBufferSizeForProcess(const WebCore::ProcessIdentifier&, size_t);
+    void setCategoryForProcess(RemoteAudioSessionProxy&, WebCore::AudioSession::CategoryType, WebCore::RouteSharingPolicy);
+    void setPreferredBufferSizeForProcess(RemoteAudioSessionProxy&, size_t);
 
-    bool tryToSetActiveForProcess(const WebCore::ProcessIdentifier&, bool);
+    bool tryToSetActiveForProcess(RemoteAudioSessionProxy&, bool);
 
     const WebCore::AudioSession& session() const { return m_session; }
 
 private:
+    void beginAudioSessionInterruption(WebCore::PlatformMediaSession::InterruptionType) final;
+    void endAudioSessionInterruption(WebCore::PlatformMediaSession::EndInterruptionFlags) final;
+
     UniqueRef<WebCore::AudioSession> m_session;
-    HashMap<WebCore::ProcessIdentifier, WeakPtr<RemoteAudioSessionProxy>> m_proxies;
+    WeakHashSet<RemoteAudioSessionProxy> m_proxies;
 };
 
 }

Modified: trunk/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp (258262 => 258263)


--- trunk/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.cpp	2020-03-11 15:46:53 UTC (rev 258263)
@@ -74,11 +74,6 @@
     MediaSessionHelper::sharedHelper().providePresentingApplicationPID(pid);
 }
 
-void RemoteMediaSessionHelperProxy::receivedInterruption(InterruptionType type, ShouldResume shouldResume)
-{
-    m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ReceivedInterruption(type, shouldResume), { });
-}
-
 void RemoteMediaSessionHelperProxy::applicationWillEnterForeground(SuspendedUnderLock suspendedUnderLock)
 {
     m_gpuConnection.connection().send(Messages::RemoteMediaSessionHelper::ApplicationWillEnterForeground(suspendedUnderLock), { });

Modified: trunk/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h (258262 => 258263)


--- trunk/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/GPUProcess/media/ios/RemoteMediaSessionHelperProxy.h	2020-03-11 15:46:53 UTC (rev 258263)
@@ -52,7 +52,6 @@
     void providePresentingApplicationPID(int);
 
     // MediaSessionHelperClient
-    void receivedInterruption(InterruptionType, ShouldResume) final;
     void applicationWillEnterForeground(SuspendedUnderLock) final;
     void applicationDidEnterBackground(SuspendedUnderLock) final;
     void applicationWillBecomeInactive() final;

Modified: trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp (258262 => 258263)


--- trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.cpp	2020-03-11 15:46:53 UTC (rev 258263)
@@ -76,12 +76,6 @@
     connection().send(Messages::RemoteMediaSessionHelperProxy::ProvidePresentingApplicationPID(pid), { });
 }
 
-void RemoteMediaSessionHelper::receivedInterruption(InterruptionType type, ShouldResume shouldResume)
-{
-    for (auto& client : m_clients)
-        client.receivedInterruption(type, shouldResume);
-}
-
 void RemoteMediaSessionHelper::applicationWillEnterForeground(SuspendedUnderLock suspendedUnderLock)
 {
     for (auto& client : m_clients)

Modified: trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h (258262 => 258263)


--- trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.h	2020-03-11 15:46:53 UTC (rev 258263)
@@ -44,10 +44,8 @@
     IPC::Connection& connection();
 
     using HasAvailableTargets = WebCore::MediaSessionHelperClient::HasAvailableTargets;
-    using InterruptionType = WebCore::MediaSessionHelperClient::InterruptionType;
     using PlayingToAutomotiveHeadUnit = WebCore::MediaSessionHelperClient::PlayingToAutomotiveHeadUnit;
     using ShouldPause = WebCore::MediaSessionHelperClient::ShouldPause;
-    using ShouldResume = WebCore::MediaSessionHelperClient::ShouldResume;
     using SupportsAirPlayVideo = WebCore::MediaSessionHelperClient::SupportsAirPlayVideo;
     using SuspendedUnderLock = WebCore::MediaSessionHelperClient::SuspendedUnderLock;
 
@@ -61,7 +59,6 @@
     void providePresentingApplicationPID(int) final;
 
     // Messages
-    void receivedInterruption(InterruptionType, ShouldResume);
     void applicationWillEnterForeground(SuspendedUnderLock);
     void applicationDidEnterBackground(SuspendedUnderLock);
     void applicationWillBecomeInactive();

Modified: trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in (258262 => 258263)


--- trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in	2020-03-11 14:50:55 UTC (rev 258262)
+++ trunk/Source/WebKit/WebProcess/GPU/media/ios/RemoteMediaSessionHelper.messages.in	2020-03-11 15:46:53 UTC (rev 258263)
@@ -24,7 +24,6 @@
 #if ENABLE(GPU_PROCESS) && PLATFORM(IOS_FAMILY)
 
 messages -> RemoteMediaSessionHelper NotRefCounted {
-    ReceivedInterruption(enum:bool WebKit::RemoteMediaSessionHelper::InterruptionType type, enum:bool WebKit::RemoteMediaSessionHelper::ShouldResume shouldResume)
     ApplicationWillEnterForeground(enum:bool WebKit::RemoteMediaSessionHelper::SuspendedUnderLock suspendedUnderLock)
     ApplicationDidEnterBackground(enum:bool WebKit::RemoteMediaSessionHelper::SuspendedUnderLock suspendedUnderLock)
     ApplicationWillBecomeInactive()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to