Merge "Automatically disconnect emergency call" into 24D1-dev
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 67b32df..9300c84 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -753,8 +753,25 @@
                     }
                 }
                 if (mEmergencyConnection != null) {
-                    mEmergencyConnection.hangup(android.telephony.DisconnectCause.OUT_OF_NETWORK);
-                    mEmergencyConnection = null;
+                    if (mEmergencyConnection.getOriginalConnection() != null) {
+                        mEmergencyConnection.hangup(cause);
+                    } else {
+                        DomainSelectionConnection dsc = mEmergencyCallDomainSelectionConnection;
+                        int disconnectCause = (cause == android.telephony.DisconnectCause.NOT_VALID)
+                                ? dsc.getDisconnectCause() : cause;
+                        mEmergencyConnection.setTelephonyConnectionDisconnected(
+                                    DisconnectCauseUtil.toTelecomDisconnectCause(disconnectCause,
+                                        dsc.getPreciseDisconnectCause(), dsc.getReasonMessage(),
+                                        dsc.getPhoneId(), dsc.getImsReasonInfo(),
+                                        new FlagsAdapterImpl()));
+                        mEmergencyConnection.close();
+
+                        TelephonyConnection c = mEmergencyConnection;
+                        mEmergencyConnection.removeTelephonyConnectionListener(
+                                mEmergencyConnectionListener);
+                        releaseEmergencyCallDomainSelection(true, false);
+                        mEmergencyStateTracker.endCall(c);
+                    }
                 }
             });
         }
@@ -2647,7 +2664,8 @@
         Log.i(this, "maybeReselectDomain csCause=" +  callFailCause + ", psCause=" + reasonInfo);
         if (mEmergencyConnection == c) {
             if (mEmergencyCallDomainSelectionConnection != null) {
-                return maybeReselectDomainForEmergencyCall(c, callFailCause, reasonInfo);
+                return maybeReselectDomainForEmergencyCall(c, callFailCause, reasonInfo,
+                        showPreciseCause, overrideCause);
             }
             Log.i(this, "maybeReselectDomain endCall()");
             c.removeTelephonyConnectionListener(mEmergencyConnectionListener);
@@ -2676,9 +2694,11 @@
     }
 
     private boolean maybeReselectDomainForEmergencyCall(final TelephonyConnection c,
-            int callFailCause, ImsReasonInfo reasonInfo) {
+            int callFailCause, ImsReasonInfo reasonInfo,
+            boolean showPreciseCause, int overrideCause) {
         Log.i(this, "maybeReselectDomainForEmergencyCall "
-                + "csCause=" +  callFailCause + ", psCause=" + reasonInfo);
+                + "csCause=" +  callFailCause + ", psCause=" + reasonInfo
+                + ", showPreciseCause=" + showPreciseCause + ", overrideCause=" + overrideCause);
 
         if (c.getOriginalConnection() != null
                 && c.getOriginalConnection().getDisconnectCause()
@@ -2686,6 +2706,12 @@
                 && c.getOriginalConnection().getDisconnectCause()
                         != android.telephony.DisconnectCause.POWER_OFF) {
 
+            int disconnectCause = (overrideCause != android.telephony.DisconnectCause.NOT_VALID)
+                    ? overrideCause : c.getOriginalConnection().getDisconnectCause();
+            mEmergencyCallDomainSelectionConnection.setDisconnectCause(disconnectCause,
+                    showPreciseCause ? callFailCause : CallFailCause.NOT_VALID,
+                    c.getOriginalConnection().getVendorDisconnectCause());
+
             DomainSelectionService.SelectionAttributes attr =
                     EmergencyCallDomainSelectionConnection.getSelectionAttributes(
                             c.getPhone().getPhoneId(), c.getPhone().getSubId(), false,
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index a75f244..5b9ee02 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -54,6 +54,7 @@
 import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING;
 import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
 import static android.telephony.PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
+import static android.telephony.PreciseDisconnectCause.NO_VALID_SIM;
 import static android.telephony.PreciseDisconnectCause.SERVICE_OPTION_NOT_AVAILABLE;
 import static android.telephony.TelephonyManager.DATA_CONNECTED;
 
@@ -345,6 +346,11 @@
             return;
         }
 
+        if (maybeTerminateSelection(cause)) {
+            logi("reselectDomain terminate selection");
+            return;
+        }
+
         if (mCrossStackTimerExpired) {
             logi("reselectDomain cross stack timer expired");
             terminateSelectionForCrossSimRedialing(false);
@@ -1506,6 +1512,19 @@
                 : DisconnectCause.EMERGENCY_TEMP_FAILURE);
     }
 
