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

Commit fe6f7a18 authored by Pengquan Meng's avatar Pengquan Meng Committed by Android (Google) Code Review
Browse files

Merge "Fixed selfManaged call issue"

parents 311bf9d0 8229bc96
Loading
Loading
Loading
Loading
+44 −31
Original line number Diff line number Diff line
@@ -1469,34 +1469,7 @@ public class CallsManager extends Call.ListenerBase
            // Hold or disconnect the active call and request call focus for the incoming call.
            Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
            Log.d(this, "Incoming call = %s Ongoing call %s", call, activeCall);
            if (activeCall != null && activeCall != call) {
                // We purposely don't check if the active call CAN current hold, but rather we check
                // whether it CAN support hold.  Consider this scenario:
                // Call A - Active (CAPABILITY_SUPPORT_HOLD, but not CAPABILITY_HOLD)
                // Call B - Held (CAPABILITY_SUPPORT_HOLD, but not CAPABILITY_HOLD)
                // Call C - Incoming call
                // In this scenario we are going to first disconnect the held call (Call B), which
                // will mean that the active call (Call A) will now support hold.
                if (supportsHold(activeCall)) {
                    Call heldCall = getHeldCall();
                    if (heldCall != null) {
                        Log.i(this, "Disconnecting held call %s before holding active call.",
                                heldCall);
                        heldCall.disconnect();
                    }

                    Log.d(this, "Answer %s, hold %s", call, activeCall);
                    activeCall.hold();
                } else {
                    // This call does not support hold. If it is from a different connection
                    // service, then disconnect it, otherwise allow the connection service to
                    // figure out the right states.
                    if (activeCall.getConnectionService() != call.getConnectionService()) {
                        activeCall.disconnect("Can't hold when answering " + call.getId());
                    }
                }
            }

            holdActiveCallForNewCall(call);
            mConnectionSvrFocusMgr.requestFocus(
                    call,
                    new RequestCallback(new ActionAnswerCall(call, videoState)));
