Add interworking with EmergencyStateTracker for sending emergency SMS

This adds the interworking implementation for emergency SMS with the
EmergencyStateTracker. When an emergency SMS is being sent, the
SmsDispatchersController calls the startEmergencySms, then the
EmergencyStateTracker sets the emergency mode to the modem and if the
emergency SMS completely sends regardless of the success or failure, it
should call the endSms, then the EmergencyStateTracker exits the
emergency mode or enters the emergency SMS callback mode if needed.

Bug: 262804071
Test: atest SmsDispatchersControllerTest, EmergencyStateTrackerTest
Test: manual (verify emergency SMS using test number on device when
domain selection disabled)
Test: manual (verify emergency SMS using test number/equipment on device
when domain selection enabled)
Test: manual (verify normal MO SMS on device when domain selection
disabled)
Test: manual (verify normal MO SMS on device when domain selection
enabled)

Change-Id: I7310c1affa3d8e474de7f3f9f81a9af56a17c2c9
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 777edb7..3c20d69 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -5,4 +5,11 @@
   namespace: "telephony"
   description: "Previously, the DB allows insertion of a random sub Id, but doesn't allow query it. This change rejects such interaction."
   bug: "294125411"
-}
\ No newline at end of file
+}
+
+flag {
+  name: "sms_domain_selection_enabled"
+  namespace: "telephony"
+  description: "This flag controls AP domain selection support for normal/emergency SMS."
+  bug: "262804071"
+}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index ecf8e5f..05bfe36 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -463,7 +463,7 @@
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
         mIccSmsInterfaceManager = mTelephonyComponentFactory
                 .inject(IccSmsInterfaceManager.class.getName())
-                .makeIccSmsInterfaceManager(this);
+                .makeIccSmsInterfaceManager(this, mFeatureFlags);
 
         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
diff --git a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
index 2d77631..7c1670c 100644
--- a/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
+++ b/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
@@ -21,6 +21,7 @@
 import static android.telephony.SmsManager.STATUS_ON_ICC_UNREAD;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -47,6 +48,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 import com.android.internal.telephony.uicc.IccConstants;
 import com.android.internal.telephony.uicc.IccFileHandler;
@@ -155,11 +157,11 @@
         }
     };
 
-    protected IccSmsInterfaceManager(Phone phone) {
+    protected IccSmsInterfaceManager(Phone phone, @NonNull FeatureFlags featureFlags) {
         this(phone, phone.getContext(),
                 (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE),
                 new SmsDispatchersController(
-                        phone, phone.mSmsStorageMonitor, phone.mSmsUsageMonitor),
+                        phone, phone.mSmsStorageMonitor, phone.mSmsUsageMonitor, featureFlags),
                 new SmsPermissions(phone, phone.getContext(),
                         (AppOpsManager) phone.getContext().getSystemService(
                                 Context.APP_OPS_SERVICE)));
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
index 67dbdb5..4e4d55d 100644
--- a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -202,10 +202,13 @@
                         tracker.onSent(mContext);
                         mTrackers.remove(token);
                         mPhone.notifySmsSent(tracker.mDestAddress);
+                        mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
+                                tracker.mDestAddress, tracker.mMessageId);
                         break;
                     case ImsSmsImplBase.SEND_STATUS_ERROR:
                         tracker.onFailed(mContext, reason, networkReasonCode);
                         mTrackers.remove(token);
+                        notifySmsSentFailedToEmergencyStateTracker(tracker);
                         break;
                     case ImsSmsImplBase.SEND_STATUS_ERROR_RETRY:
                         int maxRetryCountOverIms = getMaxRetryCountOverIms();
@@ -224,6 +227,7 @@
                         } else {
                             tracker.onFailed(mContext, reason, networkReasonCode);
                             mTrackers.remove(token);
+                            notifySmsSentFailedToEmergencyStateTracker(tracker);
                         }
                         break;
                     case ImsSmsImplBase.SEND_STATUS_ERROR_FALLBACK:
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 739ca8c..54c27c5 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -1010,6 +1010,16 @@
     protected abstract boolean shouldBlockSmsForEcbm();
 
     /**
+     * Notifies the {@link SmsDispatchersController} that sending MO SMS is failed.
+     *
+     * @param tracker holds the SMS message to be sent
+     */
+    protected void notifySmsSentFailedToEmergencyStateTracker(SmsTracker tracker) {
+        mSmsDispatchersController.notifySmsSentFailedToEmergencyStateTracker(
+                tracker.mDestAddress, tracker.mMessageId);
+    }
+
+    /**
      * Called when SMS send completes. Broadcasts a sentIntent on success.
      * On failure, either sets up retries or broadcasts a sentIntent with
      * the failure in the result code.
@@ -1041,6 +1051,8 @@
             }
             tracker.onSent(mContext);
             mPhone.notifySmsSent(tracker.mDestAddress);
+            mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
+                    tracker.mDestAddress, tracker.mMessageId);
 
             mPhone.getSmsStats().onOutgoingSms(
                     tracker.mImsRetry > 0 /* isOverIms */,
@@ -1091,6 +1103,7 @@
             // if sms over IMS is not supported on data and voice is not available...
             if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
                 tracker.onFailed(mContext, getNotInServiceError(ss), NO_ERROR_CODE);
