Resolve call audio focus not abandoned
If a BT device is connected and an incoming call is placed and rejected,
if the inband ringing is disabled, the audio routing never goes active.
The logic in handling a focus switch to NO_FOCUS currently only abandons
audio focus if the audio routing was active. Looking back at this code,
we really should just reinitialize all of the audio routing state
regardless of whether or not the audio routing was active. A lot of
these operations would be unaffected when performing them over an
inactive audio route but it's good to just reset the controller state
once the call ends.
Bug: 376820227
Flag: EXEMPT bugfix
Test: CallAudioRouteControllerTest#testAbandonCallAudioFocusAfterCallEnd
Change-Id: I3657cb8797d1a15eecf7254b9ceec9ea3851fde4
diff --git a/src/com/android/server/telecom/CallAudioRouteController.java b/src/com/android/server/telecom/CallAudioRouteController.java
index d826b9d..04a4e89 100644
--- a/src/com/android/server/telecom/CallAudioRouteController.java
+++ b/src/com/android/server/telecom/CallAudioRouteController.java
@@ -878,24 +878,22 @@
mFocusType = focus;
switch (focus) {
case NO_FOCUS -> {
- if (mIsActive) {
- // Notify the CallAudioModeStateMachine that audio operations are complete so
- // that we can relinquish audio focus.
- mCallAudioManager.notifyAudioOperationsComplete();
-
- // Reset mute state after call ends.
- handleMuteChanged(false);
- // Ensure we reset call audio state at the end of the call (i.e. if we're on
- // speaker, route back to earpiece). If we're on BT, remain on BT if it's still
- // connected.
- AudioRoute route = mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()
- ? calculateBaselineRoute(false, true, null)
- : mCurrentRoute;
- routeTo(false, route);
- // Clear pending messages
- mPendingAudioRoute.clearPendingMessages();
- clearRingingBluetoothAddress();
- }
+ // Notify the CallAudioModeStateMachine that audio operations are complete so
+ // that we can relinquish audio focus.
+ mCallAudioManager.notifyAudioOperationsComplete();
+ // Reset mute state after call ends. This should remain unaffected if audio routing
+ // never went active.
+ handleMuteChanged(false);
+ // Ensure we reset call audio state at the end of the call (i.e. if we're on
+ // speaker, route back to earpiece). If we're on BT, remain on BT if it's still
+ // connected.
+ AudioRoute route = mFeatureFlags.resolveActiveBtRoutingAndBtTimingIssue()
+ ? calculateBaselineRoute(false, true, null)
+ : mCurrentRoute;
+ routeTo(false, route);
+ // Clear pending messages
+ mPendingAudioRoute.clearPendingMessages();
+ clearRingingBluetoothAddress();
}
case ACTIVE_FOCUS -> {
// Route to active baseline route (we may need to change audio route in the case
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java
index 330e84c..ba48c64 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteControllerTest.java
@@ -1099,6 +1099,38 @@
any(CallAudioState.class), eq(expectedState));
}
+ @Test
+ @SmallTest
+ public void testAbandonCallAudioFocusAfterCallEnd() {
+ // Make sure in-band ringing is disabled so that route never becomes active
+ when(mBluetoothRouteManager.isInbandRingEnabled(eq(BLUETOOTH_DEVICE_1))).thenReturn(false);
+
+ mController.initialize();
+ mController.sendMessageWithSessionInfo(BT_DEVICE_ADDED, AudioRoute.TYPE_BLUETOOTH_SCO,
+ BLUETOOTH_DEVICE_1);
+
+ CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH,
+ CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH
+ | CallAudioState.ROUTE_SPEAKER, BLUETOOTH_DEVICE_1, BLUETOOTH_DEVICES);
+ mController.sendMessageWithSessionInfo(BT_ACTIVE_DEVICE_PRESENT,
+ AudioRoute.TYPE_BLUETOOTH_SCO, BT_ADDRESS_1);
+ verify(mCallsManager, timeout(TEST_TIMEOUT)).onCallAudioStateChanged(
+ any(CallAudioState.class), eq(expectedState));
+ assertFalse(mController.isActive());
+
+ // Verify route never went active due to in-band ringing being disabled.
+ mController.sendMessageWithSessionInfo(SWITCH_FOCUS, RINGING_FOCUS, 0);
+ assertFalse(mController.isActive());
+
+ // Emulate scenario of rejecting an incoming call so that call focus is lost and verify
+ // that we abandon the call audio focus that was gained from when the call went to
+ // ringing state.
+ mController.sendMessageWithSessionInfo(SWITCH_FOCUS, NO_FOCUS, 0);
+ // Ensure we tell the CallAudioManager that audio operations are done so that we can ensure
+ // audio focus is relinquished.
+ verify(mCallAudioManager, timeout(TEST_TIMEOUT)).notifyAudioOperationsComplete();
+ }
+
private void verifyConnectBluetoothDevice(int audioType) {
mController.initialize();
mController.setActive(true);