SRGSSR / srgletterbox-apple

The official SRG SSR media playback experience
https://srgssr.github.io/marketing/letterbox/
MIT License
14 stars 7 forks source link

Control center and audio session interaction issue #276

Open defagos opened 2 years ago

defagos commented 2 years ago

When switching the audio session AVAudioSessionCategoryOptionMixWithOthers option on, control center integration is automatically disabled by the system. When switching it back to off the control center is not automatically refreshed until the user pauses and resumes playback, e.g.

Issue type

Incorrect behavior

Environment information

Reproducibility

Always reproducible

Code sample

In AdvancedPlayerViewController~ios.m insert the following implementation to replace the existing one:

- (IBAction)toggleView:(UISwitch *)sender
{
    if (sender.on) {
        [AVAudioSession.sharedInstance setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeDefault options:0 error:NULL];
    }
    else {
        [AVAudioSession.sharedInstance setCategory:AVAudioSessionCategoryPlayback mode:AVAudioSessionModeDefault options:AVAudioSessionCategoryOptionMixWithOthers error:NULL];
    }
}

Steps to reproduce

  1. Apply the code sample instructions above.
  2. Run the demo and open the advanced player. Verify that the control center displays media information.
  3. Use the View attached to the controller switch, whose implementation has been tweaked above, to enable mix with other. Check the control center again: No more media information is displayed.
  4. Use the same switch to revert back to normal audio session options. Check the control center once more: No info is displayed, though we would expect some to be visible again.
  5. Pause and resume playback. Now the control center displays media information again.
defagos commented 2 years ago

I attempted to solve the issue as follows:

This sadly does not work. The only way I know of to make the system realize that audio is being heard again after temporarily switching to .mixWithOthers is to pause and resume the player, what our fellow SRF colleagues who reported the issue already suggested. But this makes the UI appear again, as we cannot know how a rate change is produced (we use KVO).

I also reproduced the issue by tweaking Apple audio session sample, which proves the issue is not related to our implementation. I should report this as a bug to Apple (iOS 16 beta exhibits the same behavior).

In the meantime I quite don't know what to do.

defagos commented 2 years ago

I reported the issue to Apple as FB11416789. Sample code is available as well. Here is the report I made:

Description of the problem

Applications might need to toggle AVAudioSession settings back and forth between .default and .mixWithOthers, e.g. when switching back and forth between an immersive full screen playback experience and a feed browsing experience presenting videos playing automatically without sound.

Control center integration availability depends on audio session settings. The .default option is namely required for proper control center metadata and playback control integration. When using .mixWithOthers control center integration is therefore not expected to be available, and this is what we currently correctly observe. The problem is that, while control center integration is correctly disabled when switching from .default to .mixWithOthers, it is incorrectly not enabled in the reverse direction, i.e. when switching from .mixWithOthers to .default.

The issue affects recent iOS versions (tested with 15.6.1 and 16 beta 8).

Step-by-step set of instructions to reproduce the problem

I attached a sample project to this issue. This project implements a simple video playback experience with minimal working control center integration and can be used to reproduce the described issue as follows (you can also see these steps in the attached video):

  1. Open the attached sample project and setup code signing.
  2. Run the project on a physical iOS device. The demo starts with an audio session set to the .playback category with .default options.
  3. Tap on "Play" to start playback. Open the control center to observe that metadata and playback controls are correctly available.
  4. Now use the "Mix with others enabled?" switch to enable the .mixWithOthers audio session option. Open the control center to observe that metadata and playback controls are not available anymore, as expected when using this audio session option.
  5. Now switch "Mix with others enabled?" back to off, setting the audio session option back to .default. Open the control center to observe that metadata and playback controls are still not available, though you would expect them to be available with this audio session option.

It seems that the issue is that iOS incorrectly fails to not detect that "a main playback" user experience is occurring when switching from .mixWithOthers to .default. You can test this intuition in the demo:

  1. Complete the above steps 1 to 5 if not done already.
  2. Tap on "Pause", then "Play" (which in effect simply sets the player rate to 0, then 1, without updating anything related to the control center or reinstantiating anything). When you then open the control center again you can observe that metadata and playback controls are now available, which suggests that this simple rate change allowed iOS to detect a main playback experience and restore control center integration.

Expected results

Assuming proper control center integration has been implemented, switching audio session options from .default to .mixWithOthers disables control center integration, while switching from .mixWithOthers to .default enables it.

Actual results

Assuming proper control center integration has been implemented, switching audio session options from .default to .mixWithOthers disables control center integration, but switching from .mixWithOthers to .default fails to enable it.