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
- Start audio recording on iPhone 16e
- Receive or make a phone call (triggers AVAudioSession interruption)
- End the phone call
- Resume recording with audioEngine.start()
- 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
- Is this expected behavior on iPhone 16e?
- What is the recommended way to handle phone call interruptions?
- Why does this only affect iPhone 16e and not iPhone 14 or SE 3?
Any guidance would be appreciated!