+    private boolean maybeTerminateSelection(int cause) {
+        switch (cause) {
+            case NO_VALID_SIM:
+                // The disconnect cause saved in DomainSelectionConnection shall be used.
+                mTransportSelectorCallback.onSelectionTerminated(DisconnectCause.NOT_VALID);
+                return true;
+            default:
+                break;
+        }
+
+        return false;
+    }
+
     /** Starts the cross stack timer. */
     public void startCrossStackTimer() {
         boolean inService = false;
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index e791d3c..f6b043a 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -2289,6 +2289,8 @@
         assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
                 android.telephony.DisconnectCause.NOT_VALID));
         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+        verify(mEmergencyCallDomainSelectionConnection).setDisconnectCause(
+                eq(disconnectCause), eq(preciseDisconnectCause), any());
 
         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
 
@@ -2314,9 +2316,13 @@
         TestTelephonyConnection c = setupForReDialForDomainSelection(
                 mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
 
-        assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
-                android.telephony.DisconnectCause.NOT_VALID));
+        assertTrue(mTestConnectionService.maybeReselectDomain(c, null, false,
+                android.telephony.DisconnectCause.ICC_ERROR));
         verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+        verify(mEmergencyCallDomainSelectionConnection).setDisconnectCause(
+                eq(android.telephony.DisconnectCause.ICC_ERROR),
+                eq(com.android.internal.telephony.CallFailCause.NOT_VALID),
+                any());
 
         ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
 
@@ -2967,9 +2973,10 @@
                 createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
                         TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
 
-        android.telecom.Connection c = mTestConnectionService.getEmergencyConnection();
+        TelephonyConnection c = mTestConnectionService.getEmergencyConnection();
 
         assertNotNull(c);
+        assertNull(c.getOriginalConnection());
 
         ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
                 ArgumentCaptor.forClass(
@@ -2987,6 +2994,11 @@
 
         verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
         verify(mEmergencyStateTracker).endCall(eq(c));
+
+        android.telecom.DisconnectCause disconnectCause = c.getDisconnectCause();
+
+        assertNotNull(disconnectCause);
+        assertEquals(ERROR_UNSPECIFIED, disconnectCause.getTelephonyDisconnectCause());
     }
 
     @Test
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index b995ff5..7cdc4a8 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -3129,6 +3129,39 @@
         assertEquals(EUTRAN, (int) mAccessNetwork.get(2));
     }
 
+    @Test
+    public void testReselectDomainCauseNoValidSim() throws Exception {
+        createSelector(SLOT_0_SUB_ID);
+        unsolBarringInfoChanged(false);
+        doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
+
+        EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+                REGISTRATION_STATE_HOME,
+                NetworkRegistrationInfo.DOMAIN_CS,
+                true, true, 0, 0, "", "");
+        SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+        mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+        processAllMessages();
+
+        bindImsServiceUnregistered();
+
+        verifyCsDialed();
+
+        attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+                .setAddress(TEST_URI)
+                .setEmergency(true)
+                .setEmergencyRegistrationResult(regResult)
+                .setCsDisconnectCause(PreciseDisconnectCause.NO_VALID_SIM)
+                .build();
+
+        mDomainSelector.reselectDomain(attr);
+        processAllMessages();
+
+        verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.NO_VALID_SIM));
+        verify(mTransportSelectorCallback)
+                .onSelectionTerminated(eq(DisconnectCause.NOT_VALID));
+    }
+
     private void setupForScanListTest(PersistableBundle bundle) throws Exception {
         setupForScanListTest(bundle, false);
     }