AVAudioEngine installTap stops working after phone call interruption on iPhone 16e

Environment

  • Device: iPhone 16e
  • iOS Version: 18.4.1 - 18.7.1
  • Framework: AVFoundation (AVAudioEngine)

Problem Summary

On iPhone 16e (iOS 18.4.1-18.7.1), the installTap callback stops being invoked after resuming from a phone call interruption. This issue is specific to phone call interruptions and does not occur on iPhone 14, iPhone SE 3, or earlier devices.

Expected Behavior

After a phone call interruption ends and audioEngine.start() is called, the previously installed tap should continue receiving audio buffers.

Actual Behavior

After resuming from phone call interruption:

  • Tap callback is no longer invoked
  • No audio data is captured
  • No errors are thrown
  • Engine appears to be running normally

Note: Normal pause/resume (without phone call interruption) works correctly.

Steps to Reproduce

  1. Start audio recording on iPhone 16e
  2. Receive or make a phone call (triggers AVAudioSession interruption)
  3. End the phone call
  4. Resume recording with audioEngine.start()
  5. Result: Tap callback is not invoked

Tested devices:

  • iPhone 16e (iOS 18.4.1-18.7.1): Issue reproduces ✗
  • iPhone 14 (iOS 18.x): Works correctly ✓
  • iPhone SE 3 (iOS 18.x): Works correctly ✓

Code

Initial Setup (Works)

let inputNode = audioEngine.inputNode
inputNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, time in
    self.processAudioBuffer(buffer, at: time)
}
audioEngine.prepare()
try audioEngine.start()

Interruption Handling

NotificationCenter.default.addObserver(
    forName: AVAudioSession.interruptionNotification,
    object: AVAudioSession.sharedInstance(),
    queue: nil
) { notification in
    guard let userInfo = notification.userInfo,
          let typeValue = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt,
          let type = AVAudioSession.InterruptionType(rawValue: typeValue) else {
        return
    }
    
    if type == .began {
        self.audioEngine.pause()
    } else if type == .ended {
        try? self.audioSession.setActive(true)
        try? self.audioEngine.start()
        // Tap callback doesn't work after this on iPhone 16e
    }
}

Workaround

Full engine restart is required on iPhone 16e:

func resumeAfterInterruption() {
    audioEngine.stop()
    inputNode.removeTap(onBus: 0)
    inputNode.installTap(onBus: 0, bufferSize: 4096, format: nil) { buffer, time in
        self.processAudioBuffer(buffer, at: time)
    }
    audioEngine.prepare()
    try audioSession.setActive(true)
    try audioEngine.start()
}

This works but adds latency and complexity compared to simple resume.

Questions

  1. Is this expected behavior on iPhone 16e?
  2. What is the recommended way to handle phone call interruptions?
  3. Why does this only affect iPhone 16e and not iPhone 14 or SE 3?

Any guidance would be appreciated!

AVAudioEngine installTap stops working after phone call interruption on iPhone 16e
 
 
Q