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

Commit 4b49bc1d authored by Pranav Madapurmath's avatar Pranav Madapurmath
Browse files

DSDA: Set simultaneous call type for metrics

Initial support for including metrics for call sequencing which will
track the simultaneous call type for each call. The types are based on a
priority which will be dynamically updated based on the newly added
calls. These will only be updated if the new simultaneous call type
priority is higher than the one already set for the call so that we can
have a better understanding on the metric side where sequencing may have
applied, if it did.

Bug: 384949208
Flag: com.android.server.telecom.flags.enable_call_sequencing
Test: atest CallsManagerTest#testSimultaneousCallType
Change-Id: I1251aac307f229d115e566e7161ef0051c1f22ae
parent 321a6ac4
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -131,10 +131,20 @@ public class Call implements CreateConnectionResponse, EventManager.Loggable,

    private static final char NO_DTMF_TONE = '\0';

    /**
     * The following simultaneous call types will be set on each call on creation and may be updated
     * according to priority level. CALL_DIRECTION_DUAL_DIFF_ACCOUNT holds the highest priority.
     * So if for example, a call is created with CALL_DIRECTION_DUAL_SAME_ACCOUNT, it can be
     * upgraded to CALL_DIRECTION_DUAL_DIFF_ACCOUNT if another call is added with a different phone
     * account.
     */
    public static final int CALL_SIMULTANEOUS_UNKNOWN = 0;
    public static final int CALL_SIMULTANEOUS_SINGLE = 1;
    public static final int CALL_DIRECTION_DUAL_SAME_ACCOUNT = 2;
    public static final int CALL_DIRECTION_DUAL_DIFF_ACCOUNT = 3;
    // Only used if simultaneous calling is not available
    public static final int CALL_SIMULTANEOUS_DISABLED_SAME_ACCOUNT = 1;
    // Only used if simultaneous calling is not available
    public static final int CALL_SIMULTANEOUS_DISABLED_DIFF_ACCOUNT = 2;
    public static final int CALL_DIRECTION_DUAL_SAME_ACCOUNT = 3;
    public static final int CALL_DIRECTION_DUAL_DIFF_ACCOUNT = 4;

    /**
     * Listener for CallState changes which can be leveraged by a Transaction.
+9 −1
Original line number Diff line number Diff line
@@ -511,7 +511,7 @@ public class CallsManager extends Call.ListenerBase
    private final UserManager mUserManager;
    private final CallStreamingNotification mCallStreamingNotification;
    private final BlockedNumbersManager mBlockedNumbersManager;
    private final CallsManagerCallSequencingAdapter mCallSequencingAdapter;
    private CallsManagerCallSequencingAdapter mCallSequencingAdapter;
    private final FeatureFlags mFeatureFlags;
    private final com.android.internal.telephony.flags.FeatureFlags mTelephonyFeatureFlags;

@@ -4864,6 +4864,9 @@ public class CallsManager extends Call.ListenerBase
        Log.i(this, "addCall(%s)", call);
        call.addListener(this);
        mCalls.add(call);
        // Reprocess the simultaneous call types for all the tracked calls after having added a new
        // call.
        mCallSequencingAdapter.processSimultaneousCallTypes(mCalls);
        mSelfManagedCallsBeingSetup.remove(call);

        // Specifies the time telecom finished routing the call. This is used by the dialer for
@@ -7172,6 +7175,11 @@ public class CallsManager extends Call.ListenerBase
        return mCallSequencingAdapter;
    }

    @VisibleForTesting
    public void setCallSequencingAdapter(CallsManagerCallSequencingAdapter adapter) {
        mCallSequencingAdapter = adapter;
    }

    public void waitForAudioToUpdate(boolean expectActive) {
        Log.i(this, "waitForAudioToUpdate");
        if (mFeatureFlags.useRefactoredAudioRouteSwitching()) {
+50 −4
Original line number Diff line number Diff line
@@ -16,9 +16,6 @@

package com.android.server.telecom.callsequencing;

import static com.android.server.telecom.CallsManager.CALL_FILTER_ALL;
import static com.android.server.telecom.CallsManager.ONGOING_CALL_STATES;

import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
@@ -26,8 +23,8 @@ import android.os.OutcomeReceiver;
import android.telecom.CallAttributes;
import android.telecom.CallException;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;

import com.android.server.telecom.Call;
import com.android.server.telecom.CallAudioManager;
@@ -37,6 +34,9 @@ import com.android.server.telecom.callsequencing.voip.OutgoingCallTransaction;
import com.android.server.telecom.flags.FeatureFlags;
import com.android.server.telecom.R;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

/**
@@ -309,6 +309,52 @@ public class CallsManagerCallSequencingAdapter {
        return !mIsCallSequencingEnabled || !mSequencingController.hasMmiCodeRestriction(call);
    }

    /**
     * Processes the simultaneous call type for the ongoing calls that are being tracked in
     * {@link CallsManager}. The current call's simultaneous call type will be overridden only if
     * it's current type priority is lower than the one being set.
     * @param calls The list of the currently tracked calls.
     */
    public void processSimultaneousCallTypes(Collection<Call> calls) {
        // Metrics should only be tracked when call sequencing flag is enabled.
        if (!mIsCallSequencingEnabled) {
            return;
        }
        // Device should have simultaneous calling supported.
        boolean isSimultaneousCallingSupported = mCallsManager.isDsdaCallingPossible();
        int type;
        // Go through the available calls' phone accounts to determine how many different ones
        // are being used.
        Set<PhoneAccountHandle> handles = new HashSet<>();
        for (Call call : calls) {
            if (call.getTargetPhoneAccount() != null) {
                handles.add(call.getTargetPhoneAccount());
            }
            // No need to proceed further given that we already know there is more than 1 phone
            // account being used.
            if (handles.size() > 1) {
                break;
            }
        }
        type = handles.size() > 1
                ? (isSimultaneousCallingSupported ? Call.CALL_DIRECTION_DUAL_DIFF_ACCOUNT
                        : Call.CALL_SIMULTANEOUS_DISABLED_DIFF_ACCOUNT)
                : (isSimultaneousCallingSupported ? Call.CALL_DIRECTION_DUAL_SAME_ACCOUNT
                        : Call.CALL_SIMULTANEOUS_DISABLED_SAME_ACCOUNT);

        Log.i(this, "processSimultaneousCallTypes: the calculated simultaneous call type for "
                + "the tracked calls is [%d]", type);
        calls.forEach(c -> {
            // If the current call's simultaneous call type priority is lower than the one being
            // set, then let the override occur. Otherwise, ignore it.
            if (c.getSimultaneousType() < type) {
                Log.i(this, "processSimultaneousCallTypes: overriding simultaneous call type for "
                        + "call (%s). Previous value: %d", c.getId(), c.getSimultaneousType());
                c.setSimultaneousType(type);
            }
        });
    }

    public Handler getHandler() {
        return mHandler;
    }
