Handle WPS calls while call domain selection.

Bug: 262006376
Test: atest atest TeleServiceTests:NormalCallDomainSelectorTest#testWPSCallDomainSelection and Manual testing.
Change-Id: I1536e04a233a6a07a0360c8fb094ab5284257ad5
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 4a89bd6..bf04d03 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -2040,6 +2040,8 @@
                                         .setVideoState(videoState)
                                         .setIntentExtras(extras)
                                         .setRttTextStream(mNormalCallConnection.getRttTextStream())
+                                        .setIsWpsCall(NormalCallDomainSelectionConnection
+                                                .isWpsCall(number))
                                         .build(),
                                 mNormalCallConnection::registerForCallEvents);
 
@@ -2093,12 +2095,14 @@
         // If the number is both an MMI code and a supplementary service code,
         // it shall be treated as UT. In this case, domain selection is not performed.
         if (isMmiCode && isSuppServiceCode) {
+            Log.v(LOG_TAG, "UT code not handled by call domain selection.");
             return false;
         }
 
         // Check and select same domain as ongoing call on the same subscription (if exists)
         int activeCallDomain = getActiveCallDomain(phone.getSubId());
-        if (activeCallDomain != NetworkRegistrationInfo.DOMAIN_UNKNOWN) {
+        if (activeCallDomain != NetworkRegistrationInfo.DOMAIN_UNKNOWN
+                && !NormalCallDomainSelectionConnection.isWpsCall(number)) {
             Log.d(LOG_TAG, "Selecting same domain as ongoing call on same subId");
             mNormalCallConnection = connection;
             handleOutgoingCallConnectionByCallDomainSelection(
@@ -2115,6 +2119,7 @@
         SelectionAttributes selectionAttributes =
                 new SelectionAttributes.Builder(phone.getPhoneId(), phone.getSubId(),
                         SELECTOR_TYPE_CALLING)
+                        .setNumber(number)
                         .setEmergency(false)
                         .setVideoCall(VideoProfile.isVideo(videoState))
                         .build();
diff --git a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
index 146874c..521c1f9 100644
--- a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
@@ -21,7 +21,9 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.os.Looper;
+import android.os.PersistableBundle;
 import android.telephony.Annotation.DisconnectCauses;
+import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
 import android.telephony.DomainSelectionService.SelectionAttributes;
 import android.telephony.NetworkRegistrationInfo;
@@ -30,6 +32,8 @@
 import android.telephony.TransportSelectorCallback;
 import android.telephony.ims.ImsReasonInfo;
 
+import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
+
 /**
  * Implements domain selector for outgoing non-emergency calls.
  */
@@ -131,14 +135,16 @@
 
     @Override
     public void onImsRegistrationStateChanged() {
-        logd("onImsRegistrationStateChanged");
+        logd("onImsRegistrationStateChanged. IsImsRegistered: "
+                + mImsStateTracker.isImsRegistered());
         mImsRegStateReceived = true;
         selectDomain();
     }
 
     @Override
     public void onImsMmTelCapabilitiesChanged() {
-        logd("onImsMmTelCapabilitiesChanged");
+        logd("onImsMmTelCapabilitiesChanged. ImsVoiceCap: " + mImsStateTracker.isImsVoiceCapable()
+                + " ImsVideoCap: " + mImsStateTracker.isImsVideoCapable());
         mMmTelCapabilitiesReceived = true;
         selectDomain();
     }
@@ -221,6 +227,33 @@
                 || mServiceState.getState() == ServiceState.STATE_EMERGENCY_ONLY);
     }
 
+    private boolean isWpsCallSupportedByIms() {
+        CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
+
+        PersistableBundle config = null;
+        if (configManager != null) {
+            config = configManager.getConfigForSubId(mSelectionAttributes.getSubId());
+        }
+
+        return (config != null)
+                ? config.getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL) : false;
+    }
+
+    private void handleWpsCall() {
+        if (isWpsCallSupportedByIms()) {
+            logd("WPS call placed over PS");
+            notifyPsSelected();
+        } else {
+            if (isOutOfService()) {
+                loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+                notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+            } else {
+                logd("WPS call placed over CS");
+                notifyCsSelected();
+            }
+        }
+    }
+
     private synchronized void selectDomain() {
         if (mStopDomainSelection || mSelectionAttributes == null
                 || mTransportSelectorCallback == null) {
@@ -294,8 +327,13 @@
                 }
             } else if (mImsStateTracker.isImsVoiceCapable()) {
                 logd("IMS is voice capable");
-                // Voice call over PS
-                notifyPsSelected();
+                // TODO(b/266175810) Remove this dependency.
+                if (NormalCallDomainSelectionConnection
+                        .isWpsCall(mSelectionAttributes.getNumber())) {
+                    handleWpsCall();
+                } else {
+                    notifyPsSelected();
+                }
             } else {
                 logd("IMS is not voice capable");
                 // Voice call CS fallback
diff --git a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
index 890ca34..9950b7a 100644
--- a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
@@ -31,7 +31,9 @@
 import android.os.CancellationSignal;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.PersistableBundle;
 import android.telephony.AccessNetworkConstants;
+import android.telephony.CarrierConfigManager;
 import android.telephony.DisconnectCause;
 import android.telephony.DomainSelectionService;
 import android.telephony.DomainSelector;
@@ -75,6 +77,7 @@
     private NormalCallDomainSelector mNormalCallDomainSelector;
 
     @Mock private Context mMockContext;
+    @Mock private CarrierConfigManager mMockCarrierConfigMgr;
     @Mock private ImsManager mMockImsManager;
     @Mock private ImsMmTelManager mMockMmTelManager;
     @Mock private ImsStateTracker mMockImsStateTracker;
@@ -83,10 +86,17 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+
         doReturn(Context.TELEPHONY_IMS_SERVICE).when(mMockContext)
                 .getSystemServiceName(ImsManager.class);
         doReturn(mMockImsManager).when(mMockContext)
                 .getSystemService(Context.TELEPHONY_IMS_SERVICE);
+
+        doReturn(Context.CARRIER_CONFIG_SERVICE).when(mMockContext)
+                .getSystemServiceName(CarrierConfigManager.class);
+        doReturn(mMockCarrierConfigMgr).when(mMockContext)
+                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
         doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_1);
         doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_2);
         doNothing().when(mMockImsStateTracker).removeServiceStateListener(any());
@@ -310,6 +320,49 @@
         assertTrue(transportSelectorCallback.verifyOnWlanSelected());
     }
 
+    @Test
+    public void testWPSCallDomainSelection() {
+        MockTransportSelectorCallback transportSelectorCallback =
+                new MockTransportSelectorCallback();
+        DomainSelectionService.SelectionAttributes attributes =
+                new DomainSelectionService.SelectionAttributes.Builder(
+                        SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+                        .setNumber("*272121")
+                        .setCallId(TEST_CALLID)
+                        .setEmergency(false)
+                        .setVideoCall(false)
+                        .setExitedFromAirplaneMode(false)
+                        .build();
+
+        //Case 1: WPS not supported by IMS
+        PersistableBundle config = new PersistableBundle();
+        config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, false);
+        doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1);
+        ServiceState serviceState = new ServiceState();
+        serviceState.setState(ServiceState.STATE_IN_SERVICE);
+        initialize(serviceState, true, true, true, true);
+        mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+        assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+        assertTrue(transportSelectorCallback
+                .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_CS));
+
+        //Case 2: WPS supported by IMS and WLAN registered
+        config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
+        serviceState.setState(ServiceState.STATE_IN_SERVICE);
+        initialize(serviceState, true, true, true, true);
+        mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+        assertTrue(transportSelectorCallback.verifyOnWlanSelected());
+
+        //Case 2: WPS supported by IMS and LTE registered
+        config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
+        serviceState.setState(ServiceState.STATE_IN_SERVICE);
+        initialize(serviceState, true, false, true, true);
+        mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+        assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+        assertTrue(transportSelectorCallback
+                .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
+    }
+
     static class MockTransportSelectorCallback implements TransportSelectorCallback,
             WwanSelectorCallback {
         public boolean mCreated;