Bug 179964

Summary: Camera/microphone acquisition false positive after receiving phone call
Product: WebKit Reporter: Andrew Morris <andrew>
Component: WebRTCAssignee: Nobody <webkit-unassigned>
Status: RESOLVED DUPLICATE    
Severity: Normal CC: adam, bmccarthy, daginge, eric.carlson, jonlee, l.schlegge, webkit-bug-importer, youennf, zghalib
Priority: P2 Keywords: InRadar
Version: Safari 11   
Hardware: iPhone / iPad   
OS: iOS 11   
See Also: https://bugs.webkit.org/show_bug.cgi?id=182606

Description Andrew Morris 2017-11-22 22:13:02 PST
After a successful/normal acquisition of the camera and microphone, if they are then released, the tab stays open, and then a (regular) phone call is received, trying getUserMedia again seems to work (programmatically) but no actual video or audio is actually captured.

More specifically, we are seeing this with OpenTok and you can reproduce it like this:

1. Go to safari.opentokrtc.com
2. Fill in some arbitrary details, and enter a room, you should see the video from the front-facing camera (no need to have another participant in the room)
3. Exit the call using the red hangup button
4. Keeping Safari open, receive a call from another phone
5. Answer the call, hangup after a few seconds
6. Fill in some arbitrary details again, enter a room, and you will see a black box instead o the video from your camera

I've inspected this a little with dev tools and there is a stream object that was generated with video and audio tracks, both tracks have muted=false and enabled=true, but there is no actual media. We also seem to have the correct resolution of what the video would be too.
Comment 1 Andrew Morris 2017-11-22 22:14:18 PST
Also btw, have tested this on three iPhones with different versions of iOS: 11.1.1, 11.1.2, and 11.2 beta. Issue is 100% reproducible in each case.
Comment 2 Bryan McCarthy 2017-11-30 10:02:51 PST
We are also experiencing this issue and can reproduce 100% of the time. The only workaround is to restart Safari. It would be good to understand if there are any other less brutal workarounds.
Comment 3 Radar WebKit Bug Importer 2017-11-30 10:08:41 PST
<rdar://problem/35775140>
Comment 4 daginge 2017-12-20 04:41:35 PST
Based on what I've been observing, it seems like the following is happening here:

1. On the initial getUserMedia call, you will get a reference to audio and video resources (only one process may have this at any point in time).
2. On subsequent getUserMedia calls, the reference to the media resource is re-used.
3. If another process steals the resource (audio and/or video), the reference that Safari has will fail, and would have to be requested again. However, this is never checked by Safari, and it simply returns with the reference which now does not have access anymore to read from the resource.
4. Subsequent getUserMedia calls will not fix this, as it will detect the old reference and think it has permission to read from the media resource.

I suspect that closing the tab and trying again will make it work, as it seems from my tests that the permissions are granted on a per-tab basis, instead of for all of Safari. This will also explain why requesting media from a new tab on iOS will break capturing of media in the old tab (and make that tab never work with getUserMedia again).

