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

Commit 9a48707c authored by Pranav Madapurmath's avatar Pranav Madapurmath
Browse files

Ignore max ringing failure for MT call on same number

For Fi, it's possible to sometimes receive two incoming calls at the
same time: one from Tycho over OTT Wifi and one from Telephony via the
mobile network. This can cause two missed call entries to show up since
the second call will automatically fail from the max ringing call
enforcement. Instead, we can cross-check the phone numbers as well as
the connection manager to see if we can ignore this check.

Bug: 414261900
Flag:
com.android.server.telecom.flags.allow_call_on_same_connection_mgr
Test: atest CallsManagerTest

Change-Id: Ieae905051e00b9b2228125ba46646e2b3d2d9742
parent 14c992eb
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -16,3 +16,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
@@ -1793,6 +1793,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()) {
@@ -1834,7 +1852,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();
@@ -3856,6 +3855,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);
    }