Loading src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java +10 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.os.SystemProperties; import android.telephony.DomainSelectionService; import android.text.TextUtils; import android.util.IndentingPrintWriter; Loading @@ -34,6 +35,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.flags.Flags; import com.android.internal.telephony.util.TelephonyUtils; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -48,6 +50,10 @@ public class DomainSelectionResolver { @VisibleForTesting protected static final String PACKAGE_NAME_NONE = "none"; private static final String TAG = DomainSelectionResolver.class.getSimpleName(); private static final boolean DBG = TelephonyUtils.IS_DEBUGGABLE; /** For test purpose only with userdebug release */ private static final String PROP_DISABLE_DOMAIN_SELECTION = "telephony.test.disable_domain_selection"; private static DomainSelectionResolver sInstance = null; /** Loading Loading @@ -132,6 +138,10 @@ public class DomainSelectionResolver { * {@code false} otherwise. */ public boolean isDomainSelectionSupported() { if (DBG && SystemProperties.getBoolean(PROP_DISABLE_DOMAIN_SELECTION, false)) { logi("Disabled for test"); return false; } return mDefaultComponentName != null && PhoneFactory.getDefaultPhone() .getHalVersion(HAL_SERVICE_NETWORK).greaterOrEqual(RADIO_HAL_VERSION_2_1); } Loading src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java +22 −7 Original line number Diff line number Diff line Loading @@ -84,7 +84,9 @@ public class EmergencyStateTracker { * Timeout before we continue with the emergency call without waiting for DDS switch response * from the modem. */ private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1000; private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1 * 1000; @VisibleForTesting public static final int DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS = 3 * 1000; /** Default value for if Emergency Callback Mode is supported. */ private static final boolean DEFAULT_EMERGENCY_CALLBACK_MODE_SUPPORTED = true; /** Default Emergency Callback Mode exit timeout value. */ Loading Loading @@ -1227,6 +1229,11 @@ public class EmergencyStateTracker { mRadioOnHelper = new RadioOnHelper(mContext); } final Phone phoneForEmergency = phone; final String expectedCallId = mOngoingCallId; final int waitForInServiceTimeout = needToTurnOnRadio ? DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS : 0; Rlog.i(TAG, "turnOnRadioAndSwitchDds: timeout=" + waitForInServiceTimeout); mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() { @Override public void onComplete(RadioOnStateListener listener, boolean isRadioReady) { Loading @@ -1241,25 +1248,33 @@ public class EmergencyStateTracker { completeEmergencyMode(emergencyType, DisconnectCause.POWER_OFF); } } else { if (!Objects.equals(mOngoingCallId, expectedCallId)) { Rlog.i(TAG, "onComplete " + expectedCallId + " canceled."); return; } switchDdsAndSetEmergencyMode(phone, emergencyType); } } @Override public boolean isOkToCall(Phone phone, int serviceState, boolean imsVoiceCapable) { // We currently only look to make sure that the radio is on before dialing. We // should be able to make emergency calls at any time after the radio has been // powered on and isn't in the UNAVAILABLE state, even if it is reporting the // OUT_OF_SERVICE state. // Wait for normal service state or timeout if required. if (phone == phoneForEmergency && waitForInServiceTimeout > 0 && serviceState != ServiceState.STATE_IN_SERVICE) { return false; } return phone.getServiceStateTracker().isRadioOn() && !satelliteController.isSatelliteEnabled(); } @Override public boolean onTimeout(Phone phone, int serviceState, boolean imsVoiceCapable) { return true; // onTimeout shall be called only with the Phone for emergency return phone.getServiceStateTracker().isRadioOn() && !satelliteController.isSatelliteEnabled(); } }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, 0); }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout); } else { switchDdsAndSetEmergencyMode(phone, emergencyType); } Loading src/java/com/android/internal/telephony/emergency/RadioOnHelper.java +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ public class RadioOnHelper implements RadioOnStateListener.Callback { continue; } int timeoutCallbackInterval = (forEmergencyCall && phone == phoneForEmergencyCall) int timeoutCallbackInterval = (phone == phoneForEmergencyCall) ? emergencyTimeoutIntervalMillis : 0; mInProgressListeners.add(mListeners.get(i)); mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall, forEmergencyCall Loading tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java +52 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME; import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK; import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WLAN; import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WWAN; import static com.android.internal.telephony.emergency.EmergencyStateTracker.DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -160,13 +161,61 @@ public class EmergencyStateTrackerTest extends TelephonyTest { ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor .forClass(RadioOnStateListener.Callback.class); verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone), eq(false), eq(0)); // isOkToCall() should return true once radio is on eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS)); // isOkToCall() should return true when IN_SERVICE state assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); when(mSST.isRadioOn()).thenReturn(true); assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); assertTrue(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false)); // Once radio on is complete, trigger delay dial callback.getValue().onComplete(null, true); ArgumentCaptor<Consumer<Boolean>> completeConsumer = ArgumentCaptor .forClass(Consumer.class); verify(spyEst).switchDdsDelayed(eq(testPhone), completeConsumer.capture()); verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(testPhone.getPhoneId()), eq(150) /* extensionTime */, any()); // After dds switch completes successfully, set emergency mode completeConsumer.getValue().accept(true); verify(testPhone).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any()); } /** * Test that the EmergencyStateTracker turns on radio, performs a DDS switch and sets emergency * mode switch when we are not roaming and the carrier only supports SUPL over the data plane. */ @Test @SmallTest public void startEmergencyCall_radioOff_turnOnRadioTimeoutSwitchDdsAndSetEmergencyMode() { EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker( true /* isSuplDdsSwitchRequiredForEmergencyCall */); // Create test Phones and set radio off Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */, false /* isRadioOn */); setConfigForDdsSwitch(testPhone, null, CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY, "150"); // Spy is used to capture consumer in delayDialForDdsSwitch EmergencyStateTracker spyEst = spy(emergencyStateTracker); CompletableFuture<Integer> unused = spyEst.startEmergencyCall(testPhone, TEST_CALL_ID, false); // startEmergencyCall should trigger radio on ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor .forClass(RadioOnStateListener.Callback.class); verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone), eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS)); // onTimeout should return true when radion on assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); assertFalse(callback.getValue() .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); when(mSST.isRadioOn()).thenReturn(true); assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); assertTrue(callback.getValue() .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); // Once radio on is complete, trigger delay dial callback.getValue().onComplete(null, true); ArgumentCaptor<Consumer<Boolean>> completeConsumer = ArgumentCaptor Loading Loading @@ -199,7 +248,7 @@ public class EmergencyStateTrackerTest extends TelephonyTest { ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor .forClass(RadioOnStateListener.Callback.class); verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone), eq(false), eq(0)); eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS)); // Verify future completes with DisconnectCause.POWER_OFF if radio not ready CompletableFuture<Void> unused = future.thenAccept((result) -> { assertEquals((Integer) result, (Integer) DisconnectCause.POWER_OFF); Loading Loading
src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java +10 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; import android.os.SystemProperties; import android.telephony.DomainSelectionService; import android.text.TextUtils; import android.util.IndentingPrintWriter; Loading @@ -34,6 +35,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.PhoneFactory; import com.android.internal.telephony.flags.Flags; import com.android.internal.telephony.util.TelephonyUtils; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -48,6 +50,10 @@ public class DomainSelectionResolver { @VisibleForTesting protected static final String PACKAGE_NAME_NONE = "none"; private static final String TAG = DomainSelectionResolver.class.getSimpleName(); private static final boolean DBG = TelephonyUtils.IS_DEBUGGABLE; /** For test purpose only with userdebug release */ private static final String PROP_DISABLE_DOMAIN_SELECTION = "telephony.test.disable_domain_selection"; private static DomainSelectionResolver sInstance = null; /** Loading Loading @@ -132,6 +138,10 @@ public class DomainSelectionResolver { * {@code false} otherwise. */ public boolean isDomainSelectionSupported() { if (DBG && SystemProperties.getBoolean(PROP_DISABLE_DOMAIN_SELECTION, false)) { logi("Disabled for test"); return false; } return mDefaultComponentName != null && PhoneFactory.getDefaultPhone() .getHalVersion(HAL_SERVICE_NETWORK).greaterOrEqual(RADIO_HAL_VERSION_2_1); } Loading
src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java +22 −7 Original line number Diff line number Diff line Loading @@ -84,7 +84,9 @@ public class EmergencyStateTracker { * Timeout before we continue with the emergency call without waiting for DDS switch response * from the modem. */ private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1000; private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1 * 1000; @VisibleForTesting public static final int DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS = 3 * 1000; /** Default value for if Emergency Callback Mode is supported. */ private static final boolean DEFAULT_EMERGENCY_CALLBACK_MODE_SUPPORTED = true; /** Default Emergency Callback Mode exit timeout value. */ Loading Loading @@ -1227,6 +1229,11 @@ public class EmergencyStateTracker { mRadioOnHelper = new RadioOnHelper(mContext); } final Phone phoneForEmergency = phone; final String expectedCallId = mOngoingCallId; final int waitForInServiceTimeout = needToTurnOnRadio ? DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS : 0; Rlog.i(TAG, "turnOnRadioAndSwitchDds: timeout=" + waitForInServiceTimeout); mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() { @Override public void onComplete(RadioOnStateListener listener, boolean isRadioReady) { Loading @@ -1241,25 +1248,33 @@ public class EmergencyStateTracker { completeEmergencyMode(emergencyType, DisconnectCause.POWER_OFF); } } else { if (!Objects.equals(mOngoingCallId, expectedCallId)) { Rlog.i(TAG, "onComplete " + expectedCallId + " canceled."); return; } switchDdsAndSetEmergencyMode(phone, emergencyType); } } @Override public boolean isOkToCall(Phone phone, int serviceState, boolean imsVoiceCapable) { // We currently only look to make sure that the radio is on before dialing. We // should be able to make emergency calls at any time after the radio has been // powered on and isn't in the UNAVAILABLE state, even if it is reporting the // OUT_OF_SERVICE state. // Wait for normal service state or timeout if required. if (phone == phoneForEmergency && waitForInServiceTimeout > 0 && serviceState != ServiceState.STATE_IN_SERVICE) { return false; } return phone.getServiceStateTracker().isRadioOn() && !satelliteController.isSatelliteEnabled(); } @Override public boolean onTimeout(Phone phone, int serviceState, boolean imsVoiceCapable) { return true; // onTimeout shall be called only with the Phone for emergency return phone.getServiceStateTracker().isRadioOn() && !satelliteController.isSatelliteEnabled(); } }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, 0); }, !isTestEmergencyNumber, phone, isTestEmergencyNumber, waitForInServiceTimeout); } else { switchDdsAndSetEmergencyMode(phone, emergencyType); } Loading
src/java/com/android/internal/telephony/emergency/RadioOnHelper.java +1 −1 Original line number Diff line number Diff line Loading @@ -96,7 +96,7 @@ public class RadioOnHelper implements RadioOnStateListener.Callback { continue; } int timeoutCallbackInterval = (forEmergencyCall && phone == phoneForEmergencyCall) int timeoutCallbackInterval = (phone == phoneForEmergencyCall) ? emergencyTimeoutIntervalMillis : 0; mInProgressListeners.add(mListeners.get(i)); mListeners.get(i).waitForRadioOn(phone, this, forEmergencyCall, forEmergencyCall Loading
tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java +52 −3 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME; import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK; import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WLAN; import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WWAN; import static com.android.internal.telephony.emergency.EmergencyStateTracker.DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; Loading Loading @@ -160,13 +161,61 @@ public class EmergencyStateTrackerTest extends TelephonyTest { ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor .forClass(RadioOnStateListener.Callback.class); verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone), eq(false), eq(0)); // isOkToCall() should return true once radio is on eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS)); // isOkToCall() should return true when IN_SERVICE state assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); when(mSST.isRadioOn()).thenReturn(true); assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); assertTrue(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false)); // Once radio on is complete, trigger delay dial callback.getValue().onComplete(null, true); ArgumentCaptor<Consumer<Boolean>> completeConsumer = ArgumentCaptor .forClass(Consumer.class); verify(spyEst).switchDdsDelayed(eq(testPhone), completeConsumer.capture()); verify(mPhoneSwitcher).overrideDefaultDataForEmergency(eq(testPhone.getPhoneId()), eq(150) /* extensionTime */, any()); // After dds switch completes successfully, set emergency mode completeConsumer.getValue().accept(true); verify(testPhone).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any()); } /** * Test that the EmergencyStateTracker turns on radio, performs a DDS switch and sets emergency * mode switch when we are not roaming and the carrier only supports SUPL over the data plane. */ @Test @SmallTest public void startEmergencyCall_radioOff_turnOnRadioTimeoutSwitchDdsAndSetEmergencyMode() { EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker( true /* isSuplDdsSwitchRequiredForEmergencyCall */); // Create test Phones and set radio off Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */, false /* isRadioOn */); setConfigForDdsSwitch(testPhone, null, CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY, "150"); // Spy is used to capture consumer in delayDialForDdsSwitch EmergencyStateTracker spyEst = spy(emergencyStateTracker); CompletableFuture<Integer> unused = spyEst.startEmergencyCall(testPhone, TEST_CALL_ID, false); // startEmergencyCall should trigger radio on ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor .forClass(RadioOnStateListener.Callback.class); verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone), eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS)); // onTimeout should return true when radion on assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); assertFalse(callback.getValue() .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); when(mSST.isRadioOn()).thenReturn(true); assertFalse(callback.getValue() .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); assertTrue(callback.getValue() .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false)); // Once radio on is complete, trigger delay dial callback.getValue().onComplete(null, true); ArgumentCaptor<Consumer<Boolean>> completeConsumer = ArgumentCaptor Loading Loading @@ -199,7 +248,7 @@ public class EmergencyStateTrackerTest extends TelephonyTest { ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor .forClass(RadioOnStateListener.Callback.class); verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone), eq(false), eq(0)); eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS)); // Verify future completes with DisconnectCause.POWER_OFF if radio not ready CompletableFuture<Void> unused = future.thenAccept((result) -> { assertEquals((Integer) result, (Integer) DisconnectCause.POWER_OFF); Loading