import AVFoundation import CallsKit import XCTest /// The Bluetooth rule, which only exists on iOS and so can only be tested /// here — CallsKitTests builds for macOS, where AVAudioSession does not /// exist at all. final class AudioRouteTests: XCTestCase { func testBluetoothIsAllowedOnlyWhenItIsTheChosenMicrophone() { // .allowBluetoothHFP is what lets a Bluetooth microphone be used, and // it is also what drags the whole call to the 8 kHz hands-free // profile the moment any headset connects. Left on unconditionally — // as it was until this change — every pair of AirPods silently cost // the call its audio quality in both directions, and nothing said so. let ordinary = AudioRoutes.options(bluetoothInput: false) XCTAssertFalse( ordinary.contains(.allowBluetoothHFP), "a call with no Bluetooth microphone chosen must not offer the hands-free profile") XCTAssertTrue( ordinary.contains(.allowBluetoothA2DP), "output should still reach a headset, at A2DP quality") XCTAssertTrue(ordinary.contains(.defaultToSpeaker)) // Picking the headset microphone is an informed trade, and then HFP // is exactly what has to be allowed for it to work at all. let headset = AudioRoutes.options(bluetoothInput: true) XCTAssertTrue(headset.contains(.allowBluetoothHFP)) XCTAssertTrue(headset.contains(.defaultToSpeaker)) } func testOnlyTheHandsFreePortCountsAsABluetoothMicrophone() { // A2DP is output-only, so a Bluetooth device being used as a // microphone is always on the hands-free port. Treating A2DP as a // microphone would turn HFP back on for a headset nobody is // recording from, which is the bug this rule exists to avoid. XCTAssertEqual(AVAudioSession.Port.bluetoothHFP.rawValue, "BluetoothHFP") XCTAssertNotEqual(AVAudioSession.Port.bluetoothA2DP, AVAudioSession.Port.bluetoothHFP) } }