+                notifySmsSentFailedToEmergencyStateTracker(tracker);
                 mPhone.getSmsStats().onOutgoingSms(
                         tracker.mImsRetry > 0 /* isOverIms */,
                         SmsConstants.FORMAT_3GPP2.equals(getFormat()),
@@ -1151,6 +1164,7 @@
             } else {
                 int errorCode = (smsResponse != null) ? smsResponse.mErrorCode : NO_ERROR_CODE;
                 tracker.onFailed(mContext, error, errorCode);
+                notifySmsSentFailedToEmergencyStateTracker(tracker);
                 mPhone.getSmsStats().onOutgoingSms(
                         tracker.mImsRetry > 0 /* isOverIms */,
                         SmsConstants.FORMAT_3GPP2.equals(getFormat()),
@@ -2375,6 +2389,7 @@
             int errorCode) {
         for (SmsTracker tracker : trackers) {
             tracker.onFailed(mContext, error, errorCode);
+            notifySmsSentFailedToEmergencyStateTracker(tracker);
         }
         if (trackers.length > 0) {
             // This error occurs before the SMS is sent. Make an assumption if it would have
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index d2dfcac..8795840 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -45,16 +45,20 @@
 import android.telephony.SmsManager;
 import android.telephony.SmsMessage;
 import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
 import android.text.TextUtils;
 
 import com.android.ims.ImsManager;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.telephony.cdma.CdmaInboundSmsHandler;
 import com.android.internal.telephony.cdma.CdmaSMSDispatcher;
 import com.android.internal.telephony.domainselection.DomainSelectionConnection;
 import com.android.internal.telephony.domainselection.DomainSelectionResolver;
 import com.android.internal.telephony.domainselection.EmergencySmsDomainSelectionConnection;
 import com.android.internal.telephony.domainselection.SmsDomainSelectionConnection;
+import com.android.internal.telephony.emergency.EmergencyStateTracker;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.gsm.GsmInboundSmsHandler;
 import com.android.internal.telephony.gsm.GsmSMSDispatcher;
 import com.android.telephony.Rlog;
@@ -62,8 +66,10 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 
 /**
@@ -94,6 +100,15 @@
     /** InboundSmsHandler exited WaitingState */
     protected static final int EVENT_SMS_HANDLER_EXITING_WAITING_STATE = 17;
 
+    /** Called when SMS should be sent using AP domain selection. */
+    private static final int EVENT_SEND_SMS_USING_DOMAIN_SELECTION = 18;
+
+    /** Called when SMS is completely sent using AP domain selection regardless of the result. */
+    private static final int EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION = 19;
+
+    /** Called when AP domain selection is abnormally terminated. */
+    private static final int EVENT_DOMAIN_SELECTION_TERMINATED_ABNORMALLY = 20;
+
     /** Delete any partial message segments after being IN_SERVICE for 1 day. */
     private static final long PARTIAL_SEGMENT_WAIT_DURATION = (long) (60 * 60 * 1000) * 24;
     /** Constant for invalid time */
@@ -117,6 +132,7 @@
     private final SmsUsageMonitor mUsageMonitor;
     private final CommandsInterface mCi;
     private final Context mContext;
+    private final @NonNull FeatureFlags mFeatureFlags;
 
     /** true if IMS is registered and sms is supported, false otherwise.*/
     private boolean mIms = false;
@@ -183,7 +199,7 @@
             };
 
     /** Stores the sending SMS information for a pending request. */
-    private class PendingRequest {
+    private static class PendingRequest {
         public static final int TYPE_DATA = 1;
         public static final int TYPE_TEXT = 2;
         public static final int TYPE_MULTIPART_TEXT = 3;
@@ -310,13 +326,18 @@
 
         @Override
         public void onSelectionTerminated(@DisconnectCauses int cause) {
-            notifyDomainSelectionTerminated(this);
+            logd("onSelectionTerminated: emergency=" + mEmergency + ", cause=" + cause);
+            // This callback is invoked by another thread, so this operation is posted and handled
+            // through the execution flow of SmsDispatchersController.
+            SmsDispatchersController.this.sendMessage(
+                    obtainMessage(EVENT_DOMAIN_SELECTION_TERMINATED_ABNORMALLY, this));
         }
     }
 
     /** Manages the domain selection connections: MO SMS or emergency SMS. */
     private DomainSelectionConnectionHolder mDscHolder;
     private DomainSelectionConnectionHolder mEmergencyDscHolder;
+    private EmergencyStateTracker mEmergencyStateTracker;
 
     /**
      * Puts a delivery pending tracker to the map based on the format.
@@ -332,13 +353,13 @@
     }
 
     public SmsDispatchersController(Phone phone, SmsStorageMonitor storageMonitor,
-            SmsUsageMonitor usageMonitor) {
-        this(phone, storageMonitor, usageMonitor, phone.getLooper());
+            SmsUsageMonitor usageMonitor, @NonNull FeatureFlags featureFlags) {
+        this(phone, storageMonitor, usageMonitor, phone.getLooper(), featureFlags);
     }
 
     @VisibleForTesting
     public SmsDispatchersController(Phone phone, SmsStorageMonitor storageMonitor,
-            SmsUsageMonitor usageMonitor, Looper looper) {
+            SmsUsageMonitor usageMonitor, Looper looper, @NonNull FeatureFlags featureFlags) {
         super(looper);
 
         Rlog.d(TAG, "SmsDispatchersController created");
@@ -346,6 +367,7 @@
         mContext = phone.getContext();
         mUsageMonitor = usageMonitor;
         mCi = phone.mCi;
+        mFeatureFlags = featureFlags;
         mPhone = phone;
 
         // Create dispatchers, inbound SMS handlers and
@@ -447,7 +469,36 @@
                 mPhone.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
                 resetPartialSegmentWaitTimer();
                 break;
-
+            case EVENT_SEND_SMS_USING_DOMAIN_SELECTION: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                DomainSelectionConnectionHolder holder =
+                        (DomainSelectionConnectionHolder) args.arg1;
+                PendingRequest request = (PendingRequest) args.arg2;
+                String logTag = (String) args.arg3;
+                try {
+                    handleSendSmsUsingDomainSelection(holder, request, logTag);
+                } finally {
+                    args.recycle();
+                }
+                break;
+            }
+            case EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                String destAddr = (String) args.arg1;
+                Long messageId = (Long) args.arg2;
+                Boolean success = (Boolean) args.arg3;
+                try {
+                    handleSmsSentCompletedUsingDomainSelection(destAddr, messageId, success);
+                } finally {
+                    args.recycle();
+                }
+                break;
+            }
+            case EVENT_DOMAIN_SELECTION_TERMINATED_ABNORMALLY: {
+                handleDomainSelectionTerminatedAbnormally(
+                        (DomainSelectionConnectionHolder) msg.obj);
+                break;
+            }
             default:
                 if (isCdmaMo()) {
                     mCdmaDispatcher.handleMessage(msg);
@@ -701,7 +752,7 @@
         boolean retryUsingImsService = false;
 
         if (!tracker.mUsesImsServiceForIms) {
-            if (mDomainSelectionResolverProxy.isDomainSelectionSupported()) {
+            if (isSmsDomainSelectionEnabled()) {
                 DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false);
 
                 // If the DomainSelectionConnection is not available,
@@ -756,6 +807,8 @@
                 // should never come here...
                 Rlog.e(TAG, "sendRetrySms failed to re-encode per missing fields!");
                 tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
+                notifySmsSentFailedToEmergencyStateTracker(
+                        tracker.mDestAddress, tracker.mMessageId);
                 return;
             }
             String scAddr = (String) map.get("scAddr");
@@ -763,6 +816,8 @@
             if (destAddr == null) {
                 Rlog.e(TAG, "sendRetrySms failed due to null destAddr");
                 tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
+                notifySmsSentFailedToEmergencyStateTracker(
+                        tracker.mDestAddress, tracker.mMessageId);
                 return;
             }
 
@@ -803,6 +858,8 @@
                         + "scAddr: %s, "
                         + "destPort: %s", scAddr, map.get("destPort")));
                 tracker.onFailed(mContext, SmsManager.RESULT_SMS_SEND_RETRY_FAILED, NO_ERROR_CODE);
+                notifySmsSentFailedToEmergencyStateTracker(
+                        tracker.mDestAddress, tracker.mMessageId);
                 return;
             }
             // replace old smsc and pdu with newly encoded ones
@@ -889,6 +946,16 @@
     }
 
     /**
+     * Checks whether the SMS domain selection is enabled or not.
+     *
+     * @return {@code true} if the SMS domain selection is enabled, {@code false} otherwise.
+     */
+    private boolean isSmsDomainSelectionEnabled() {
+        return mFeatureFlags.smsDomainSelectionEnabled()
+                && mDomainSelectionResolverProxy.isDomainSelectionSupported();
+    }
+
+    /**
      * Determines whether or not to use CDMA format for MO SMS when the domain selection uses.
      * If the domain is {@link NetworkRegistrationInfo#DOMAIN_PS}, then format is based on
      * IMS SMS format, otherwise format is based on current phone type.
@@ -929,7 +996,6 @@
     private DomainSelectionConnectionHolder getDomainSelectionConnection(boolean emergency) {
         DomainSelectionConnectionHolder holder = getDomainSelectionConnectionHolder(emergency);
         DomainSelectionConnection connection = (holder != null) ? holder.getConnection() : null;
-        boolean created = false;
 
         if (connection == null) {
             connection = mDomainSelectionResolverProxy.getDomainSelectionConnection(
@@ -940,8 +1006,6 @@
                 // Use the legacy architecture.
                 return null;
             }
-
-            created = true;
         }
 
         if (holder == null) {
@@ -965,6 +1029,7 @@
      * @param holder The {@link DomainSelectionConnectionHolder} that contains the
      *               {@link DomainSelectionConnection} and its related information.
      */
+    @SuppressWarnings("FutureReturnValueIgnored")
     private void requestDomainSelection(@NonNull DomainSelectionConnectionHolder holder) {
         DomainSelectionService.SelectionAttributes attr =
                 new DomainSelectionService.SelectionAttributes.Builder(mPhone.getPhoneId(),
@@ -1001,16 +1066,14 @@
     }
 
     /**
-     * Sends a SMS after selecting the domain via the domain selection service.
+     * Requests the domain selection for MO SMS.
      *
      * @param holder The {@link DomainSelectionConnectionHolder} that contains the
      *               {@link DomainSelectionConnection} and its related information.
-     * @param request The {@link PendingRequest} that stores the SMS request
-     *                (data, text, multipart text) to be sent.
-     * @param logTag The log tag to display which method called this method.
+     * @param logTag The log string.
      */
-    private void sendSmsUsingDomainSelection(@NonNull DomainSelectionConnectionHolder holder,
-            @NonNull PendingRequest request, @NonNull String logTag) {
+    private void requestDomainSelection(@NonNull DomainSelectionConnectionHolder holder,
+            @NonNull PendingRequest request, String logTag) {
         boolean isDomainSelectionRequested = holder.isDomainSelectionRequested();
         // The domain selection is in progress so waits for the result of
         // the domain selection by adding this request to the pending list.
@@ -1025,6 +1088,120 @@
     }
 
     /**
+     * Handles an event for sending a SMS after selecting the domain via the domain selection
+     * service.
+     *
+     * @param holder The {@link DomainSelectionConnectionHolder} that contains the
+     *               {@link DomainSelectionConnection} and its related information.
+     * @param request The {@link PendingRequest} that stores the SMS request
+     *                (data, text, multipart text) to be sent.
+     * @param logTag The log tag to display which method called this method.
+     */
+    @SuppressWarnings("FutureReturnValueIgnored")
+    private void handleSendSmsUsingDomainSelection(@NonNull DomainSelectionConnectionHolder holder,
+            @NonNull PendingRequest request, @NonNull String logTag) {
+        if (holder.isEmergency()) {
+            if (mEmergencyStateTracker == null) {
+                mEmergencyStateTracker = EmergencyStateTracker.getInstance();
+            }
+
+            CompletableFuture<Integer> future = mEmergencyStateTracker.startEmergencySms(mPhone,
+                    String.valueOf(request.messageId),
+                    isTestEmergencyNumber(request.destAddr));
+            future.thenAccept((result) -> {
+                logi("startEmergencySms(" + logTag + "): messageId=" + request.messageId
+                        + ", result=" + result);
+                // An emergency SMS should be proceeded regardless of the result of the
+                // EmergencyStateTracker.
+                // So the domain selection request should be invoked without checking the result.
+                requestDomainSelection(holder, request, logTag);
+            });
+        } else {
+            requestDomainSelection(holder, request, logTag);
+        }
+    }
+
+    /**
+     * Sends a SMS after selecting the domain via the domain selection service.
+     *
+     * @param holder The {@link DomainSelectionConnectionHolder} that contains the
+     *               {@link DomainSelectionConnection} and its related information.
+     * @param request The {@link PendingRequest} that stores the SMS request
+     *                (data, text, multipart text) to be sent.
+     * @param logTag The log tag to display which method called this method.
+     */
+    private void sendSmsUsingDomainSelection(@NonNull DomainSelectionConnectionHolder holder,
+            @NonNull PendingRequest request, @NonNull String logTag) {
+        // Run on main thread for interworking with EmergencyStateTracker
+        // and adding the pending request.
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = holder;
+        args.arg2 = request;
+        args.arg3 = logTag;
+        sendMessage(obtainMessage(EVENT_SEND_SMS_USING_DOMAIN_SELECTION, args));
+    }
+
+    /**
+     * Called when sending MO SMS is complete regardless of the sent result.
+     *
+     * @param destAddr The destination address for SMS.
+     * @param messageId The message id for SMS.
+     * @param success A flag specifying whether MO SMS is successfully sent or not.
+     */
+    private void handleSmsSentCompletedUsingDomainSelection(@NonNull String destAddr,
+            long messageId, boolean success) {
+        if (mEmergencyStateTracker != null) {
+            TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+            if (tm.isEmergencyNumber(destAddr)) {
+                mEmergencyStateTracker.endSms(String.valueOf(messageId), success);
+            }
+        }
+    }
+
+    /**
+     * Called when MO SMS is successfully sent.
+     */
+    protected void notifySmsSentToEmergencyStateTracker(@NonNull String destAddr, long messageId) {
+        if (isSmsDomainSelectionEnabled()) {
+            // Run on main thread for interworking with EmergencyStateTracker.
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = destAddr;
+            args.arg2 = Long.valueOf(messageId);
+            args.arg3 = Boolean.TRUE;
+            sendMessage(obtainMessage(EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION, args));
+        }
+    }
+
+    /**
+     * Called when sending MO SMS is failed.
+     */
+    protected void notifySmsSentFailedToEmergencyStateTracker(@NonNull String destAddr,
+            long messageId) {
+        if (isSmsDomainSelectionEnabled()) {
+            // Run on main thread for interworking with EmergencyStateTracker.
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = destAddr;
+            args.arg2 = Long.valueOf(messageId);
+            args.arg3 = Boolean.FALSE;
+            sendMessage(obtainMessage(EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION, args));
+        }
+    }
+
+    private boolean isTestEmergencyNumber(String number) {
+        try {
+            TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+            Map<Integer, List<EmergencyNumber>> eMap = tm.getEmergencyNumberList();
+            return eMap.values().stream().flatMap(Collection::stream).anyMatch(eNumber ->
+                    eNumber.isFromSources(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST)
+                    && number.equals(eNumber.getNumber()));
+        } catch (IllegalStateException ise) {
+            return false;
+        } catch (RuntimeException r) {
+            return false;
+        }
+    }
+
+    /**
      * Finishes the domain selection for MO SMS.
      *
      * @param holder The {@link DomainSelectionConnectionHolder} object that is being finished.
@@ -1054,21 +1231,16 @@
     }
 
     /**
-     * Notifies the application that MO SMS is not sent by the error of domain selection.
+     * Called when MO SMS is not sent by the error of domain selection.
      *
      * @param holder The {@link DomainSelectionConnectionHolder} object that is being terminated.
      */
-    private void notifyDomainSelectionTerminated(@NonNull DomainSelectionConnectionHolder holder) {
-        final List<PendingRequest> pendingRequests = holder.getPendingRequests();
-
-        logd("notifyDomainSelectionTerminated: pendingRequests=" + pendingRequests.size());
-
-        for (PendingRequest r : pendingRequests) {
-            triggerSentIntentForFailure(r.sentIntents);
-        }
-
+    private void handleDomainSelectionTerminatedAbnormally(
+            @NonNull DomainSelectionConnectionHolder holder) {
+        logd("handleDomainSelectionTerminatedAbnormally: pendingRequests="
+                + holder.getPendingRequests().size());
+        sendAllPendingRequests(holder, NetworkRegistrationInfo.DOMAIN_UNKNOWN);
         holder.setConnection(null);
-        holder.clearAllRequests();
     }
 
     /**
@@ -1089,12 +1261,36 @@
                     + ", size=" + pendingRequests.size());
         }
 
+        // When the domain selection request is failed, SMS should be fallback
+        // to the legacy implementation.
+        boolean wasDomainUnknown = false;
+
+        if (domain == NetworkRegistrationInfo.DOMAIN_UNKNOWN) {
+            logd("sendAllPendingRequests: fallback - imsAvailable="
+                    + mImsSmsDispatcher.isAvailable());
+
+            wasDomainUnknown = true;
+
+            if (mImsSmsDispatcher.isAvailable()) {
+                domain = NetworkRegistrationInfo.DOMAIN_PS;
+            } else {
+                domain = NetworkRegistrationInfo.DOMAIN_CS;
+            }
+        }
+
         for (PendingRequest r : pendingRequests) {
             switch (r.type) {
                 case PendingRequest.TYPE_DATA:
                     sendData(domain, r);
                     break;
                 case PendingRequest.TYPE_TEXT:
+                    // When the domain selection request is failed, emergency SMS should be fallback
+                    // to the legacy implementation.
+                    if (wasDomainUnknown
+                            && domain != NetworkRegistrationInfo.DOMAIN_PS
+                            && mImsSmsDispatcher.isEmergencySmsSupport(r.destAddr)) {
+                        domain = NetworkRegistrationInfo.DOMAIN_PS;
+                    }
                     sendText(domain, r);
                     break;
                 case PendingRequest.TYPE_MULTIPART_TEXT:
@@ -1308,7 +1504,7 @@
             scAddr = getSmscAddressFromUSIMWithPhoneIdentity(callingPackage);
         }
 
-        if (mDomainSelectionResolverProxy.isDomainSelectionSupported()) {
+        if (isSmsDomainSelectionEnabled()) {
             DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false);
 
             // If the DomainSelectionConnection is not available,
@@ -1547,7 +1743,7 @@
             scAddr = getSmscAddressFromUSIMWithPhoneIdentity(callingPkg);
         }
 
-        if (mDomainSelectionResolverProxy.isDomainSelectionSupported()) {
+        if (isSmsDomainSelectionEnabled()) {
             TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
             boolean isEmergency = tm.isEmergencyNumber(destAddr);
             DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency);
@@ -1696,7 +1892,7 @@
             scAddr = getSmscAddressFromUSIMWithPhoneIdentity(callingPkg);
         }
 
-        if (mDomainSelectionResolverProxy.isDomainSelectionSupported()) {
+        if (isSmsDomainSelectionEnabled()) {
             DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false);
 
             // If the DomainSelectionConnection is not available,
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 17a4a54..b756675 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -327,8 +327,12 @@
         return new IccPhoneBookInterfaceManager(phone);
     }
 
-    public IccSmsInterfaceManager makeIccSmsInterfaceManager(Phone phone) {
-        return new IccSmsInterfaceManager(phone);
+    /**
+     * Returns a new {@link IccSmsInterfaceManager} instance.
+     */
+    public IccSmsInterfaceManager makeIccSmsInterfaceManager(Phone phone,
+            @NonNull FeatureFlags featureFlags) {
+        return new IccSmsInterfaceManager(phone, featureFlags);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index ebc6342..2119003 100644
--- a/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -129,6 +129,7 @@
         // if sms over IMS is not supported on data and voice is not available...
         if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
             tracker.onFailed(mContext, getNotInServiceError(ss), NO_ERROR_CODE);
+            notifySmsSentFailedToEmergencyStateTracker(tracker);
             return;
         }
 
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index a45e956..23473d2 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -47,7 +47,6 @@
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.emergency.EmergencyNumber;
 import android.util.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -981,9 +980,10 @@
      * This should be called once an emergency SMS is sent.
      *
      * @param smsId the SMS id on which to end the emergency SMS.
-     * @param emergencyNumber the emergency number which was used for the emergency SMS.
+     * @param success the flag specifying whether an emergency SMS is successfully sent or not.
+     *                {@code true} if SMS is successfully sent, {@code false} otherwise.
      */
-    public void endSms(@NonNull String smsId, EmergencyNumber emergencyNumber) {
+    public void endSms(@NonNull String smsId, boolean success) {
         mOngoingEmergencySmsIds.remove(smsId);
 
         // If the outgoing emergency SMSs are empty, we can try to exit the emergency mode.
diff --git a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
index 5b1f36d..dae808a 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmSMSDispatcher.java
@@ -171,6 +171,7 @@
             if(mPhone.getServiceState().getRilDataRadioTechnology()
                     != ServiceState.RIL_RADIO_TECHNOLOGY_NR) {
                 tracker.onFailed(mContext, getNotInServiceError(ss), NO_ERROR_CODE);
+                notifySmsSentFailedToEmergencyStateTracker(tracker);
                 return;
             }
         }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index b073cd4..dc63932 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -23,10 +23,12 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.isNull;
 import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
@@ -59,6 +61,8 @@
 import com.android.internal.telephony.domainselection.DomainSelectionConnection;
 import com.android.internal.telephony.domainselection.EmergencySmsDomainSelectionConnection;
 import com.android.internal.telephony.domainselection.SmsDomainSelectionConnection;
+import com.android.internal.telephony.emergency.EmergencyStateTracker;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.uicc.IccUtils;
 
 import org.junit.After;
@@ -80,8 +84,8 @@
      */
     private static class TestSmsDispatchersController extends SmsDispatchersController {
         TestSmsDispatchersController(Phone phone, SmsStorageMonitor storageMonitor,
-                SmsUsageMonitor usageMonitor, Looper looper) {
-            super(phone, storageMonitor, usageMonitor, looper);
+                SmsUsageMonitor usageMonitor, Looper looper, FeatureFlags featureFlags) {
+            super(phone, storageMonitor, usageMonitor, looper, featureFlags);
         }
 
         public DomainSelectionConnectionHolder testGetDomainSelectionConnectionHolder(
@@ -104,6 +108,15 @@
             sendMultipartText(destAddr, scAddr, parts, sentIntents, deliveryIntents, messageUri,
                     callingPkg, persistMessage, priority, expectMore, validityPeriod, messageId);
         }
+
+        public void testNotifySmsSentToEmergencyStateTracker(String destAddr, long messageId) {
+            notifySmsSentToEmergencyStateTracker(destAddr, messageId);
+        }
+
+        public void testNotifySmsSentFailedToEmergencyStateTracker(String destAddr,
+                long messageId) {
+            notifySmsSentFailedToEmergencyStateTracker(destAddr, messageId);
+        }
     }
 
     /**
@@ -158,6 +171,7 @@
     private static final String ACTION_TEST_SMS_SENT = "TEST_SMS_SENT";
 
     // Mocked classes
+    private FeatureFlags mFeatureFlags;
     private SMSDispatcher.SmsTracker mTracker;
     private PendingIntent mSentIntent;
     private TestImsSmsDispatcher mImsSmsDispatcher;
@@ -165,6 +179,8 @@
     private TestSmsDispatcher mCdmaSmsDispatcher;
     private SmsDomainSelectionConnection mSmsDsc;
     private EmergencySmsDomainSelectionConnection mEmergencySmsDsc;
+    private EmergencyStateTracker mEmergencyStateTracker;
+    private CompletableFuture<Integer> mEmergencySmsFuture;
 
     private TestSmsDispatchersController mSmsDispatchersController;
     private boolean mInjectionCallbackTriggered = false;
@@ -174,10 +190,10 @@
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
         mTracker = mock(SMSDispatcher.SmsTracker.class);
+        mFeatureFlags = mock(FeatureFlags.class);
         setupMockPackagePermissionChecks();
         mSmsDispatchersController = new TestSmsDispatchersController(mPhone, mSmsStorageMonitor,
-            mSmsUsageMonitor, mTestableLooper.getLooper());
-        setUpDomainSelectionConnectionAsNotSupported();
+            mSmsUsageMonitor, mTestableLooper.getLooper(), mFeatureFlags);
         processAllMessages();
     }
 
@@ -191,6 +207,7 @@
         mDscFuture = null;
         mSmsDispatchersController.dispose();
         mSmsDispatchersController = null;
+        mFeatureFlags = null;
         super.tearDown();
     }
 
@@ -436,9 +453,11 @@
     public void testSendEmergencyTextWhenDomainPs() throws Exception {
         setUpDomainSelectionConnection();
         setUpSmsDispatchers();
+        setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
 
         mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
                 "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
 
         SmsDispatchersController.DomainSelectionConnectionHolder holder =
                 mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true);
@@ -463,12 +482,92 @@
 
     @Test
     @SmallTest
-    public void testNotifyDomainSelectionTerminated() throws Exception {
+    public void testSendEmergencyTextWhenEmergencyStateTrackerReturnsFailure() throws Exception {
         setUpDomainSelectionConnection();
         setUpSmsDispatchers();
+        setUpEmergencyStateTracker(DisconnectCause.OUT_OF_SERVICE);
+
+        mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
+
+        // Verify the domain selection requested regardless of the result of EmergencyStateTracker.
+        verify(mEmergencySmsDsc).requestDomainSelection(any(), any());
+    }
+
+    @Test
+    @SmallTest
+    public void testNotifySmsSentToEmergencyStateTracker() throws Exception {
+        setUpDomainSelectionEnabled(true);
+        setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+
+        mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L);
+        processAllMessages();
+
+        verify(mTelephonyManager).isEmergencyNumber(eq("911"));
+        verify(mEmergencyStateTracker).endSms(eq("1"), eq(true));
+    }
+
+    @Test
+    @SmallTest
+    public void testNotifySmsSentToEmergencyStateTrackerWithNonEmergencyNumber() throws Exception {
+        setUpDomainSelectionEnabled(true);
+        setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+
+        mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("1234", 1L);
+        processAllMessages();
+
+        verify(mTelephonyManager).isEmergencyNumber(eq("1234"));
+        verify(mEmergencyStateTracker, never()).endSms(anyString(), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testNotifySmsSentToEmergencyStateTrackerWithoutEmergencyStateTracker()
+            throws Exception {
+        setUpDomainSelectionEnabled(true);
+        mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L);
+
+        verify(mTelephonyManager, never()).isEmergencyNumber(anyString());
+    }
+
+    @Test
+    @SmallTest
+    public void testNotifySmsSentFailedToEmergencyStateTracker() throws Exception {
+        setUpDomainSelectionEnabled(true);
+        setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+
+        mSmsDispatchersController.testNotifySmsSentFailedToEmergencyStateTracker("911", 1L);
+        processAllMessages();
+
+        verify(mTelephonyManager).isEmergencyNumber(eq("911"));
+        verify(mEmergencyStateTracker).endSms(eq("1"), eq(false));
+    }
+
+    @Test
+    @SmallTest
+    public void testNotifySmsSentFailedToEmergencyStateTrackerWithNonEmergencyNumber()
+            throws Exception {
+        setUpDomainSelectionEnabled(true);
+        setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+
+        mSmsDispatchersController.testNotifySmsSentFailedToEmergencyStateTracker("1234", 1L);
+        processAllMessages();
+
+        verify(mTelephonyManager).isEmergencyNumber(eq("1234"));
+        verify(mEmergencyStateTracker, never()).endSms(anyString(), anyBoolean());
+    }
+
+    @Test
+    @SmallTest
+    public void testNotifyDomainSelectionTerminatedWhenImsAvailableAndNormalSms() throws Exception {
+        setUpDomainSelectionConnection();
+        setUpSmsDispatchers();
+        when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
 
         mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
                 "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
 
         SmsDispatchersController.DomainSelectionConnectionHolder holder =
                 mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
@@ -483,10 +582,7 @@
 
         DomainSelectionConnection.DomainSelectionConnectionCallback callback = captor.getValue();
         assertNotNull(callback);
-
-        mSmsDispatchersController.post(() -> {
-            callback.onSelectionTerminated(DisconnectCause.LOCAL);
-        });
+        callback.onSelectionTerminated(DisconnectCause.LOCAL);
         processAllMessages();
 
         verify(mSmsDsc, never()).finishSelection();
@@ -494,13 +590,49 @@
         assertFalse(holder.isDomainSelectionRequested());
         assertEquals(0, holder.getPendingRequests().size());
 
-        // We can use the IntentReceiver for receiving the sent result, but it can be reported as
-        // a flaky test since sometimes broadcasts can take a long time if the system is under load.
-        // At this point, we couldn't use the PendingIntent as a mock because it's a final class
-        // so this test checks the method in the IActivityManager when the PendingIntent#send(int)
-        // is called.
-        verify(mIActivityManager).sendIntentSender(any(), any(), any(),
-                eq(SmsManager.RESULT_ERROR_GENERIC_FAILURE), any(), any(), any(), any(), any());
+        verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
+                any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
+                eq(1L), eq(false));
+    }
+
+    @Test
+    @SmallTest
+    public void testNotifyDomainSelectionTerminatedWhenImsNotAvailableAndEmergencySms()
+            throws Exception {
+        setUpDomainSelectionConnection();
+        setUpSmsDispatchers();
+        setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+        when(mImsSmsDispatcher.isAvailable()).thenReturn(false);
+        when(mImsSmsDispatcher.isEmergencySmsSupport(anyString())).thenReturn(true);
+
+        mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
+
+        SmsDispatchersController.DomainSelectionConnectionHolder holder =
+                mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true);
+        ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> captor =
+                ArgumentCaptor.forClass(
+                        DomainSelectionConnection.DomainSelectionConnectionCallback.class);
+        verify(mEmergencySmsDsc).requestDomainSelection(any(), captor.capture());
+        assertNotNull(holder);
+        assertNotNull(holder.getConnection());
+        assertTrue(holder.isDomainSelectionRequested());
+        assertEquals(1, holder.getPendingRequests().size());
+
+        DomainSelectionConnection.DomainSelectionConnectionCallback callback = captor.getValue();
+        assertNotNull(callback);
+        callback.onSelectionTerminated(DisconnectCause.LOCAL);
+        processAllMessages();
+
+        verify(mEmergencySmsDsc, never()).finishSelection();
+        assertNull(holder.getConnection());
+        assertFalse(holder.isDomainSelectionRequested());
+        assertEquals(0, holder.getPendingRequests().size());
+
+        verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
+                any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
+                eq(1L), eq(false));
     }
 
     @Test
@@ -511,6 +643,7 @@
 
         mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
                 "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
 
         SmsDispatchersController.DomainSelectionConnectionHolder holder =
                 mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
@@ -521,6 +654,7 @@
 
         mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
                 "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
 
         verify(mSmsDsc).requestDomainSelection(any(), any());
         assertNotNull(holder.getConnection());
@@ -539,6 +673,23 @@
         assertEquals(0, holder.getPendingRequests().size());
     }
 
+    @Test
+    @SmallTest
+    public void testSendTextWhenFeatureFlagDisabledForSmsDomainSelection() throws Exception {
+        setUpDomainSelectionConnection();
+        setUpSmsDispatchers();
+        when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(false);
+
+        mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
+
+        // Expect that the domain selection logic will not be executed.
+        SmsDispatchersController.DomainSelectionConnectionHolder holder =
+                mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
+        assertNull(holder);
+    }
+
     private void switchImsSmsFormat(int phoneType) {
         mSimulatedCommands.setImsRegistrationState(new int[]{1, phoneType});
         mSimulatedCommands.notifyImsNetworkStateChanged();
@@ -553,7 +704,7 @@
         assertTrue(mSmsDispatchersController.setImsManager(imsManager));
     }
 
-    private void setUpDomainSelectionConnectionAsNotSupported() {
+    private void setUpDomainSelectionEnabled(boolean enabled) {
         mSmsDispatchersController.setDomainSelectionResolverProxy(
                 new SmsDispatchersController.DomainSelectionResolverProxy() {
                     @Override
@@ -566,9 +717,10 @@
 
                     @Override
                     public boolean isDomainSelectionSupported() {
-                        return false;
+                        return true;
                     }
                 });
+        when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(enabled);
     }
 
     private void setUpDomainSelectionConnection()  {
@@ -589,6 +741,7 @@
                         return true;
                     }
                 });
+        when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(true);
 
         mDscFuture = new CompletableFuture<>();
         when(mSmsDsc.requestDomainSelection(
@@ -620,6 +773,18 @@
                         | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT);
     }
 
+    private void setUpEmergencyStateTracker(int result) throws Exception {
+        mEmergencySmsFuture = new CompletableFuture<Integer>();
+        mEmergencyStateTracker = Mockito.mock(EmergencyStateTracker.class);
+        replaceInstance(SmsDispatchersController.class, "mEmergencyStateTracker",
+                mSmsDispatchersController, mEmergencyStateTracker);
+        when(mEmergencyStateTracker.startEmergencySms(any(Phone.class), anyString(), anyBoolean()))
+                .thenReturn(mEmergencySmsFuture);
+        doNothing().when(mEmergencyStateTracker).endSms(anyString(), anyBoolean());
+        mEmergencySmsFuture.complete(result);
+        when(mTelephonyManager.isEmergencyNumber(eq("911"))).thenReturn(true);
+    }
+
     private void sendDataWithDomainSelection(@NetworkRegistrationInfo.Domain int domain,
             boolean isCdmaMo) throws Exception {
         setUpDomainSelectionConnection();
@@ -628,6 +793,7 @@
         byte[] data = new byte[] { 0x01 };
         mSmsDispatchersController.testSendData(
                 "test-app", "1111", "2222", 8080, data, mSentIntent, null, false);
+        processAllMessages();
 
         SmsDispatchersController.DomainSelectionConnectionHolder holder =
                 mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
@@ -663,6 +829,7 @@
 
         mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
                 "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
 
         SmsDispatchersController.DomainSelectionConnectionHolder holder =
                 mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
@@ -704,6 +871,7 @@
         ArrayList<PendingIntent> deliveryIntents = new ArrayList<>();
         mSmsDispatchersController.testSendMultipartText("1111", "2222", parts, sentIntents,
                 deliveryIntents, null, "test-app", false, 0, false, 10, 1L);
+        processAllMessages();
 
         SmsDispatchersController.DomainSelectionConnectionHolder holder =
                 mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
@@ -746,6 +914,7 @@
         replaceInstance(SMSDispatcher.SmsTracker.class, "mFormat", mTracker, smsFormat);
 
         mSmsDispatchersController.sendRetrySms(mTracker);
+        processAllMessages();
 
         SmsDispatchersController.DomainSelectionConnectionHolder holder =
                 mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
@@ -782,6 +951,7 @@
         mTracker.mUsesImsServiceForIms = true;
 
         mSmsDispatchersController.sendRetrySms(mTracker);
+        processAllMessages();
 
         verify(mSmsDsc, never()).requestDomainSelection(any(), any());
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index 7c1ac2c..0be1927 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -869,7 +869,7 @@
         assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
                 Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
 
-        emergencyStateTracker.endSms(TEST_SMS_ID, getTestEmergencyNumber());
+        emergencyStateTracker.endSms(TEST_SMS_ID, true);
 
         verify(phone0).exitEmergencyMode(any(Message.class));
         assertFalse(emergencyStateTracker.isInEmergencyMode());
@@ -1316,7 +1316,7 @@
 
         assertTrue(emergencyStateTracker.isInEmergencyMode());
 
-        emergencyStateTracker.endSms(TEST_SMS_ID, getTestEmergencyNumber());
+        emergencyStateTracker.endSms(TEST_SMS_ID, true);
         processAllMessages();
 
         assertFalse(emergencyStateTracker.isInEmergencyMode());
@@ -1353,7 +1353,7 @@
         assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
                 Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
 
-        emergencyStateTracker.endSms(TEST_SMS_ID, getTestEmergencyNumber());
+        emergencyStateTracker.endSms(TEST_SMS_ID, true);
 
         assertTrue(emergencyStateTracker.isInEmergencyMode());
 
@@ -1400,7 +1400,7 @@
         assertTrue(emergencyStateTracker.isInEcm());
         assertFalse(emergencyStateTracker.isInEmergencyCall());
 
-        emergencyStateTracker.endSms(TEST_SMS_ID, getTestEmergencyNumber());
+        emergencyStateTracker.endSms(TEST_SMS_ID, true);
         processAllMessages();
 
         verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
@@ -1455,7 +1455,7 @@
 
         emergencyStateTracker.onEmergencyTransportChanged(
                 EmergencyStateTracker.EMERGENCY_TYPE_SMS, MODE_EMERGENCY_WWAN);
-        emergencyStateTracker.endSms(TEST_SMS_ID, getTestEmergencyNumber());
+        emergencyStateTracker.endSms(TEST_SMS_ID, true);
         processAllMessages();
 
         // Enter emergency callback mode and emergency mode changed by SMS end.
@@ -1502,7 +1502,7 @@
         assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
                 Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
 
-        emergencyStateTracker.endSms(TEST_SMS_ID, getTestEmergencyNumber());
+        emergencyStateTracker.endSms(TEST_SMS_ID, true);
 
         assertTrue(emergencyStateTracker.isInEmergencyMode());