Loading src/java/com/android/internal/telephony/GsmCdmaPhone.java +30 −8 Original line number Diff line number Diff line Loading @@ -1357,8 +1357,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) Loading @@ -1372,12 +1399,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. Loading @@ -1391,7 +1412,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 Loading src/java/com/android/internal/telephony/Phone.java +6 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,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; Loading Loading @@ -3969,6 +3970,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. Loading tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading Loading @@ -1654,4 +1658,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); } } Loading
src/java/com/android/internal/telephony/GsmCdmaPhone.java +30 −8 Original line number Diff line number Diff line Loading @@ -1357,8 +1357,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) Loading @@ -1372,12 +1399,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. Loading @@ -1391,7 +1412,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 Loading
src/java/com/android/internal/telephony/Phone.java +6 −0 Original line number Diff line number Diff line Loading @@ -82,6 +82,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; Loading Loading @@ -3969,6 +3970,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. Loading
tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java +89 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -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; Loading @@ -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 Loading Loading @@ -1654,4 +1658,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); } }