DSDA: Disconnect nonholdable calls with MT call

Ensures that we disconnect the non-holdable calls on one sim when we
receive an incoming call another sim. Previously, we would just
disconnect the active call but in a scenario where we have a HOLDING +
ACTIVE call plus a RINGING call (on another sim), we should also opt to
disconnect the held call as well. A good example of this is with
Verizon.

Bug: 392698669
Test: atest
CtsTelecomCujTestCases: CallSequencingManagedHoldRestrictionTest
Test: Manual verification with non-holdable sim to ensure that calls are
disconnected when receiving an incoming call on the other sim
Flag: com.android.server.telecom.flags.enable_call_sequencing

Change-Id: I6369cc2ca7a241cd5762bb3a1a3eb1bbabd52728
diff --git a/src/com/android/server/telecom/callsequencing/CallSequencingController.java b/src/com/android/server/telecom/callsequencing/CallSequencingController.java
index 713d155..dcc5ac4 100644
--- a/src/com/android/server/telecom/callsequencing/CallSequencingController.java
+++ b/src/com/android/server/telecom/callsequencing/CallSequencingController.java
@@ -62,6 +62,7 @@
 import com.android.server.telecom.metrics.TelecomMetricsController;
 import com.android.server.telecom.stats.CallFailureCause;
 
+import java.util.List;
 import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
@@ -343,8 +344,12 @@
                         return CompletableFuture.completedFuture(false);
                     } else {
                         if (isSequencingRequiredActiveAndCall) {
-                            return activeCall.disconnect("Active call disconnected in favor of"
-                                    + " new call.");
+                            // Disconnect all calls with the same phone account as the active call
+                            // as they do would not support holding.
+                            Log.i(this, "Disconnecting non-holdable calls from account (%s).",
+                                    activeCall.getTargetPhoneAccount());
+                            return disconnectAllCallsWithPhoneAccount(
+                                    activeCall.getTargetPhoneAccount());
                         } else {
                             Log.i(this, "holdActiveCallForNewCallWithSequencing: "
                                     + "allowing ConnectionService to determine how to handle "
@@ -895,6 +900,25 @@
                 && callToUnhold.getState() == CallState.ON_HOLD;
     }
 
+    private CompletableFuture<Boolean> disconnectAllCallsWithPhoneAccount(
+            PhoneAccountHandle handle) {
+        CompletableFuture<Boolean> disconnectFuture = CompletableFuture.completedFuture(true);
+        List<Call> calls = mCallsManager.getCalls().stream()
+                .filter(c -> c.getTargetPhoneAccount().equals(handle)).toList();
+        for (Call call: calls) {
+            // Wait for all disconnects before we accept the new call.
+            disconnectFuture = disconnectFuture.thenComposeAsync((result) -> {
+                if (!result) {
+                    Log.i(this, "disconnectAllCallsWithPhoneAccount: "
+                            + "Failed to disconnect %s.", call);
+                }
+                return call.disconnect("Un-holdable call " + call + " disconnected "
+                        + "in favor of new call.");
+            }, new LoggedHandlerExecutor(mHandler, "CSC.dACWPA", mCallsManager.getLock()));
+        }
+        return disconnectFuture;
+    }
+
     /**
      * Generic helper to log the result of the {@link CompletableFuture} containing the transactions
      * that are being processed in the context of call sequencing.
diff --git a/tests/src/com/android/server/telecom/tests/CallSequencingTests.java b/tests/src/com/android/server/telecom/tests/CallSequencingTests.java
index 64d2d7d..9cfc95c 100644
--- a/tests/src/com/android/server/telecom/tests/CallSequencingTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallSequencingTests.java
@@ -18,7 +18,6 @@
 
 import static com.android.server.telecom.CallsManager.CALL_FILTER_ALL;
 import static com.android.server.telecom.CallsManager.ONGOING_CALL_STATES;
-import static com.android.server.telecom.UserUtil.showErrorDialogForRestrictedOutgoingCall;
 
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.TestCase.fail;
@@ -78,8 +77,8 @@
 import org.junit.runners.JUnit4;
 import org.mockito.Mock;
 
-import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
@@ -342,6 +341,7 @@
     public void testHoldCallForNewCall_DoesNotSupportHold_Disconnect() {
         setPhoneAccounts(mNewCall, mActiveCall, false);
         setActiveCallFocus(mActiveCall);
+        when(mCallsManager.getCalls()).thenReturn(Collections.singletonList(mActiveCall));
         when(mCallsManager.canHold(mActiveCall)).thenReturn(false);
         when(mCallsManager.supportsHold(mActiveCall)).thenReturn(false);
         when(mActiveCall.disconnect(anyString())).thenReturn(