Add timeout for ImsState callback
If the ImsRegistration or MmTelCapabilities callbacks are not received, read the states from ImsStateTracker and continue with domain selection.
Bug: 343021500
Flag: EXEMPT bugfix
Test: atest TeleServiceTests:NormalCallDomainSelectorTest
Change-Id: I2f74b2587b9a273cbc5c966a4bf76d4db23a43ac
diff --git a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
index aedd06e..bf6c647 100644
--- a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.content.Context;
import android.os.Looper;
+import android.os.Message;
import android.os.PersistableBundle;
import android.telecom.TelecomManager;
import android.telephony.Annotation.DisconnectCauses;
@@ -45,6 +46,13 @@
private static final String LOG_TAG = "NCDS";
+ // Wait-time for IMS state change callback.
+ @VisibleForTesting
+ protected static final int WAIT_FOR_IMS_STATE_TIMEOUT_MS = 3000; // 3 seconds
+
+ @VisibleForTesting
+ protected static final int MSG_WAIT_FOR_IMS_STATE_TIMEOUT = 11;
+
@VisibleForTesting
protected enum SelectorState {
ACTIVE,
@@ -67,12 +75,40 @@
logd("Subscribing to state callbacks. Subid:" + subId);
mImsStateTracker.addServiceStateListener(this);
mImsStateTracker.addImsStateListener(this);
+
} else {
loge("Invalid Subscription. Subid:" + subId);
}
}
@Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+
+ case MSG_WAIT_FOR_IMS_STATE_TIMEOUT: {
+ loge("ImsStateTimeout. ImsState callback not received");
+ if (mSelectorState != SelectorState.ACTIVE) {
+ return;
+ }
+
+ if (!mImsRegStateReceived) {
+ onImsRegistrationStateChanged();
+ }
+
+ if (!mMmTelCapabilitiesReceived) {
+ onImsMmTelCapabilitiesChanged();
+ }
+ }
+ break;
+
+ default: {
+ super.handleMessage(message);
+ }
+ break;
+ }
+ }
+
+ @Override
public void selectDomain(SelectionAttributes attributes, TransportSelectorCallback callback) {
mSelectionAttributes = attributes;
mTransportSelectorCallback = callback;
@@ -104,6 +140,7 @@
if (subId == getSubId()) {
logd("NormalCallDomainSelection triggered. Sub-id:" + subId);
+ sendEmptyMessageDelayed(MSG_WAIT_FOR_IMS_STATE_TIMEOUT, WAIT_FOR_IMS_STATE_TIMEOUT_MS);
post(() -> selectDomain());
} else {
mSelectorState = SelectorState.INACTIVE;
@@ -389,6 +426,10 @@
return;
}
+ if (hasMessages(MSG_WAIT_FOR_IMS_STATE_TIMEOUT)) {
+ removeMessages(MSG_WAIT_FOR_IMS_STATE_TIMEOUT);
+ }
+
// Check IMS registration state.
if (!mImsStateTracker.isImsRegistered()) {
logd("IMS is NOT registered");
diff --git a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
index cce07d0..49411bd 100644
--- a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
@@ -19,6 +19,7 @@
import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
@@ -666,6 +667,82 @@
mNormalCallDomainSelector.getSelectorState());
}
+ @Test
+ public void testImsRegistrationStateTimeoutMessage() {
+ final TestTransportSelectorCallback transportSelectorCallback =
+ new TestTransportSelectorCallback(mNormalCallDomainSelector);
+
+ final ServiceState serviceState = new ServiceState();
+ serviceState.setState(ServiceState.STATE_IN_SERVICE);
+ mNormalCallDomainSelector.onServiceStateUpdated(serviceState);
+ doReturn(true).when(mMockImsStateTracker).isImsStateReady();
+ doReturn(true).when(mMockImsStateTracker).isImsRegistered();
+ doReturn(true).when(mMockImsStateTracker).isImsVoiceCapable();
+ doReturn(false).when(mMockImsStateTracker).isImsVideoCapable();
+ doReturn(true).when(mMockImsStateTracker).isImsRegisteredOverWlan();
+
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(false)
+ .setExitedFromAirplaneMode(false)
+ .build();
+
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(mNormalCallDomainSelector.hasMessages(
+ NormalCallDomainSelector.MSG_WAIT_FOR_IMS_STATE_TIMEOUT));
+
+ mNormalCallDomainSelector.onImsRegistrationStateChanged();
+ mNormalCallDomainSelector.onImsMmTelCapabilitiesChanged();
+ processAllMessages();
+
+ assertFalse(mNormalCallDomainSelector.hasMessages(
+ NormalCallDomainSelector.MSG_WAIT_FOR_IMS_STATE_TIMEOUT));
+ assertTrue(transportSelectorCallback.mWlanSelected);
+ assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE,
+ mNormalCallDomainSelector.getSelectorState());
+ }
+
+ @Test
+ public void testImsRegistrationStateTimeoutHandler() {
+ final TestTransportSelectorCallback transportSelectorCallback =
+ new TestTransportSelectorCallback(mNormalCallDomainSelector);
+
+ final ServiceState serviceState = new ServiceState();
+ serviceState.setState(ServiceState.STATE_IN_SERVICE);
+ mNormalCallDomainSelector.onServiceStateUpdated(serviceState);
+ doReturn(true).when(mMockImsStateTracker).isImsStateReady();
+ doReturn(false).when(mMockImsStateTracker).isImsRegistered();
+ doReturn(true).when(mMockImsStateTracker).isImsVoiceCapable();
+ doReturn(false).when(mMockImsStateTracker).isImsVideoCapable();
+ doReturn(true).when(mMockImsStateTracker).isImsRegisteredOverWlan();
+
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(false)
+ .setExitedFromAirplaneMode(false)
+ .build();
+
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(mNormalCallDomainSelector.hasMessages(
+ NormalCallDomainSelector.MSG_WAIT_FOR_IMS_STATE_TIMEOUT));
+
+ mTestableLooper.moveTimeForward(
+ NormalCallDomainSelector.WAIT_FOR_IMS_STATE_TIMEOUT_MS + 10);
+ processAllMessages();
+
+ assertEquals(transportSelectorCallback.mSelectedDomain, NetworkRegistrationInfo.DOMAIN_CS);
+ assertEquals(NormalCallDomainSelector.SelectorState.INACTIVE,
+ mNormalCallDomainSelector.getSelectorState());
+ }
+
static class TestTransportSelectorCallback implements TransportSelectorCallback,
WwanSelectorCallback {
public boolean mCreated;