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

Commit 4380a6ef authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Support dialing e-call based on dialing sim's emergency number list.

Support a carrier config for dialing an emergency call based on the
dialing sim's emergency number list.

When this config is enabled, we will only consider the dialed SIM's
emergency number list when placing an emergency call instead of the current
platform behavior of using the platform's combined list of known emergency
numbers across all SIMs.

Test: atest com.android.internal.telephony.GsmCdmaPhoneTest#testEmergencyCallAnySim
Test: atest com.android.internal.telephony.GsmCdmaPhoneTest#testNotEmergencyNumberOnDialedSim1
Test: atest com.android.internal.telephony.GsmCdmaPhoneTest#testNotEmergencyNumberOnDialedSim2
Bug: 203947159
Change-Id: I292d7f27b253f71066194e3f60bd7114e579c87c
parent b00d6547
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -1340,8 +1340,35 @@ public class GsmCdmaPhone extends Phone {
                    + possibleEmergencyNumber);
            dialString = possibleEmergencyNumber;
        }

        CarrierConfigManager configManager =
                (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
        PersistableBundle carrierConfig = configManager.getConfigForSubId(getSubId());
        boolean allowWpsOverIms = carrierConfig.getBoolean(
                CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL);
        boolean useOnlyDialedSimEccList = carrierConfig.getBoolean(
                CarrierConfigManager.KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL);


        TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
        boolean isEmergency = tm.isEmergencyNumber(dialString);
        boolean isEmergency;
        // Check if the carrier wants to treat a call as an emergency call based on its own list of
        // known emergency numbers.
        // useOnlyDialedSimEccList is false for the vast majority of carriers.  There are, however,
        // some carriers which do not want to handle dial requests for numbers which are in the
        // emergency number list on another SIM, but is not on theirs.  In this case we will use the
        // emergency number list for this carrier's SIM only.
        if (useOnlyDialedSimEccList) {
            isEmergency = getEmergencyNumberTracker().isEmergencyNumber(dialString,
                    true /* exactMatch */);
            logi("dial; isEmergency=" + isEmergency
                    + " (based on this phone only); globalIsEmergency="
                    + tm.isEmergencyNumber(dialString));
        } else {
            isEmergency = tm.isEmergencyNumber(dialString);
            logi("dial; isEmergency=" + isEmergency + " (based on all phones)");
        }

        /** Check if the call is Wireless Priority Service call */
        boolean isWpsCall = dialString != null ? (dialString.startsWith(PREFIX_WPS)
                || dialString.startsWith(PREFIX_WPS_CLIR_ACTIVATE)
@@ -1355,12 +1382,6 @@ public class GsmCdmaPhone extends Phone {

        Phone imsPhone = mImsPhone;

        CarrierConfigManager configManager =
                (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);

        boolean allowWpsOverIms = configManager.getConfigForSubId(getSubId())
                .getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL);

        boolean useImsForEmergency = isEmergency && useImsForEmergency();

        String dialPart = PhoneNumberUtils.extractNetworkPortionAlt(PhoneNumberUtils.
@@ -1374,7 +1395,8 @@ public class GsmCdmaPhone extends Phone {
                && (isWpsCall ? allowWpsOverIms : true);

        if (DBG) {
            logd("useImsForCall=" + useImsForCall
            logi("useImsForCall=" + useImsForCall
                    + ", useOnlyDialedSimEccList=" + useOnlyDialedSimEccList
                    + ", isEmergency=" + isEmergency
                    + ", useImsForEmergency=" + useImsForEmergency
                    + ", useImsForUt=" + useImsForUt
+6 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ import com.android.internal.telephony.dataconnection.DcTracker;
import com.android.internal.telephony.dataconnection.LinkBandwidthEstimator;
import com.android.internal.telephony.dataconnection.TransportManager;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
import com.android.internal.telephony.metrics.SmsStats;
import com.android.internal.telephony.metrics.VoiceCallSessionStats;
@@ -3952,6 +3953,11 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        return mImsPhone;
    }

    @VisibleForTesting
    public void setImsPhone(ImsPhone imsPhone) {
        mImsPhone = imsPhone;
    }

    /**
     * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI.
     * @param keyType whether the key is being used for WLAN or ePDG.
+89 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.nullable;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
@@ -52,6 +53,7 @@ import android.content.SharedPreferences;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.WorkSource;
import android.preference.PreferenceManager;
@@ -73,6 +75,7 @@ import android.testing.TestableLooper;

import androidx.test.filters.FlakyTest;

import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.test.SimulatedCommands;
import com.android.internal.telephony.test.SimulatedCommandsVerifier;
import com.android.internal.telephony.uicc.IccCardApplicationStatus;
@@ -99,6 +102,7 @@ import java.util.List;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class GsmCdmaPhoneTest extends TelephonyTest {
    private static final String TEST_EMERGENCY_NUMBER = "555";
    @Mock
    private Handler mTestHandler;
    @Mock
@@ -1651,4 +1655,89 @@ public class GsmCdmaPhoneTest extends TelephonyTest {

        assertEquals(false, mPhoneUT.isAllowedNetworkTypesLoadedFromDb());
    }

    /**
     * Verifies that an emergency call placed on a SIM which does NOT explicitly define a number as
     * an emergency call will still be placed as an emergency call.
     * @throws CallStateException
     */
    @Test
    public void testEmergencyCallAnySim() throws CallStateException {
        setupEmergencyCallScenario(false /* USE_ONLY_DIALED_SIM_ECC_LIST */,
                false /* isEmergencyOnDialedSim */);

        ArgumentCaptor<PhoneInternalInterface.DialArgs> dialArgsArgumentCaptor =
                ArgumentCaptor.forClass(PhoneInternalInterface.DialArgs.class);
        mPhoneUT.dial(TEST_EMERGENCY_NUMBER, new ImsPhone.ImsDialArgs.Builder().build());

        // Should have dialed out over IMS and should have specified that it is an emergency call
        verify(mImsPhone).dial(anyString(), dialArgsArgumentCaptor.capture());
        PhoneInternalInterface.DialArgs args = dialArgsArgumentCaptor.getValue();
        assertTrue(args.isEmergency);
    }

    /**
     * Tests the scenario where a number is dialed on a sim where it is NOT an emergency number,
     * but it IS an emergency number based on {@link TelephonyManager#isEmergencyNumber(String)},
     * and the carrier wants to ONLY use the dialed SIM's ECC list.
     * @throws CallStateException
     */
    @Test
    public void testNotEmergencyNumberOnDialedSim1() throws CallStateException {
        setupEmergencyCallScenario(true /* USE_ONLY_DIALED_SIM_ECC_LIST */,
                false /* isEmergencyOnDialedSim */);

        ArgumentCaptor<PhoneInternalInterface.DialArgs> dialArgsArgumentCaptor =
                ArgumentCaptor.forClass(PhoneInternalInterface.DialArgs.class);
        mPhoneUT.dial(TEST_EMERGENCY_NUMBER, new ImsPhone.ImsDialArgs.Builder().build());

        // Should have dialed out over IMS and should have specified that it is NOT an emergency
        // call
        verify(mImsPhone).dial(anyString(), dialArgsArgumentCaptor.capture());
        PhoneInternalInterface.DialArgs args = dialArgsArgumentCaptor.getValue();
        assertFalse(args.isEmergency);
    }

    /**
     * Tests the scenario where a number is dialed on a sim where it is NOT an emergency number,
     * but it IS an emergency number based on {@link TelephonyManager#isEmergencyNumber(String)},
     * and the carrier wants to use the global ECC list.
     * @throws CallStateException
     */
    @Test
    public void testNotEmergencyNumberOnDialedSim2() throws CallStateException {
        setupEmergencyCallScenario(false /* USE_ONLY_DIALED_SIM_ECC_LIST */,
                false /* isEmergencyOnDialedSim */);

        ArgumentCaptor<PhoneInternalInterface.DialArgs> dialArgsArgumentCaptor =
                ArgumentCaptor.forClass(PhoneInternalInterface.DialArgs.class);
        mPhoneUT.dial(TEST_EMERGENCY_NUMBER, new ImsPhone.ImsDialArgs.Builder().build());

        // Should have dialed out over IMS and should have specified that it is an emergency call
        verify(mImsPhone).dial(anyString(), dialArgsArgumentCaptor.capture());
        PhoneInternalInterface.DialArgs args = dialArgsArgumentCaptor.getValue();
        assertTrue(args.isEmergency);
    }

    private void setupEmergencyCallScenario(boolean isUsingOnlyDialedSim,
            boolean isEmergencyPerDialedSim) {
        PersistableBundle bundle = mContextFixture.getCarrierConfigBundle();
        bundle.putBoolean(CarrierConfigManager.KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL,
                isUsingOnlyDialedSim);
        bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true);
        doReturn(true).when(mImsPhone).isImsAvailable();
        doReturn(true).when(mImsManager).isVolteEnabledByPlatform();
        doReturn(true).when(mImsManager).isEnhanced4gLteModeSettingEnabledByUser();
        doReturn(true).when(mImsManager).isNonTtyOrTtyOnVolteEnabled();
        doReturn(true).when(mImsPhone).isVoiceOverCellularImsEnabled();
        ServiceState ss = mock(ServiceState.class);
        doReturn(ServiceState.STATE_IN_SERVICE).when(ss).getState();
        doReturn(ss).when(mImsPhone).getServiceState();

        doReturn(true).when(mTelephonyManager).isEmergencyNumber(anyString());
        doReturn(isEmergencyPerDialedSim).when(mEmergencyNumberTracker).isEmergencyNumber(
                anyString(), anyBoolean());

        mPhoneUT.setImsPhone(mImsPhone);
    }
}