WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
217606
Web Audio broken on iOS 14 after switching app
https://bugs.webkit.org/show_bug.cgi?id=217606
Summary
Web Audio broken on iOS 14 after switching app
Ashley Gullen
Reported
2020-10-12 06:15:41 PDT
Demo URL:
https://downloads.scirra.com/labs/ios14audio/standard/index.html
Steps to reproduce: 1. Press button and verify a sound can be heard 2. Go to the home screen 3. Switch back to Safari so the page is showing again 4. Press the button again Observed result: Audio no longer plays. Expected result: Audio to continue playing. It looks like all our JavaScript code is running as expected, and the AudioContext state is still "running" after switching back to the app, but no audio playback happens. So it appears to be a regression in iOS 14. This affects all web content made in Construct 3 (www.construct.net).
Attachments
Patch
(19.58 KB, patch)
2020-10-26 14:43 PDT
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(6.91 KB, patch)
2020-10-26 16:34 PDT
,
Chris Dumez
darin
: review+
Details
Formatted Diff
Diff
Patch
(9.39 KB, patch)
2020-10-28 11:51 PDT
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(9.40 KB, patch)
2020-10-28 11:57 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(10.60 KB, patch)
2020-10-28 13:27 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(12.24 KB, patch)
2020-10-28 15:24 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(10.60 KB, patch)
2020-10-28 16:06 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(3.86 KB, patch)
2020-10-28 17:47 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(3.87 KB, patch)
2020-10-28 18:19 PDT
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Show Obsolete
(8)
View All
Add attachment
proposed patch, testcase, etc.
Ashley Gullen
Comment 1
2020-10-12 06:17:40 PDT
Note it also works correctly in Safari 14 on macOS, and in Chrome on Android, so it looks like this only affects iOS.
Radar WebKit Bug Importer
Comment 2
2020-10-12 17:39:39 PDT
<
rdar://problem/70231769
>
Chris Dumez
Comment 3
2020-10-26 09:57:53 PDT
I see an exception showing in the console on homing out: Unhandled Promise Rejection: undefined _SetSuspended(e) { const isSuspended = e["isSuspended"]; console.log("[Construct 3] Setting audio suspended: ", isSuspended); // Upon resume: first resume the whole context if (!isSuspended && this._audioContext["resume"]) this._audioContext["resume"](); // Suspend or resume all audio instances for (const ai of this._audioInstances) ai.SetSuspended(isSuspended); // After suspend: also suspend the whole context if (isSuspended && this._audioContext["suspend"]) this._audioContext["suspend"](); // On this line. } Looks like the script is not dealing with this promise rejection.
Ashley Gullen
Comment 4
2020-10-26 10:18:03 PDT
Why would that promise reject? It didn't before, so this seems to be new.
Chris Dumez
Comment 5
2020-10-26 10:48:30 PDT
(In reply to Ashley Gullen from
comment #4
)
> Why would that promise reject? It didn't before, so this seems to be new.
I will investigate. It is possible it is new behavior since we've been working on aligning our WebAudio implementation with the W3C specification.
Chris Dumez
Comment 6
2020-10-26 10:48:53 PDT
Still reproduces on with WebKit trunk.
Chris Dumez
Comment 7
2020-10-26 10:57:22 PDT
suspend() throws because the audio context's state is "interrupted", likely because the view is not longer visible and we interrupt audio in this case. It seems wrong to reject the promise in this case. Seems like we should set the "suspendedByUser" flag and resolve the promise in this case.
Ashley Gullen
Comment 8
2020-10-26 12:12:16 PDT
This may be off topic but the spec says the only valid AudioContext states are "running", "suspended" and "closed". Since "interrupted" isn't a specified state we haven't written any code to try to handle that. Separately, this has caused us problems in the past in WKWebView, since some things (in our case showing an AdMob ad) seemed to cause the AudioContext to end up in this non-standard state, causing audio playback to fail in that case as well.
Chris Dumez
Comment 9
2020-10-26 12:16:45 PDT
(In reply to Ashley Gullen from
comment #8
)
> This may be off topic but the spec says the only valid AudioContext states > are "running", "suspended" and "closed". Since "interrupted" isn't a > specified state we haven't written any code to try to handle that. > Separately, this has caused us problems in the past in WKWebView, since some > things (in our case showing an AdMob ad) seemed to cause the AudioContext to > end up in this non-standard state, causing audio playback to fail in that > case as well.
Yes, "interrupted" is not a standard state and I agree we should stop exposing to the Web this internal implementation detail.
Chris Dumez
Comment 10
2020-10-26 14:25:16 PDT
Even after I stop rejecting the suspend() promise and get rid of the "interrupted" state, clicking the button still does not play audio sometimes (it is flaky). I am not sure why (The JS is pretty complicated) and there is no longer any exception/error in the console. When the button does not cause audio playback, I see that the AudioContext's state is "running", as expected.
Chris Dumez
Comment 11
2020-10-26 14:38:00 PDT
(In reply to Chris Dumez from
comment #10
)
> Even after I stop rejecting the suspend() promise and get rid of the > "interrupted" state, clicking the button still does not play audio sometimes > (it is flaky). I am not sure why (The JS is pretty complicated) and there is > no longer any exception/error in the console. > > When the button does not cause audio playback, I see that the AudioContext's > state is "running", as expected.
Could you point me to the code that actually plays the audio when I click the button? I tried to follow in Web Inspector but could not easily find the logic.
Chris Dumez
Comment 12
2020-10-26 14:43:47 PDT
Created
attachment 412355
[details]
Patch
Ashley Gullen
Comment 13
2020-10-26 14:54:39 PDT
If you beautify the source and search for createBufferSource, there is one in a method named Play. That is where the actual playback is done and the call to start() made.
Chris Dumez
Comment 14
2020-10-26 15:23:19 PDT
(In reply to Ashley Gullen from
comment #13
)
> If you beautify the source and search for createBufferSource, there is one > in a method named Play. That is where the actual playback is done and the > call to start() made.
Thanks, will debug further.
Chris Dumez
Comment 15
2020-10-26 16:34:38 PDT
Created
attachment 412364
[details]
Patch
Chris Dumez
Comment 16
2020-10-27 08:31:05 PDT
I landed this first patch via
Bug 218235
and am keeping this bug open because it is still very flaky. There seems to be a remaining issue where when going back to Safari, we try to resume the AudioContext and fail due to a permission error. The call to AudioOutputUnitStart() fails with an AVAudioSessionErrorCodeCannotStartPlaying error code and we still move the AudioContext's state to "running" and resolve the resume() promise. There are several issues here: 1. If the attempt to start the AudioDestination fails, we should probably reject the resume() promise and not set the state to "running". 2. Why are we getting a AVAudioSessionErrorCodeCannotStartPlaying error when trying to start the AudioDestination when going back to Safari. This is flaky so I assume we attempt to start the destination slightly before AVFoundation realizes we are allowed to play.
Chris Dumez
Comment 17
2020-10-27 15:01:12 PDT
After the fixes from
Bug 218235
&
Bug 218251
, this test page provided actually works reliably how. That said, it only works reliably because the test page keeps trying to resume the context until context.state becomes "running". As a result, I am keeping this bug open for now. We still have a race when coming back to Safari causing us to fail to resume rendering in some cases. Without the retry logic on the JS side, it would fail which is bad. I am looking into why this race is happening and if we can resolve it. If not, I guess we could implement a retry logic on WebKit side to avoid relying on the page's JS to do so.
Chris Dumez
Comment 18
2020-10-28 11:51:50 PDT
Created
attachment 412556
[details]
Patch
Chris Dumez
Comment 19
2020-10-28 11:57:55 PDT
Created
attachment 412558
[details]
Patch
Chris Dumez
Comment 20
2020-10-28 13:27:08 PDT
Created
attachment 412567
[details]
Patch
Eric Carlson
Comment 21
2020-10-28 14:28:47 PDT
Comment on
attachment 412567
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=412567&action=review
r=me once the bots are happy
> Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp:108 > + weakThis->setIsPlaying(true);
Why not call `setIsPlaying` when success is false?
Chris Dumez
Comment 22
2020-10-28 15:02:26 PDT
Comment on
attachment 412567
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=412567&action=review
>> Source/WebCore/platform/audio/cocoa/AudioDestinationCocoa.cpp:108 >> + weakThis->setIsPlaying(true); > > Why not call `setIsPlaying` when success is false?
I am maintaining pre-existing behavior here. If you try to start and starting fails, presumably there is nothing to do since you did not start playing. isPlaying should already be false? Either way, seems out of scope of this patch no? I am not changing behavior here AFAICT.
Chris Dumez
Comment 23
2020-10-28 15:24:47 PDT
Created
attachment 412577
[details]
Patch
Chris Dumez
Comment 24
2020-10-28 16:06:13 PDT
Created
attachment 412583
[details]
Patch
Chris Dumez
Comment 25
2020-10-28 17:47:10 PDT
Created
attachment 412595
[details]
Patch
Eric Carlson
Comment 26
2020-10-28 18:12:04 PDT
Comment on
attachment 412595
[details]
Patch r=me once the bots can deal with it
Chris Dumez
Comment 27
2020-10-28 18:19:51 PDT
Created
attachment 412599
[details]
Patch
EWS
Comment 28
2020-10-28 19:40:36 PDT
Committed
r269134
: <
https://trac.webkit.org/changeset/269134
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 412599
[details]
.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug