Merge "Check TTY enable flag and capability of IMS while selecting call domain."
diff --git a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
index 521c1f9..3da0044 100644
--- a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.os.Looper;
 import android.os.PersistableBundle;
+import android.telecom.TelecomManager;
 import android.telephony.Annotation.DisconnectCauses;
 import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
@@ -254,6 +255,27 @@
         }
     }
 
+    private boolean isTtySupportedByIms() {
+        CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
+
+        PersistableBundle config = null;
+        if (configManager != null) {
+            config = configManager.getConfigForSubId(mSelectionAttributes.getSubId());
+        }
+
+        return (config != null)
+                && config.getBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL);
+    }
+
+    private boolean isTtyModeEnabled() {
+        TelecomManager tm = mContext.getSystemService(TelecomManager.class);
+        if (tm == null) {
+            loge("isTtyModeEnabled: telecom not available");
+            return false;
+        }
+        return tm.getCurrentTtyMode() != TelecomManager.TTY_MODE_OFF;
+    }
+
     private synchronized void selectDomain() {
         if (mStopDomainSelection || mSelectionAttributes == null
                 || mTransportSelectorCallback == null) {
@@ -298,54 +320,71 @@
             return;
         }
 
-        if (mImsStateTracker.isMmTelFeatureAvailable()) {
-
-            if (!mImsRegStateReceived || !mMmTelCapabilitiesReceived) {
-                loge("Waiting for ImsState and MmTelCapabilities callbacks");
-                return;
-            }
-
-            if (!mImsStateTracker.isImsRegistered()) {
-                logd("IMS is NOT registered");
-                if (isOutOfService()) {
-                    loge("Cannot place call in current ServiceState: " + mServiceState.getState());
-                    notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
-                } else {
-                    notifyCsSelected();
-                }
-                return;
-            }
-
-            if (mSelectionAttributes.isVideoCall()) {
-                logd("It's a video call");
-                if (mImsStateTracker.isImsVideoCapable()) {
-                    logd("IMS is video capable");
-                    notifyPsSelected();
-                } else {
-                    logd("IMS is not video capable. Ending the call");
-                    notifySelectionTerminated(DisconnectCause.OUTGOING_FAILURE);
-                }
-            } else if (mImsStateTracker.isImsVoiceCapable()) {
-                logd("IMS is voice capable");
-                // TODO(b/266175810) Remove this dependency.
-                if (NormalCallDomainSelectionConnection
-                        .isWpsCall(mSelectionAttributes.getNumber())) {
-                    handleWpsCall();
-                } else {
-                    notifyPsSelected();
-                }
+        if (!mImsStateTracker.isMmTelFeatureAvailable()) {
+            logd("MmTelFeatureAvailable unavailable");
+            if (isOutOfService()) {
+                loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+                notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
             } else {
-                logd("IMS is not voice capable");
-                // Voice call CS fallback
-                if (isOutOfService()) {
-                    loge("Cannot place call in current ServiceState: " + mServiceState.getState());
-                    notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
-                } else {
-                    notifyCsSelected();
-                }
+                notifyCsSelected();
+            }
+            return;
+        }
+
+        if (!mImsRegStateReceived || !mMmTelCapabilitiesReceived) {
+            loge("Waiting for ImsState and MmTelCapabilities callbacks");
+            return;
+        }
+
+        // Check IMS registration state.
+        if (!mImsStateTracker.isImsRegistered()) {
+            logd("IMS is NOT registered");
+            if (isOutOfService()) {
+                loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+                notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+            } else {
+                notifyCsSelected();
+            }
+            return;
+        }
+
+        // Check TTY
+        if (isTtyModeEnabled() && !isTtySupportedByIms()) {
+            if (isOutOfService()) {
+                loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+                notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+            } else {
+                notifyCsSelected();
+            }
+            return;
+        }
+
+        // Handle video call.
+        if (mSelectionAttributes.isVideoCall()) {
+            logd("It's a video call");
+            if (mImsStateTracker.isImsVideoCapable()) {
+                logd("IMS is video capable");
+                notifyPsSelected();
+            } else {
+                logd("IMS is not video capable. Ending the call");
+                notifySelectionTerminated(DisconnectCause.OUTGOING_FAILURE);
+            }
+            return;
+        }
+
+        // Handle voice call.
+        if (mImsStateTracker.isImsVoiceCapable()) {
+            logd("IMS is voice capable");
+            // TODO(b/266175810) Remove this dependency.
+            if (NormalCallDomainSelectionConnection
+                    .isWpsCall(mSelectionAttributes.getNumber())) {
+                handleWpsCall();
+            } else {
+                notifyPsSelected();
             }
         } else {
-            logd("IMS is not registered or unavailable");
+            logd("IMS is not voice capable");
+            // Voice call CS fallback
             if (isOutOfService()) {
                 loge("Cannot place call in current ServiceState: " + mServiceState.getState());
                 notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
diff --git a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
index 9950b7a..8780f1f 100644
--- a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
@@ -32,6 +32,7 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.PersistableBundle;
+import android.telecom.TelecomManager;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
@@ -82,6 +83,7 @@
     @Mock private ImsMmTelManager mMockMmTelManager;
     @Mock private ImsStateTracker mMockImsStateTracker;
     @Mock private DomainSelectorBase.DestroyListener mMockDestroyListener;
+    @Mock private TelecomManager mMockTelecomManager;
 
     @Before
     public void setUp() throws Exception {
@@ -97,6 +99,11 @@
         doReturn(mMockCarrierConfigMgr).when(mMockContext)
                 .getSystemService(Context.CARRIER_CONFIG_SERVICE);
 
+        doReturn(Context.TELECOM_SERVICE).when(mMockContext)
+                .getSystemServiceName(TelecomManager.class);
+        doReturn(mMockTelecomManager).when(mMockContext)
+                .getSystemService(Context.TELECOM_SERVICE);
+
         doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_1);
         doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_2);
         doNothing().when(mMockImsStateTracker).removeServiceStateListener(any());
@@ -363,6 +370,47 @@
                 .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
     }
 
+    @Test
+    public void testTtyCallDomainSelection() {
+        MockTransportSelectorCallback transportSelectorCallback =
+                new MockTransportSelectorCallback();
+        DomainSelectionService.SelectionAttributes attributes =
+                new DomainSelectionService.SelectionAttributes.Builder(
+                        SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+                        .setCallId(TEST_CALLID)
+                        .setEmergency(false)
+                        .setVideoCall(false)
+                        .setExitedFromAirplaneMode(false)
+                        .build();
+
+        //Case 1: TTY not supported by IMS and TTY enabled
+        doReturn(TelecomManager.TTY_MODE_FULL).when(mMockTelecomManager).getCurrentTtyMode();
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false);
+        doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1);
+        ServiceState serviceState = new ServiceState();
+        serviceState.setState(ServiceState.STATE_IN_SERVICE);
+        initialize(serviceState, true, false, true, true);
+        mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+        assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+        assertTrue(transportSelectorCallback
+                .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_CS));
+
+        //Case 2: TTY supported by IMS and TTY enabled
+        config.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
+        mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+        assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+        assertTrue(transportSelectorCallback
+                .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
+
+        //Case 3: TTY supported by IMS and TTY disabled
+        doReturn(TelecomManager.TTY_MODE_OFF).when(mMockTelecomManager).getCurrentTtyMode();
+        mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+        assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+        assertTrue(transportSelectorCallback
+                .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
+    }
+
     static class MockTransportSelectorCallback implements TransportSelectorCallback,
             WwanSelectorCallback {
         public boolean mCreated;