+48 −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.callsequencing.CallSequencingController;
import com.android.server.telecom.callsequencing.CallsManagerCallSequencingAdapter;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceFocusManager;
@@ -3777,6 +3778,53 @@ public class CallsManagerTest extends TelecomTestCase {
        inOrder.verify(call).setState(eq(CallState.RINGING), anyString());
    }

    @SmallTest
    @Test
    public void testSimultaneousCallType() {
        when(mFeatureFlags.enableCallSequencing()).thenReturn(true);
        // Setup CallsManagerCallSequencingAdapter
        CallSequencingController sequencingController = mock(CallSequencingController.class);
        CallAudioManager callAudioManager = mock(CallAudioManager.class);
        CallsManagerCallSequencingAdapter adapter = new CallsManagerCallSequencingAdapter(
                mCallsManager, mContext, sequencingController, callAudioManager, mFeatureFlags);
        mCallsManager.setCallSequencingAdapter(adapter);
        // Explicitly disable simultaneous calling
        TelephonyManager mockTelephonyManager = mComponentContextFixture.getTelephonyManager();
        when(mockTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims()).thenReturn(1);

        Call call1 = addSpyCall(SIM_1_HANDLE, CallState.ACTIVE);
        assertEquals(call1.getSimultaneousType(), Call.CALL_SIMULTANEOUS_DISABLED_SAME_ACCOUNT);

        // Emulate adding another concurrent call on a different call when simultaneous calling
        // isn't supported by the device.
        Call call2 = addSpyCall(SIM_2_HANDLE, CallState.ON_HOLD);
        assertEquals(call1.getSimultaneousType(), Call.CALL_SIMULTANEOUS_DISABLED_DIFF_ACCOUNT);
        assertEquals(call2.getSimultaneousType(), Call.CALL_SIMULTANEOUS_DISABLED_DIFF_ACCOUNT);
        mCallsManager.removeCall(call2);

        // Now enable simultaneous calling and verify the updated call simultaneous types when
        // adding another call.
        when(mockTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims()).thenReturn(2);
        call2 = addSpyCall(SIM_1_HANDLE, CallState.ON_HOLD);
        assertEquals(call1.getSimultaneousType(), Call.CALL_DIRECTION_DUAL_SAME_ACCOUNT);
        assertEquals(call2.getSimultaneousType(), Call.CALL_DIRECTION_DUAL_SAME_ACCOUNT);

        // Add a new call and remove the held one (emulation).
        mCallsManager.removeCall(call2);
        // Verify that the simultaneous call type priority of the 1st call has been upgraded.
        Call call3 = addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
        assertEquals(call1.getSimultaneousType(), Call.CALL_DIRECTION_DUAL_DIFF_ACCOUNT);
        assertEquals(call3.getSimultaneousType(), Call.CALL_DIRECTION_DUAL_DIFF_ACCOUNT);

        // Remove the first call and add another call with the same handle as the third call.
        mCallsManager.removeCall(call1);
        Call call4 = addSpyCall(SIM_2_HANDLE, CallState.ON_HOLD);
        // Verify that call3's priority remains unchanged but call4's priority is
        // Call.CALL_DIRECTION_DUAL_SAME_ACCOUNT.
        assertEquals(call3.getSimultaneousType(), Call.CALL_DIRECTION_DUAL_DIFF_ACCOUNT);
        assertEquals(call4.getSimultaneousType(), Call.CALL_DIRECTION_DUAL_SAME_ACCOUNT);
    }

    @SmallTest
    @Test
    public void testPendingAccountSelectionNotClearedWithNewCall() {