[webkit-changes] [WebKit/WebKit] b300e9: [iOS] YouTube playback can unexpectedly interrupt ...

Aditya Keerthi noreply at github.com
Mon May 8 11:44:59 PDT 2023


  Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: b300e9f2c444288175f0af13b59562609b86c24e
      https://github.com/WebKit/WebKit/commit/b300e9f2c444288175f0af13b59562609b86c24e
  Author: Aditya Keerthi <akeerthi at apple.com>
  Date:   2023-05-08 (Mon, 08 May 2023)

  Changed paths:
    A LayoutTests/media/audio-play-with-video-element-interrupted-expected.txt
    A LayoutTests/media/audio-play-with-video-element-interrupted.html
    M Source/WebCore/Modules/audiosession/DOMAudioSession.cpp
    M Source/WebCore/Modules/audiosession/DOMAudioSession.h
    M Source/WebCore/platform/audio/AudioSession.cpp
    M Source/WebCore/platform/audio/AudioSession.h
    M Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.cpp
    M Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.h
    M Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.messages.in
    M Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.cpp
    M Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.h
    M Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.cpp
    M Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.h
    M Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.messages.in

  Log Message:
  -----------
  [iOS] YouTube playback can unexpectedly interrupt other apps playing audio
https://bugs.webkit.org/show_bug.cgi?id=256168
rdar://108741963

Reviewed by Jean-Yves Avenard.

Consider the following sequence of events:

1. Begin playback of a video on YouTube.
2. Open another app like Music, and play some audio while the video is playing.
3. Play the YouTube video again, as it will be paused following (2).
4. Play the audio in Music again, as it will be paused following (3).

After (4), the YouTube video does not get paused, and ends up interrupting
the content in Music. Instead, the same behavior as (2) should occur, where
the video gets paused, and the audio from Music is allowed to play uninterrupted.

The issue arises from the existing implemention of audio playback using the
GPU process. With the GPU process, there is now an `AudioSession` in both the
Web and GPU processes. After (2), the system dispatches an
`AVAudioSessionInterruptionNotification` notification, observed in the GPU
process, and used to pause playback. The interruption state is stored on the
`AudioSession` in the GPU process, and is sent to the `AudioSession` in the Web
process (`RemoteAudioSession`). Consequently, the video playback is correctly
paused following (2).

After (3), the video is resumed in the Web process, and the `RemoteAudioSession`
is marked as uninterrupted. However, the `AudioSession` is the GPU process is
not informed that the audio interruption has ended. Consequently, when the
notification is dispatched again after (4), it is ignored, as the GPU process
believes the audio session is already interrupted. This results in a failure
to correctly interrupt the audio session, and media playback in WebKit ends
up interrupting the session in another app.

To fix, ensure the GPU process is notified when interruption ends as a result
of change in the Web process.

* LayoutTests/media/audio-play-with-video-element-interrupted-expected.txt: Added.
* LayoutTests/media/audio-play-with-video-element-interrupted.html: Added.

Added a layout test to exercise the issue. Without this fix, the test times out.

* Source/WebCore/Modules/audiosession/DOMAudioSession.cpp:
(WebCore::DOMAudioSession::audioSessionActiveStateChanged):
(WebCore::DOMAudioSession::activeStateChanged): Deleted.
* Source/WebCore/Modules/audiosession/DOMAudioSession.h:
* Source/WebCore/platform/audio/AudioSession.cpp:
(WebCore::AudioSession::activeStateChanged):
* Source/WebCore/platform/audio/AudioSession.h:

Rename an `InterruptionObserver` method that has the same name as an
`AudioSession` method, so that `RemoteAudioSession` (a derived class of
`AudioSession`) can also be an `InterruptionObserver`.

* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.cpp:
(WebKit::RemoteAudioSessionProxy::beginInterruption):
(WebKit::RemoteAudioSessionProxy::endInterruption):
(WebKit::RemoteAudioSessionProxy::beginInterruptionRemote):

Call into `RemoteAudioSessionProxyManager`, which is the actual
`InterruptionObserver`.

(WebKit::RemoteAudioSessionProxy::endInterruptionRemote):

Ditto.

* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.h:
* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxy.messages.in:

Add new IPC messages to begin/end interruptions from the Web process.

* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.cpp:
(WebKit::RemoteAudioSessionProxyManager::beginInterruptionRemote):

Temporarily remove `this` as an `InterruptionObserver` to avoid sending a
spurious interruption message to the Web process, since this interruption
was triggered by the Web process.

(WebKit::RemoteAudioSessionProxyManager::endInterruptionRemote):

Ditto.

* Source/WebKit/GPUProcess/media/RemoteAudioSessionProxyManager.h:
* Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.cpp:
(WebKit::RemoteAudioSession::RemoteAudioSession):
(WebKit::RemoteAudioSession::~RemoteAudioSession):
(WebKit::RemoteAudioSession::beginInterruptionRemote):

Temporarily remove `this` as an `InterruptionObserver` to avoid sending a
spurious interruption message to the GPU process, since this interruption
was triggered by the GPU process.

(WebKit::RemoteAudioSession::endInterruptionRemote):

Ditto.

(WebKit::RemoteAudioSession::beginAudioSessionInterruption):

Send IPC to the GPU process to reflect the Web process state.

(WebKit::RemoteAudioSession::endAudioSessionInterruption):
* Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.h:

Make `RemoteAudioSession` an `InterruptionObserver` so that it can send IPC to
the GPU process when the Web process state is changed.

* Source/WebKit/WebProcess/GPU/media/RemoteAudioSession.messages.in:

Rename the IPC method to avoid conflicting the method on the `AudioSession` base
class that drives interruptions. This change is necessary to avoid sending a
spurious IPC to the GPU process when the interrupted state is changed in the Web
process.

Canonical link: https://commits.webkit.org/263810@main




More information about the webkit-changes mailing list