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

Commit 6ff39615 authored by Pranav Madapurmath's avatar Pranav Madapurmath Committed by Android (Google) Code Review
Browse files

Merge "Ignore max ringing failure for MT call on same number" into main

parents 263c41c1 9a48707c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -8,3 +8,14 @@ flag {
  description: "Enables simultaneous call sequencing for SIM PhoneAccounts"
  bug: "327038818"
}

# OWNER=pmadapurmath TARGET=25Q3
flag {
  name: "allow_call_on_same_connection_mgr"
  namespace: "telecom"
  description: "If two incoming calls are received at the same time from the same connection service, allow the CS to handle the second call."
  bug: "414261900"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}
+20 −1
Original line number Diff line number Diff line
@@ -1784,6 +1784,24 @@ public class CallsManager extends Call.ListenerBase
                    : mUserManager.isQuietModeEnabled(call.getAssociatedUser());
        }

        boolean ignoreIncomingCallFailureOnSameNumber = false;
        if (hasMaximumManagedRingingCalls(call)) {
            Call ringingCall = getRingingOrSimulatedRingingCall();
            PhoneAccountHandle connectionMgr = mPhoneAccountRegistrar.getSimCallManagerFromCall(
                    call);
            // Check if the new incoming call is using the same connection mgr with the already
            // tracked ringing call. This can happen in a scenario where two incoming calls are
            // received on Fi: one from Tycho (over WiFi) and from Telephony via the mobile network.
            // In this case, we should allow the new call to go through instead of failing it and
            // logging it. We are refraining from doing a phone number check as it's possible that
            // Fi is using shadow numbers.
            if (mFeatureFlags.allowCallOnSameConnectionMgr() && ringingCall != null
                    && connectionMgr != null && Objects.equals(connectionMgr,
                    ringingCall.getConnectionManagerPhoneAccount())) {
                ignoreIncomingCallFailureOnSameNumber = true;
            }
        }

        // We should always allow emergency calls and also allow non-emergency calls when ECBM
        // is active for the phone account.
        if (isCallHiddenFromProfile && !call.isEmergencyCall() && !call.isInECBM()) {
@@ -1825,7 +1843,8 @@ public class CallsManager extends Call.ListenerBase
            } else {
                notifyCreateConnectionFailed(phoneAccountHandle, call);
            }
        } else if (mFeatureFlags.enableCallSequencing() && (hasMaximumManagedRingingCalls(call)
        } else if (mFeatureFlags.enableCallSequencing()
                && ((hasMaximumManagedRingingCalls(call) && !ignoreIncomingCallFailureOnSameNumber)
                || hasMaximumManagedDialingCalls(call))) {
            // Fail incoming call if there's already a ringing or dialing call present.
            boolean maxRinging = hasMaximumManagedRingingCalls(call);
+37 −5
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.telecom.tests;

import static android.provider.CallLog.Calls.MISSED_REASON_NOT_MISSED;
import static android.provider.CallLog.Calls.USER_MISSED_NOT_RUNNING;

import static junit.framework.Assert.assertNotNull;
@@ -51,7 +52,6 @@ import static java.lang.Thread.sleep;

import android.Manifest;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -83,7 +83,6 @@ import android.telephony.PhoneCapability;
import android.telephony.TelephonyManager;
import android.util.ArraySet;
import android.util.Pair;
import android.widget.Toast;

import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
@@ -146,8 +145,6 @@ import com.android.server.telecom.ui.DisconnectedCallNotifier;
import com.android.server.telecom.ui.ToastFactory;
import com.android.server.telecom.callsequencing.TransactionManager;

import com.google.common.base.Objects;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -170,7 +167,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@RunWith(JUnit4.class)
public class CallsManagerTest extends TelecomTestCase {
@@ -262,6 +258,8 @@ public class CallsManagerTest extends TelecomTestCase {
    private static final Uri TEST_ADDRESS = Uri.parse("tel:555-1212");
    private static final Uri TEST_ADDRESS2 = Uri.parse("tel:555-1213");
    private static final Uri TEST_ADDRESS3 = Uri.parse("tel:555-1214");

    private static final String TEST_NUMBER = "1234567890";
    private static final Map<Uri, PhoneAccountHandle> CONTACT_PREFERRED_ACCOUNT = Map.of(
            TEST_ADDRESS2, SIM_1_HANDLE,
            TEST_ADDRESS3, SIM_2_HANDLE);
@@ -773,6 +771,7 @@ public class CallsManagerTest extends TelecomTestCase {
            Uri handle = invocation.getArgument(0);
            CallerInfoLookupHelper.OnQueryCompleteListener listener = invocation.getArgument(1);
            CallerInfo info = new CallerInfo();
            info.setPhoneNumber(TEST_NUMBER);
            if (CONTACT_PREFERRED_ACCOUNT.get(handle) != null) {
                PhoneAccountHandle pah = CONTACT_PREFERRED_ACCOUNT.get(handle);
                info.preferredPhoneAccountComponent = pah.getComponentName();
@@ -3855,6 +3854,39 @@ public class CallsManagerTest extends TelecomTestCase {
        assertTrue(mCallsManager.getPendingAccountSelection().containsKey(pendingCall.getId()));
    }

    @SmallTest
    @Test
    public void testIgnoreMaxRingingCallOnSameNumber() {
        when(mFeatureFlags.enableCallSequencing()).thenReturn(true);
        when(mFeatureFlags.allowCallOnSameConnectionMgr()).thenReturn(true);
        setupCallerInfoLookupHelper();
        ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
        doReturn(SIM_1_HANDLE.getComponentName()).when(service).getComponentName();
        mCallsManager.addConnectionServiceRepositoryCache(SIM_1_HANDLE.getComponentName(),
                SIM_1_HANDLE.getUserHandle(), service);
        when(mPhoneAccountRegistrar.phoneAccountRequiresBindPermission(
                any(PhoneAccountHandle.class))).thenReturn(true);

        // WHEN
        Call existingIncomingCall = createCall(SIM_2_HANDLE, CallState.RINGING);
        mCallsManager.addCall(existingIncomingCall);
        PhoneAccountHandle connectionMgr = mock(PhoneAccountHandle.class);
        existingIncomingCall.setConnectionManagerPhoneAccount(connectionMgr);
        when(mPhoneAccountRegistrar.getSimCallManagerFromCall(any(Call.class)))
                .thenReturn(connectionMgr);
        when(mMockCurrentUserManager.isAdminUser()).thenReturn(true);

        // THEN, add a new incoming call with the same number as the 1st call
        Bundle extras = new Bundle();
        extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, TEST_ADDRESS);
        Call newCall = mCallsManager.processIncomingCallIntent(SIM_2_HANDLE, extras, false);
        // Verify we don't mark the call as auto missed and that the connection doesn't fail
        // locally.
        assertEquals(existingIncomingCall, mCallsManager.getRingingOrSimulatedRingingCall());
        assertEquals(newCall.getMissedReason(), MISSED_REASON_NOT_MISSED);
        verify(service, never()).createConnectionFailed(any());
    }

    private Call addSpyCall() {
        return addSpyCall(SIM_2_HANDLE, CallState.ACTIVE);
    }