@@ -1932,11 +1905,43 @@ public class CallsManager extends Call.ListenerBase
        maybeMoveToSpeakerPhone(call);
    }

    void markCallAsActive(Call call) {
    /**
     * Returns true if the active call is held.
     */
    boolean holdActiveCallForNewCall(Call call) {
        Call activeCall = (Call) mConnectionSvrFocusMgr.getCurrentFocusCall();
        if (activeCall != null && activeCall != call) {
            if (canHold(activeCall)) {
                activeCall.hold();
                return true;
            } else if (supportsHold(call)) {
                Call heldCall = getHeldCallByConnectionService(call.getConnectionService());
                if (heldCall != null) {
                    heldCall.disconnect();
                    Log.i(this, "Disconnecting held call %s before holding active call.", heldCall);
                }
                activeCall.hold();
                return true;
            } else {
                // This call does not support hold. If it is from a different connection
                // service, then disconnect it, otherwise allow the connection service to
                // figure out the right states.
                if (activeCall.getConnectionService() != call.getConnectionService()) {
                    activeCall.disconnect();
                }
            }
        }
        return false;
    }

    @VisibleForTesting
    public void markCallAsActive(Call call) {
        if (call.isSelfManaged()) {
            // backward compatibility, the self-managed connection service will set the call state
            // to active directly. We should request the call focus for self-managed call before
            // the state change
            // to active directly. We should hold or disconnect the current active call based on the
            // holdability, and request the call focus for the self-managed call before the state
            // change.
            holdActiveCallForNewCall(call);
            mConnectionSvrFocusMgr.requestFocus(
                    call,
                    new RequestCallback(new ActionSetCallState(
@@ -2168,6 +2173,14 @@ public class CallsManager extends Call.ListenerBase
        return getFirstCallWithState(CallState.ON_HOLD);
    }

    public Call getHeldCallByConnectionService(ConnectionServiceWrapper connSvr) {
        Optional<Call> heldCall = mCalls.stream()
                .filter(call -> call.getConnectionService() == connSvr
                        && call.getState() == CallState.ON_HOLD)
                .findFirst();
        return heldCall.isPresent() ? heldCall.get() : null;
    }

    @VisibleForTesting
    public int getNumHeldCalls() {
        int count = 0;
+128 −9
Original line number Diff line number Diff line
@@ -23,8 +23,6 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyChar;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
@@ -421,6 +419,7 @@ public class CallsManagerTest extends TelecomTestCase {
        // GIVEN a CallsManager with ongoing call, and this call can be held
        Call ongoingCall = addSpyCall();
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call
@@ -430,11 +429,11 @@ public class CallsManagerTest extends TelecomTestCase {
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call is held, and the focus request for incoming call is sent
        verify(ongoingCall).hold();
        verify(ongoingCall).hold(any());
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold();
        verify(heldCall).unhold(any());
    }

    @SmallTest
@@ -446,6 +445,7 @@ public class CallsManagerTest extends TelecomTestCase {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call which has different ConnectionService
@@ -455,13 +455,14 @@ public class CallsManagerTest extends TelecomTestCase {
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call is disconnected, and the focus request for incoming call is sent
        verify(ongoingCall).disconnect();
        verify(ongoingCall).disconnect(any());
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold();
        verify(heldCall).unhold(any());
    }

    @SmallTest
    @Test
    public void testUnholdCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
        ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);
@@ -469,6 +470,7 @@ public class CallsManagerTest extends TelecomTestCase {
        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCallWithConnectionService(connSvr);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a held call which has different ConnectionService
@@ -478,11 +480,11 @@ public class CallsManagerTest extends TelecomTestCase {
        mCallsManager.unholdCall(heldCall);

        // THEN the ongoing call is held
        verify(ongoingCall).hold();
        verify(ongoingCall).hold(any());
        verifyFocusRequestAndExecuteCallback(heldCall);

        // and held call is unhold now
        verify(heldCall).unhold();
        verify(heldCall).unhold(any());
    }

    @SmallTest
@@ -491,6 +493,7 @@ public class CallsManagerTest extends TelecomTestCase {
        // GIVEN a CallsManager with ongoing call, and this call can be held
        Call ongoingCall = addSpyCall();
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // WHEN answer an incoming call
@@ -528,13 +531,14 @@ public class CallsManagerTest extends TelecomTestCase {

    @SmallTest
    @Test
    public void testANswerCallWhenOngoingHasDifferentConnectionService() {
    public void testAnswerCallWhenOngoingHasDifferentConnectionService() {
        ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
        ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);

        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // WHEN answer an incoming call
@@ -549,6 +553,44 @@ public class CallsManagerTest extends TelecomTestCase {
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenMultipleHeldCallsExisted() {
        ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
        ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);

        // Given an ongoing call and held call with the ConnectionService connSvr1. The
        // ConnectionService connSvr1 can handle one held call
        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        Call heldCall = addSpyCallWithConnectionService(connSvr1);
        doReturn(CallState.ON_HOLD).when(heldCall).getState();

        // and other held call has difference ConnectionService
        Call heldCall2 = addSpyCallWithConnectionService(connSvr2);
        doReturn(CallState.ON_HOLD).when(heldCall2).getState();

        // WHEN answer an incoming call which ConnectionService is connSvr1
        Call incomingCall = addSpyCallWithConnectionService(connSvr1);
        mCallsManager.answerCall(incomingCall, VideoProfile.STATE_AUDIO_ONLY);

        // THEN the previous held call is disconnected
        verify(heldCall).disconnect();

        // and the ongoing call is held
        verify(ongoingCall).hold();

        // and the heldCall2 is not disconnected
        verify(heldCall2, never()).disconnect();

        // and the focus request is sent
        verifyFocusRequestAndExecuteCallback(incomingCall);

        // and the incoming call is answered
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testAnswerCallWhenNoOngoingCallExisted() {
@@ -565,6 +607,83 @@ public class CallsManagerTest extends TelecomTestCase {
        verify(incomingCall).answer(VideoProfile.STATE_AUDIO_ONLY);
    }

    @SmallTest
    @Test
    public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndFromDifferentConnectionService() {
        ConnectionServiceWrapper connSvr1 = Mockito.mock(ConnectionServiceWrapper.class);
        ConnectionServiceWrapper connSvr2 = Mockito.mock(ConnectionServiceWrapper.class);

        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCallWithConnectionService(connSvr1);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();

        // and a new self-managed call which has different ConnectionService
        Call newCall = addSpyCallWithConnectionService(connSvr2);
        doReturn(true).when(newCall).isSelfManaged();

        // WHEN active the new call
        mCallsManager.markCallAsActive(newCall);

        // THEN the ongoing call is disconnected, and the focus request for the new call is sent
        verify(ongoingCall).disconnect();
        verifyFocusRequestAndExecuteCallback(newCall);

        // and the new call is active
        assertEquals(CallState.ACTIVE, newCall.getState());
    }

    @SmallTest
    @Test
    public void testSetActiveCallWhenOngoingCallCanNotBeHeldAndHasSameConnectionService() {
        ConnectionServiceWrapper connSvr = Mockito.mock(ConnectionServiceWrapper.class);

        // GIVEN a CallsManager with ongoing call, and this call can not be held
        Call ongoingCall = addSpyCallWithConnectionService(connSvr);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(false).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        when(mConnectionSvrFocusMgr.getCurrentFocusCall()).thenReturn(ongoingCall);

        // and a new self-managed call which has the same ConnectionService
        Call newCall = addSpyCallWithConnectionService(connSvr);
        doReturn(true).when(newCall).isSelfManaged();

        // WHEN active the new call
        mCallsManager.markCallAsActive(newCall);

        // THEN the ongoing call isn't disconnected
        verify(ongoingCall, never()).disconnect();
        verifyFocusRequestAndExecuteCallback(newCall);

        // and the new call is active
        assertEquals(CallState.ACTIVE, newCall.getState());
    }

    @SmallTest
    @Test
    public void testSetActiveCallWhenOngoingCallCanBeHeld() {
        // GIVEN a CallsManager with ongoing call, and this call can be held
        Call ongoingCall = addSpyCall();
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_HOLD);
        doReturn(true).when(ongoingCall).can(Connection.CAPABILITY_SUPPORT_HOLD);
        doReturn(ongoingCall).when(mConnectionSvrFocusMgr).getCurrentFocusCall();

        // and a new self-managed call
        Call newCall = addSpyCall();
        doReturn(true).when(newCall).isSelfManaged();

        // WHEN active the new call
        mCallsManager.markCallAsActive(newCall);

        // THEN the ongoing call is held
        verify(ongoingCall).hold();
        verifyFocusRequestAndExecuteCallback(newCall);

        // and the new call is active
        assertEquals(CallState.ACTIVE, newCall.getState());
    }

    private Call addSpyCallWithConnectionService(ConnectionServiceWrapper connSvr) {
        Call call = addSpyCall();
        doReturn(connSvr).when(call).getConnectionService();