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

Commit bc00c318 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Ensure correct audio mode is used for conferences.

Conferences don't have an ability to indicate they're using VOIP audio
mode.  As a consequence, CallAudioManager can end up setting the audio
mode back to MODE_INCALL when holding and holding a conference call where
the children are all VOIP calls.  To fix this, add ability to get the
voip mode from the children if available.

Also added some more logging for VOIP audio mode and changes to this
attribute on a call.

Test: Manual on network; make voip conference and verify that the audio
works after hold/unhold operation and verify that MODE_IN_COMMUNICATION
is set correctly.
Test: Add unit test to ensure voip audio mode is detected for a conference
with VOIP children.
Fixes: 230536808
Change-Id: Idd3faa5cb8d78b886e7c87901692a3b0b1bbe10b
parent 37699d93
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -898,7 +898,7 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
    @Override
    public String toString() {
        return String.format(Locale.US, "[Call id=%s, state=%s, tpac=%s, cmgr=%s, handle=%s, "
                        + "vidst=%s, childs(%d), has_parent(%b), cap=%s, prop=%s]",
                        + "vidst=%s, childs(%d), has_parent(%b), cap=%s, prop=%s], voip=%b",
                mId,
                CallState.toString(getParcelableCallState()),
                getTargetPhoneAccount(),
@@ -908,7 +908,8 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
                getChildCalls().size(),
                getParentCall() != null,
                Connection.capabilitiesToStringShort(getConnectionCapabilities()),
                Connection.propertiesToStringShort(getConnectionProperties()));
                Connection.propertiesToStringShort(getConnectionProperties()),
                mIsVoipAudioMode);
    }

    @Override
@@ -3653,6 +3654,9 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
    }

    public void setIsVoipAudioMode(boolean audioModeIsVoip) {
        if (mIsVoipAudioMode != audioModeIsVoip) {
            Log.addEvent(this, LogUtils.Events.SET_VOIP_MODE, audioModeIsVoip ? "Y" : "N");
        }
        mIsVoipAudioMode = audioModeIsVoip;
        for (Listener l : mListeners) {
            l.onIsVoipAudioModeChanged(this);
+22 −1
Original line number Diff line number Diff line
@@ -733,10 +733,31 @@ public class CallAudioManager extends CallsManagerListenerBase {
                .setHasAudioProcessingCalls(mAudioProcessingCalls.size() > 0)
                .setIsTonePlaying(mIsTonePlaying)
                .setForegroundCallIsVoip(
                        mForegroundCall != null && mForegroundCall.getIsVoipAudioMode())
                        mForegroundCall != null && isCallVoip(mForegroundCall))
                .setSession(Log.createSubsession()).build();
    }

    /**
     * Determines if a {@link Call} is a VOIP call for audio purposes.
     * For top level calls, we get this from {@link Call#getIsVoipAudioMode()}.  A {@link Call}
     * representing a {@link android.telecom.Conference}, however, has no means of specifying that
     * it is a VOIP conference, so we will get that attribute from one of the children.
     * @param call The call.
     * @return {@code true} if the call is a VOIP call, {@code false} if is a SIM call.
     */
    @VisibleForTesting
    public boolean isCallVoip(Call call) {
        if (call.isConference() && call.getChildCalls() != null
                && call.getChildCalls().size() > 0 ) {
            // If this is a conference with children, we can get the VOIP audio mode attribute from
            // one of the children.  The Conference doesn't have a VOIP audio mode property, so we
            // need to infer from the first child.
            Call firstChild = call.getChildCalls().get(0);
            return firstChild.getIsVoipAudioMode();
        }
        return call.getIsVoipAudioMode();
    }

    private HashSet<Call> getBinForCall(Call call) {
        if (call.getState() == CallState.ANSWERED) {
            // If the call has the speed-up-mt-audio capability, treat answered state as active
+1 −0
Original line number Diff line number Diff line
@@ -208,6 +208,7 @@ public class LogUtils {
        public static final String CALL_DIAGNOSTIC_SERVICE_TIMEOUT =
                "CALL_DIAGNOSTIC_SERVICE_TIMEOUT";
        public static final String VERSTAT_CHANGED = "VERSTAT_CHANGED";
        public static final String SET_VOIP_MODE = "SET_VOIP_MODE";

        public static class Timings {
            public static final String ACCEPT_TIMING = "accept";
+16 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import org.junit.runners.JUnit4;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;

import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;
@@ -661,6 +662,21 @@ public class CallAudioManagerTest extends TelecomTestCase {
        verifyProperCleanup();
    }

    @SmallTest
    @Test
    public void testGetVoipMode() {
        Call child = mock(Call.class);
        when(child.getIsVoipAudioMode()).thenReturn(true);

        Call conference = mock(Call.class);
        when(conference.isConference()).thenReturn(true);
        when(conference.getIsVoipAudioMode()).thenReturn(false);
        when(conference.getChildCalls()).thenReturn(Arrays.asList(child));

        assertTrue(mCallAudioManager.isCallVoip(conference));
        assertTrue(mCallAudioManager.isCallVoip(child));
    }

    private Call createSimulatedRingingCall() {
        Call call = mock(Call.class);
        when(call.getState()).thenReturn(CallState.SIMULATED_RINGING);