I do not know of a workaround from JavaScript to fix this unfortunately. Perhaps youenn has some details?
Comment 5 youenn fablet 2017-12-20 09:46:00 PST
(In reply to daginge from comment #4)
> Based on what I've been observing, it seems like the following is happening
> here:
> 
> 1. On the initial getUserMedia call, you will get a reference to audio and
> video resources (only one process may have this at any point in time).
> 2. On subsequent getUserMedia calls, the reference to the media resource is
> re-used.

Only one media stream at a time can grab camera or microphone.
If you do a getUserMedia in a page and get a stream, it will work.
If you do another getUserMedia (on the page or another page), the first stream will get muted.
The second stream should be fine.

> 3. If another process steals the resource (audio and/or video), the
> reference that Safari has will fail, and would have to be requested again.
> However, this is never checked by Safari, and it simply returns with the
> reference which now does not have access anymore to read from the resource.

If so, that is a bug.
The newest getUserMedia should succeed and will mute the initial tab.
If this is done on different pages, you should be able to switch between the streams using Safari UI (camera icons).
It is working consistently on MacOS. Doing some testing in recent iOS builds, we might have some bugs there.

> 4. Subsequent getUserMedia calls will not fix this, as it will detect the
> old reference and think it has permission to read from the media resource.

If you keep all tabs opened it should work.
It seems there is a bug when one capturing tab is closing and another is starting at the same time.

> I suspect that closing the tab and trying again will make it work, as it
> seems from my tests that the permissions are granted on a per-tab basis,
> instead of for all of Safari. This will also explain why requesting media
> from a new tab on iOS will break capturing of media in the old tab (and make
> that tab never work with getUserMedia again).
> 
> I do not know of a workaround from JavaScript to fix this unfortunately.
> Perhaps youenn has some details?

There is no perfect workaround right now.
It seems the only possibility is to:
- open a new tab
- close all the tabs that are capturing/trying to capture.
- wait a little bit to capture in the new tab.
This should hopefully work as the previously closed tabs will do their cleanup and tear down the capture devices.
Then the new tab will do a fresh start without any issue.
That may be doable if your web site is the only one capturing at any given time.

This is a bad bug and we should try to fix it asap.
Comment 6 Adam 2018-02-06 15:18:53 PST
We are getting reports of a similar issue when using another app that uses the microphone (in this case Whatsapp) and then coming back to Safari. You have to quit Safari and open a new tab to get access to the microphone again. Subsequent calls to getUserMedia result in a stream without audio. 

Customer reports below problem:

1) Get an iPhone (let's say iPhone 7)

2) Access to playground (https://tokbox.com/developer/tools/playground/) with Safari, and start publishing. Subscribers 
will get video and audio.

3) Stop publishing. (Don't disconnect, just stop)

4) Go to whatsapp and make an audio call. (Start call, listen to audio 
and stop call)

5) Go back to playground and publish again.

6) You will get only video on the subscribers, but no audio.

Workarounds:

a) Refresh the Safari tab -> it does not help.

b) Close the Safari tab and go to playground on a fresh new tab -> 
audio comes back.
Comment 7 Jon Lee 2018-02-06 18:17:11 PST
Please try on the latest 11.3 beta.
Comment 8 Adam 2018-02-06 20:52:10 PST
Still happening for me on 11.3 beta 1. Upgrading to 11.3 beta 2 now 🤞
Comment 9 Adam 2018-02-06 22:39:20 PST
Still happening with 11.3 beta 2 as well. Here's how i reproduced it:

1. Go to meet.tokbox.com/testing
2. Allow access to your camera
3. Click the unpublish button
4. Make a phone call (I called my voicemail and waited 3 seconds)
5. Go back to Safari and click on the "Publish HD" button.

Result: You get a timeout trying to publish because there is no audio. You keep getting  the timeout in that tab even if you refresh it. You have to close it and open a new tab.
Comment 10 youenn fablet 2018-02-07 08:52:23 PST
(In reply to Adam from comment #9)
> Still happening with 11.3 beta 2 as well. Here's how i reproduced it:
> 
> 1. Go to meet.tokbox.com/testing
> 2. Allow access to your camera
> 3. Click the unpublish button
> 4. Make a phone call (I called my voicemail and waited 3 seconds)
> 5. Go back to Safari and click on the "Publish HD" button.
> 
> Result: You get a timeout trying to publish because there is no audio. You
> keep getting  the timeout in that tab even if you refresh it. You have to
> close it and open a new tab.

I also reproduced the issue.
Did some testing and if one does not do 3, reloading at step 5 allows getting back the audio.
Comment 11 Mark Roberts 2018-02-07 08:58:45 PST
I'm also observing this issue and getting reports from users who are seeing this issue. macOS and iOS seem affected (iOS 11.2.1, Safari 11.0.3). Specifically, video is fine, but I observe what Adam mentions:

> 6) You will get only video on the subscribers, but no audio.

I also see no bytesSent or bytesReceived for the audio track in getStats. This is reproducible with just the getUserMedia samples from https://webrtc.github.io/samples/ (as mentioned in the related bug, 180748).
Comment 12 Adam 2018-02-20 18:21:11 PST
I just updated to the new iOS 11.3 beta 3 (15E5189f) and this issue is resolved for me now! I can no longer reproduce the problem with my steps above. Thank you!
Comment 13 Jon Lee 2018-02-20 18:53:01 PST

*** This bug has been marked as a duplicate of bug 182606 ***