Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa188849 authored by Thomas Stuart's avatar Thomas Stuart
Browse files

tracked calls now recieve the AR change for active call

WA reported a bug where a self managed call was placed via earpiece,
placed another MO PSTN call on speaker was made in between, and when coming
back to the WA call, the audio route was still earpiece and not speaker.

This change updates all tracked calls with the audio route change of the
active foreground call.

Bug: 233930427
Test: 2 manual,
	a. using telecom's self-managed test app
	b. using WA (ConnectionService version)  w/ whitelisted numbers
      1 unit test, atest CallAudioRouteStateMachineTest#
                         testTrackedCallsReceiveAudioRouteChange
Change-Id: I5362381bb8b230a2cf7aaa550940ced53e8d5c44
parent 106ad531
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import com.android.server.telecom.bluetooth.BluetoothRouteManager;
import java.util.Collection;
import java.util.HashMap;
import java.util.Objects;
import java.util.Set;

/**
 * This class describes the available routes of a call as a state machine.
@@ -1764,18 +1765,20 @@ public class CallAudioRouteStateMachine extends StateMachine {
            if (force || !newCallAudioState.equals(mLastKnownCallAudioState)) {
                mStatusBarNotifier.notifyMute(newCallAudioState.isMuted());
                mCallsManager.onCallAudioStateChanged(mLastKnownCallAudioState, newCallAudioState);
                updateAudioForForegroundCall(newCallAudioState);
                updateAudioStateForTrackedCalls(newCallAudioState);
                mLastKnownCallAudioState = newCallAudioState;
            }
        }
    }

    private void updateAudioForForegroundCall(CallAudioState newCallAudioState) {
        Call call = mCallsManager.getForegroundCall();
    private void updateAudioStateForTrackedCalls(CallAudioState newCallAudioState) {
        Set<Call> calls = mCallsManager.getTrackedCalls();
        for (Call call : calls) {
            if (call != null && call.getConnectionService() != null) {
                call.getConnectionService().onCallAudioStateChanged(call, newCallAudioState);
            }
        }
    }

    private int calculateSupportedRoutes() {
        int routeMask = CallAudioState.ROUTE_SPEAKER;
+9 −0
Original line number Diff line number Diff line
@@ -1137,6 +1137,15 @@ public class CallsManager extends Call.ListenerBase
        return mCallAudioManager.getForegroundCall();
    }

    @VisibleForTesting
    public Set<Call> getTrackedCalls() {
        if (mCallAudioManager == null) {
            // Happens when getTrackedCalls is called before full initialization.
            return null;
        }
        return mCallAudioManager.getTrackedCalls();
    }

    @Override
    public void onCallHoldFailed(Call call) {
        markAllAnsweredCallAsRinging(call, "hold");
+54 −0
Original line number Diff line number Diff line
@@ -53,7 +53,9 @@ import org.mockito.stubbing.Answer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -89,6 +91,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase {
    @Mock ConnectionServiceWrapper mockConnectionServiceWrapper;
    @Mock WiredHeadsetManager mockWiredHeadsetManager;
    @Mock StatusBarNotifier mockStatusBarNotifier;
    @Mock Call fakeSelfManagedCall;
    @Mock Call fakeCall;
    @Mock CallAudioManager mockCallAudioManager;

@@ -116,11 +119,16 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase {
        };

        when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
        when(mockCallsManager.getTrackedCalls()).thenReturn(Set.of(fakeCall));
        when(mockCallsManager.getLock()).thenReturn(mLock);
        when(mockCallsManager.hasVideoCall()).thenReturn(false);
        when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
        when(fakeCall.isAlive()).thenReturn(true);
        when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
        when(fakeSelfManagedCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
        when(fakeSelfManagedCall.isAlive()).thenReturn(true);
        when(fakeSelfManagedCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
        when(fakeSelfManagedCall.isSelfManaged()).thenReturn(true);

        doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class),
                any(CallAudioState.class));
@@ -153,6 +161,51 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase {
        assertNotNull(stateMachine);
    }

    @SmallTest
    @Test
    public void testTrackedCallsReceiveAudioRouteChange() {
        CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine(
                mContext,
                mockCallsManager,
                mockBluetoothRouteManager,
                mockWiredHeadsetManager,
                mockStatusBarNotifier,
                mAudioServiceFactory,
                CallAudioRouteStateMachine.EARPIECE_AUTO_DETECT,
                mThreadHandler.getLooper());
        stateMachine.setCallAudioManager(mockCallAudioManager);

        Set<Call> trackedCalls = new HashSet<>(Arrays.asList(fakeCall, fakeSelfManagedCall));
        when(mockCallsManager.getTrackedCalls()).thenReturn(trackedCalls);

        // start state --> ROUTE_EARPIECE
        CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE,
                CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER);
        stateMachine.initialize(initState);

        stateMachine.setCallAudioManager(mockCallAudioManager);

        assertEquals(stateMachine.getCurrentCallAudioState().getRoute(),
                CallAudioRouteStateMachine.ROUTE_EARPIECE);

        // ROUTE_EARPIECE  --> ROUTE_SPEAKER
        stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_SPEAKER,
                CallAudioRouteStateMachine.SPEAKER_ON);

        stateMachine.sendMessageWithSessionInfo(
                CallAudioRouteStateMachine.UPDATE_SYSTEM_AUDIO_ROUTE);

        waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);
        waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT);

        // assert expected end state
        assertEquals(stateMachine.getCurrentCallAudioState().getRoute(),
                CallAudioRouteStateMachine.ROUTE_SPEAKER);
        // should update the audio route on all tracked calls ...
        verify(mockConnectionServiceWrapper, times(trackedCalls.size()))
                .onCallAudioStateChanged(any(), any());
    }

    @MediumTest
    @Test
    public void testStreamRingMuteChange() {
@@ -749,6 +802,7 @@ public class CallAudioRouteStateMachineTest extends TelecomTestCase {
                mockConnectionServiceWrapper);
        fakeCall = mock(Call.class);
        when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
        when(mockCallsManager.getTrackedCalls()).thenReturn(Set.of(fakeCall));
        when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);
        when(fakeCall.isAlive()).thenReturn(true);
        when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL);
+2 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@RunWith(Parameterized.class)
public class CallAudioRouteTransitionTests extends TelecomTestCase {
@@ -182,6 +183,7 @@ public class CallAudioRouteTransitionTests extends TelecomTestCase {
        };

        when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall);
        when(mockCallsManager.getTrackedCalls()).thenReturn(Set.of(fakeCall));
        when(mockCallsManager.getLock()).thenReturn(mLock);
        when(mockCallsManager.hasVideoCall()).thenReturn(false);
        when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper);