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

Commit 67eefb16 authored by Thomas Stuart's avatar Thomas Stuart
Browse files

fix abort call not informing clients

A client reported that after a call was aborted, no signal was given
to the application.

Upon investigation, this is due to an edge case where the callback
is not called.

This change ensures all call states will receive the onDisconnected
callback

Flag: com.android.server.telecom.flags.echo_abort_transactional_outgoing
Bug: 354122175
Test: unit
Change-Id: I885d5f70db336931c14c0beaf0c889dee62f4376
parent cab60804
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -86,3 +86,15 @@ flag {
      purpose: PURPOSE_BUGFIX
    }
}

# OWNER=tjstuart TARGET=25Q4
flag {
  name: "echo_abort_transactional_outgoing"
  namespace: "telecom"
  description: "Fixes bug where clients are not informed of aborted outgoing calls"
  bug: "354122175"
  metadata {
      purpose: PURPOSE_BUGFIX
    }
}
+7 −2
Original line number Diff line number Diff line
@@ -2881,12 +2881,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT ||
                mState == CallState.CONNECTING) {
            Log.i(this, "disconnect: Aborting call %s", getId());
            abort(disconnectionTimeout);
            if (mFlags.enableCallSequencing()) {
                disconnectFutureHandler = awaitCallStateChangeAndMaybeDisconnectCall(
                        false /* shouldDisconnectUponTimeout */, "disconnect",
                        CallState.DISCONNECTED, CallState.ABORTED);
            }
            abort(disconnectionTimeout);
        } else if (mState != CallState.ABORTED && mState != CallState.DISCONNECTED) {
            if (mState == CallState.AUDIO_PROCESSING && !hasGoneActiveBefore()) {
                setOverrideDisconnectCauseCode(new DisconnectCause(DisconnectCause.REJECTED));
@@ -2924,7 +2924,12 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,
        if (mCreateConnectionProcessor != null &&
                !mCreateConnectionProcessor.isProcessingComplete()) {
            mCreateConnectionProcessor.abort();
        } else if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT
        } else if (mFlags.echoAbortTransactionalOutgoing() && mIsTransactionalCall) {
            CompletableFuture<Boolean> wasCompleted = mTransactionalService.onDisconnect(this,
                    new DisconnectCause(DisconnectCause.CANCELED));
            Log.d(this, "abort: wasTransactionCompleted=[%b", wasCompleted);
        }
        else if (mState == CallState.NEW || mState == CallState.SELECT_PHONE_ACCOUNT
                || mState == CallState.CONNECTING) {
            if (disconnectionTimeout > 0) {
                // If the cancelation was from NEW_OUTGOING_CALL with a timeout of > 0
+24 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ import com.android.server.telecom.CallEndpointControllerFactory;
import com.android.server.telecom.CallState;
import com.android.server.telecom.CallerInfoLookupHelper;
import com.android.server.telecom.CallsManager;
import com.android.server.telecom.TransactionalServiceWrapper;
import com.android.server.telecom.callsequencing.CallSequencingController;
import com.android.server.telecom.callsequencing.CallsManagerCallSequencingAdapter;
import com.android.server.telecom.ClockProxy;
@@ -2002,6 +2003,29 @@ public class CallsManagerTest extends TelecomTestCase {
        verify(ringingCall).reject(anyBoolean(), any(), any());
    }

    @SmallTest
    @Test
    public void testAbortIsPropagatedToClient() {
        // GIVEN
        DisconnectCause abortCause = new DisconnectCause(DisconnectCause.CANCELED);
        TransactionalServiceWrapper tsw = mock(TransactionalServiceWrapper.class);
        Call connectingCall = addSpyCall(VOIP_1_HANDLE, CallState.CONNECTING);
        connectingCall.setTransactionServiceWrapper(tsw);
        connectingCall.setIsTransactionalCall(true);

        // WHEN
        when(mFeatureFlags.echoAbortTransactionalOutgoing()).thenReturn(true);
        doReturn(true).when(connectingCall).can(Connection.CAPABILITY_HOLD);
        connectingCall.disconnect(0, abortCause.getReason());

        // THEN
        assertTrue(connectingCall.isLocallyDisconnecting());
        TransactionalServiceWrapper service = connectingCall.getTransactionServiceWrapper();
        assertNotNull(service);
        verify(service).onDisconnect(eq(connectingCall), eq(abortCause));
    }


    /**
     * Verifies that an anomaly report is triggered when a stuck/zombie call is found and force
     * disconnected when making room for an outgoing call.