Skip to content

Releases: willbin/callkit-ios27-repro

iOS 27 Public Beta 6 — CallKit residual UI reproduction

Choose a tag to compare

@willbin willbin released this 09 Sep 10:22
477dc89

Summary

On an iPhone 17 running iOS 27 Public Beta 6, the system CallKit UI remains visible after ending two outgoing calls individually.

This is reproducible using Apple's “Making and Receiving VoIP Calls with CallKit” sample (Speakerbox), with only two minimal changes to support multiple simultaneous calls. After both calls end, Speakerbox displays “No Calls”, but the system CallKit UI still shows 111, and the Dynamic Island retains a call-related status.

Environment

  • Device: iPhone 17 (physical device)
  • OS: iOS 27 Public Beta 6
  • App: Apple's Speakerbox sample with the modifications below
  • Backend: None. The sample's original simulated calls are used; no external VoIP SDK is involved.

Changes to the original sample

Only two files were modified.

1. ProviderDelegate.swift

Added:

providerConfiguration.maximumCallGroups = 3

The original setting remains unchanged:

providerConfiguration.maximumCallsPerCallGroup = 1

2. SpeakerboxCallManager.swift

Before starting a new outgoing call, hold existing calls that are not already on hold. The hold actions and new start action are submitted in the same transaction:

let transaction = CXTransaction()

for call in calls where !call.isOnHold {
    transaction.addAction(
        CXSetHeldCallAction(call: call.uuid, onHold: true)
    )
}

transaction.addAction(startCallAction)
requestTransaction(transaction)

No changes were made to the simulated connection timing, startedConnectingAt/connectedAt reporting, CXEndCallAction handling, call removal, or audio handling.

The original end-call handler finds the call by UUID, calls endSpeakerboxCall(), fulfills the end action, and removes the call from the app's list.

Steps to reproduce

  1. Launch the modified Speakerbox sample.
  2. Create an outgoing call to 111.
  3. Create a second outgoing call to 222. The first call is placed on hold.
  4. Wait until Speakerbox shows 111 — On Hold and 222 — Active, with call durations displayed.
  5. In Speakerbox, select 222 → End Call.
  6. Select 111 → End Call.
  7. Confirm that Speakerbox displays “No Calls”.
  8. Open the app switcher and inspect the system CallKit UI. Also inspect the Dynamic Island.
  9. Open the remaining system call UI and tap End.

Expected result

After both calls end, the system should no longer display an ongoing call in the CallKit UI or Dynamic Island.

Actual result

  • Speakerbox displays “No Calls”.
  • The system CallKit UI continues to display the first call, 111.
  • The Dynamic Island continues to show a call-related “Hold” status.
  • Tapping End in the remaining system call UI does not clear the residual state during the recording.
  • The issue occurs even after waiting for both simulated calls to connect before ending them.

This is the system-provided CallKit UI, not an active-call view implemented by the sample app.

Reproduction video

Recording: 4b03d30e507b874d9c19c0523632e9d6.mp4

  • 00:24–00:26 (approximately): Both calls are present; 111 is on hold and 222 is active.
  • 00:26–00:31 (approximately): End 222, then end 111. Speakerbox displays “No Calls”.
  • 00:31–01:03 (approximately): The system CallKit UI and Dynamic Island retain the call state despite further attempts to end it.

Questions

Is this an iOS 27 regression, or is additional lifecycle handling required when extending Speakerbox to support multiple calls?

Please advise what additional diagnostics would help investigate why the system UI retains an ongoing-call state after both calls have been ended using the sample's original end-call handling.

Downloads

The modified Apple Speakerbox source ZIP and reproduction MP4 are attached below. Apple sample code retains its original license in the archive.