Merge "Add satellite DemoSimulator." into 24D1-dev
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index 136e997..bc1e1a8 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -781,22 +781,16 @@
             if (isSmsDomainSelectionEnabled()) {
                 TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
                 boolean isEmergency = tm.isEmergencyNumber(tracker.mDestAddress);
-                DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency);
-
-                // If the DomainSelectionConnection is not available,
-                // fallback to the legacy implementation.
-                if (holder != null && holder.getConnection() != null) {
-                    // This may be invoked by another thread, so this operation is posted and
-                    // handled through the execution flow of SmsDispatchersController.
-                    SomeArgs args = SomeArgs.obtain();
-                    args.arg1 = holder;
-                    args.arg2 = new PendingRequest(PendingRequest.TYPE_RETRY_SMS, tracker,
-                            null, null, null, null, null, false, null, 0, null, null, false,
-                            0, false, 0, 0L, false);
-                    args.arg3 = "sendRetrySms";
-                    sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
-                    return;
-                }
+                // This may be invoked by another thread, so this operation is posted and
+                // handled through the execution flow of SmsDispatchersController.
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = getDomainSelectionConnectionHolder(isEmergency);
+                args.arg2 = new PendingRequest(PendingRequest.TYPE_RETRY_SMS, tracker,
+                        null, null, null, null, null, false, null, 0, null, null, false,
+                        0, false, 0, 0L, false);
+                args.arg3 = "sendRetrySms";
+                sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
+                return;
             }
 
             if (mImsSmsDispatcher.isAvailable()) {
@@ -1007,52 +1001,23 @@
      * Returns a {@link DomainSelectionConnectionHolder} according to the flag specified.
      *
      * @param emergency The flag to indicate that the domain selection is for an emergency SMS.
-     * @return A {@link DomainSelectionConnectionHolder} instance or null.
+     * @return A {@link DomainSelectionConnectionHolder} instance.
      */
     @VisibleForTesting
     @Nullable
     protected DomainSelectionConnectionHolder getDomainSelectionConnectionHolder(
             boolean emergency) {
-        return emergency ? mEmergencyDscHolder : mDscHolder;
-    }
-
-    /**
-     * Returns a {@link DomainSelectionConnectionHolder} if the domain selection supports,
-     * return null otherwise.
-     *
-     * @param emergency The flag to indicate that the domain selection is for an emergency SMS.
-     * @return A {@link DomainSelectionConnectionHolder} that grabs the
-     *         {@link DomainSelectionConnection} and its related information to use the domain
-     *         selection architecture.
-     */
-    private DomainSelectionConnectionHolder getDomainSelectionConnection(boolean emergency) {
-        DomainSelectionConnectionHolder holder = getDomainSelectionConnectionHolder(emergency);
-        DomainSelectionConnection connection = (holder != null) ? holder.getConnection() : null;
-
-        if (connection == null) {
-            connection = mDomainSelectionResolverProxy.getDomainSelectionConnection(
-                    mPhone, DomainSelectionService.SELECTOR_TYPE_SMS, emergency);
-
-            if (connection == null) {
-                // Domain selection architecture is not supported.
-                // Use the legacy architecture.
-                return null;
+        if (emergency) {
+            if (mEmergencyDscHolder == null) {
+                mEmergencyDscHolder = new DomainSelectionConnectionHolder(emergency);
             }
-        }
-
-        if (holder == null) {
-            holder = new DomainSelectionConnectionHolder(emergency);
-
-            if (emergency) {
-                mEmergencyDscHolder = holder;
-            } else {
-                mDscHolder = holder;
+            return mEmergencyDscHolder;
+        } else {
+            if (mDscHolder == null) {
+                mDscHolder = new DomainSelectionConnectionHolder(emergency);
             }
+            return mDscHolder;
         }
-
-        holder.setConnection(connection);
-
-        return holder;
     }
 
     /**
@@ -1102,6 +1067,8 @@
      *
      * @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 string.
      */
     private void requestDomainSelection(@NonNull DomainSelectionConnectionHolder holder,
@@ -1111,6 +1078,21 @@
         // the domain selection by adding this request to the pending list.
         holder.addRequest(request);
 
+        if (holder.getConnection() == null) {
+            DomainSelectionConnection connection =
+                    mDomainSelectionResolverProxy.getDomainSelectionConnection(
+                            mPhone, DomainSelectionService.SELECTOR_TYPE_SMS, holder.isEmergency());
+            if (connection == null) {
+                logd("requestDomainSelection: fallback for " + logTag);
+                // If the domain selection connection is not available,
+                // fallback to the legacy implementation.
+                sendAllPendingRequests(holder, NetworkRegistrationInfo.DOMAIN_UNKNOWN);
+                return;
+            } else {
+                holder.setConnection(connection);
+            }
+        }
+
         if (!isDomainSelectionRequested) {
             if (VDBG) {
                 logd("requestDomainSelection: " + logTag);
@@ -1571,19 +1553,13 @@
         }
 
         if (isSmsDomainSelectionEnabled()) {
-            DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false);
-
-            // If the DomainSelectionConnection is not available,
-            // fallback to the legacy implementation.
-            if (holder != null && holder.getConnection() != null) {
-                sendSmsUsingDomainSelection(holder,
-                        new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage,
-                                destAddr, scAddr, asArrayList(sentIntent),
-                                asArrayList(deliveryIntent), isForVvm, data, destPort, null, null,
-                                false, 0, false, 0, 0L, false),
-                        "sendData");
-                return;
-            }
+            sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(false),
+                    new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage,
+                            destAddr, scAddr, asArrayList(sentIntent),
+                            asArrayList(deliveryIntent), isForVvm, data, destPort, null, null,
+                            false, 0, false, 0, 0L, false),
+                    "sendData");
+            return;
         }
 
         if (mImsSmsDispatcher.isAvailable()) {
@@ -1812,20 +1788,14 @@
         if (isSmsDomainSelectionEnabled()) {
             TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
             boolean isEmergency = tm.isEmergencyNumber(destAddr);
-            DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency);
-
-            // If the DomainSelectionConnection is not available,
-            // fallback to the legacy implementation.
-            if (holder != null && holder.getConnection() != null) {
-                sendSmsUsingDomainSelection(holder,
-                        new PendingRequest(PendingRequest.TYPE_TEXT, null, callingPkg,
-                                destAddr, scAddr, asArrayList(sentIntent),
-                                asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
-                                messageUri, persistMessage, priority, expectMore, validityPeriod,
-                                messageId, skipShortCodeCheck),
-                        "sendText");
-                return;
-            }
+            sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
+                    new PendingRequest(PendingRequest.TYPE_TEXT, null, callingPkg,
+                            destAddr, scAddr, asArrayList(sentIntent),
+                            asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
+                            messageUri, persistMessage, priority, expectMore, validityPeriod,
+                            messageId, skipShortCodeCheck),
+                    "sendText");
+            return;
         }
 
         if (mImsSmsDispatcher.isAvailable() || mImsSmsDispatcher.isEmergencySmsSupport(destAddr)) {
@@ -1961,19 +1931,13 @@
         if (isSmsDomainSelectionEnabled()) {
             TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
             boolean isEmergency = tm.isEmergencyNumber(destAddr);
-            DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency);
-
-            // If the DomainSelectionConnection is not available,
-            // fallback to the legacy implementation.
-            if (holder != null && holder.getConnection() != null) {
-                sendSmsUsingDomainSelection(holder,
-                        new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
-                                callingPkg, destAddr, scAddr, sentIntents, deliveryIntents, false,
-                                null, 0, parts, messageUri, persistMessage, priority, expectMore,
-                                validityPeriod, messageId, false),
-                        "sendMultipartText");
-                return;
-            }
+            sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
+                    new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
+                            callingPkg, destAddr, scAddr, sentIntents, deliveryIntents, false,
+                            null, 0, parts, messageUri, persistMessage, priority, expectMore,
+                            validityPeriod, messageId, false),
+                    "sendMultipartText");
+            return;
         }
 
         if (mImsSmsDispatcher.isAvailable()) {
diff --git a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
index ff90978..d4830ae 100644
--- a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
@@ -62,14 +62,12 @@
     private final PersistAtomsStorage mStorage;
     private final DeviceStateHelper mDeviceStateHelper;
     private boolean mExistAnyConnectedInternetPdn;
-    private final SatelliteController mSatelliteController;
 
     public ServiceStateStats(Phone phone) {
         super(Runnable::run);
         mPhone = phone;
         mStorage = PhoneFactory.getMetricsCollector().getAtomsStorage();
         mDeviceStateHelper = PhoneFactory.getMetricsCollector().getDeviceStateHelper();
-        mSatelliteController = SatelliteController.getInstance();
     }
 
     /** Finalizes the durations of the current service state segment. */
@@ -121,6 +119,7 @@
             // Finish the duration of last service state and mark modem off
             addServiceState(mLastState.getAndSet(new TimestampedServiceState(null, now)), now);
         } else {
+            SatelliteController satelliteController = SatelliteController.getInstance();
             CellularServiceState newState = new CellularServiceState();
             newState.voiceRat = getVoiceRat(mPhone, serviceState);
             newState.dataRat = getRat(serviceState, NetworkRegistrationInfo.DOMAIN_PS);
@@ -138,8 +137,8 @@
             newState.overrideVoiceService = mOverrideVoiceService.get();
             newState.isDataEnabled = mPhone.getDataSettingsManager().isDataEnabled();
             newState.isIwlanCrossSim = isCrossSimCallingRegistered(mPhone);
-            newState.isNtn = mSatelliteController != null
-                    ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false;
+            newState.isNtn = satelliteController != null
+                    && satelliteController.isInSatelliteModeForCarrierRoaming(mPhone);
             TimestampedServiceState prevState =
                     mLastState.getAndSet(new TimestampedServiceState(newState, now));
             addServiceStateAndSwitch(
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 6d90a79..f764b2b 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -277,9 +277,6 @@
                         mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
                                 SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
                                 getPendingDatagramCount(), error);
-                        mControllerMetricsStats.reportOutgoingDatagramSuccessCount(
-                                argument.datagramType, mIsDemoMode);
-                        mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram();
                         startWaitForSimulatedPollDatagramsDelayTimer(request);
                         if (getPendingDatagramCount() > 0) {
                             // Send response for current datagram
@@ -306,9 +303,6 @@
                         // after updating datagram transfer state internally.
                         argument.callback.accept(error);
                         // Abort sending all the pending datagrams
-                        mControllerMetricsStats.reportOutgoingDatagramFailCount(
-                                argument.datagramType, mIsDemoMode);
-                        mSessionMetricsStats.addCountOfFailedOutgoingDatagram();
                         abortSendingPendingDatagrams(argument.subId,
                                 SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
                     }
@@ -550,8 +544,6 @@
                 pendingDatagramsMap.entrySet()) {
             SendSatelliteDatagramArgument argument = entry.getValue();
             reportSendDatagramCompleted(argument, errorCode);
-            mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType,
-                    mIsDemoMode);
             argument.callback.accept(errorCode);
         }
 
@@ -610,6 +602,15 @@
                                 ? (System.currentTimeMillis() - argument.datagramStartTime) : 0)
                         .setIsDemoMode(mIsDemoMode)
                         .build());
+        if (resultCode == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+            mControllerMetricsStats.reportOutgoingDatagramSuccessCount(argument.datagramType,
+                    mIsDemoMode);
+            mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram();
+        } else {
+            mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType,
+                    mIsDemoMode);
+            mSessionMetricsStats.addCountOfFailedOutgoingDatagram();
+        }
     }
 
     /**
@@ -733,9 +734,6 @@
                     0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
             abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
                     SATELLITE_RESULT_NOT_REACHABLE);
-            mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType,
-                    mIsDemoMode);
-            mSessionMetricsStats.addCountOfFailedOutgoingDatagram();
         }
     }
 
@@ -798,8 +796,6 @@
 
             // Log metrics about the outgoing datagram
             reportSendDatagramCompleted(argument, SATELLITE_RESULT_MODEM_TIMEOUT);
-            mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType,
-                    mIsDemoMode);
             // Remove current datagram from pending map.
             if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) {
                 mPendingEmergencyDatagramsMap.remove(argument.datagramId);
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index ce41d6e..c0917fe 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -3771,11 +3771,6 @@
 
     private void processNewCarrierConfigData(int subId) {
         configureSatellitePlmnForCarrier(subId);
-        synchronized (mIsSatelliteEnabledLock) {
-            mSatelliteAttachRestrictionForCarrierArray.clear();
-            mIsSatelliteAttachEnabledForCarrierArrayPerSub.clear();
-        }
-
         setSatelliteAttachEnabledForCarrierOnSimLoaded(subId);
         updateRestrictReasonForEntitlementPerCarrier(subId);
     }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 76e5661..c497ca1 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -439,7 +439,8 @@
             ServiceState serviceState = phone.getServiceState();
             if (serviceState != null) {
                 int state = serviceState.getState();
-                if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY)
+                if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY
+                        || serviceState.isEmergencyOnly())
                         && !serviceState.isUsingNonTerrestrialNetwork()) {
                     logv("isCellularAvailable true");
                     return true;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 81712c6..414fb3b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -816,15 +816,237 @@
         setUpDomainSelectionConnection();
         setUpSmsDispatchers();
         when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(false);
+        when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
+
+        mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+
+        // Expect that the domain selection is not executed and
+        // ImsSmsDispatcher handles this text directly.
+        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 testSendTextWhenDomainSelectionFinishedAndNewTextSent() throws Exception {
+        setUpDomainSelectionConnection();
+        setUpSmsDispatchers();
 
         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);
+        verify(mSmsDsc).requestDomainSelection(any(), any());
+        assertNotNull(holder);
+        assertNotNull(holder.getConnection());
+        assertTrue(holder.isDomainSelectionRequested());
+        assertEquals(1, holder.getPendingRequests().size());
+
+        // Expect that finishDomainSelection is called while a new pending request is posted.
+        mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+
+        SmsDomainSelectionConnection newSmsDsc = Mockito.mock(SmsDomainSelectionConnection.class);
+        mSmsDispatchersController.setDomainSelectionResolverProxy(
+                new SmsDispatchersController.DomainSelectionResolverProxy() {
+                    @Override
+                    @Nullable
+                    public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+                            @DomainSelectionService.SelectorType int selectorType,
+                            boolean isEmergency) {
+                        return newSmsDsc;
+                    }
+
+                    @Override
+                    public boolean isDomainSelectionSupported() {
+                        return true;
+                    }
+                });
+        CompletableFuture newDscFuture = new CompletableFuture<>();
+        when(newSmsDsc.requestDomainSelection(
+                any(DomainSelectionService.SelectionAttributes.class),
+                any(DomainSelectionConnection.DomainSelectionConnectionCallback.class)))
+                .thenReturn(newDscFuture);
+
+        // Expect that new domain selection connection is created and domain selection is performed.
+        mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
+
+        verify(mSmsDsc).finishSelection();
+
+        verify(newSmsDsc).requestDomainSelection(any(), any());
+        assertNotNull(holder.getConnection());
+        assertTrue(holder.isDomainSelectionRequested());
+        assertEquals(1, holder.getPendingRequests().size());
+
+        newDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+        processAllMessages();
+
+        verify(newSmsDsc).finishSelection();
+        verify(mImsSmsDispatcher, times(2)).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));
+        assertNull(holder.getConnection());
+        assertFalse(holder.isDomainSelectionRequested());
+        assertEquals(0, holder.getPendingRequests().size());
+    }
+
+    @Test
+    @SmallTest
+    public void testSendTextForEmergencyWhenDomainSelectionFinishedAndNewTextSent()
+            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);
+        verify(mEmergencySmsDsc).requestDomainSelection(any(), any());
+        assertNotNull(holder);
+        assertNotNull(holder.getConnection());
+        assertTrue(holder.isEmergency());
+        assertTrue(holder.isDomainSelectionRequested());
+        assertEquals(1, holder.getPendingRequests().size());
+
+        // Expect that finishDomainSelection is called while a new pending request is posted.
+        mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+
+        EmergencySmsDomainSelectionConnection newEmergencySmsDsc =
+                Mockito.mock(EmergencySmsDomainSelectionConnection.class);
+        mSmsDispatchersController.setDomainSelectionResolverProxy(
+                new SmsDispatchersController.DomainSelectionResolverProxy() {
+                    @Override
+                    @Nullable
+                    public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+                            @DomainSelectionService.SelectorType int selectorType,
+                            boolean isEmergency) {
+                        return newEmergencySmsDsc;
+                    }
+
+                    @Override
+                    public boolean isDomainSelectionSupported() {
+                        return true;
+                    }
+                });
+        CompletableFuture newDscFuture = new CompletableFuture<>();
+        when(newEmergencySmsDsc.requestDomainSelection(
+                any(DomainSelectionService.SelectionAttributes.class),
+                any(DomainSelectionConnection.DomainSelectionConnectionCallback.class)))
+                .thenReturn(newDscFuture);
+
+        // Expect that new domain selection connection is created and domain selection is performed.
+        mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
+
+        verify(mEmergencySmsDsc).finishSelection();
+
+        verify(newEmergencySmsDsc).requestDomainSelection(any(), any());
+        assertNotNull(holder.getConnection());
+        assertTrue(holder.isDomainSelectionRequested());
+        assertEquals(1, holder.getPendingRequests().size());
+
+        newDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+        processAllMessages();
+
+        verify(newEmergencySmsDsc).finishSelection();
+        verify(mImsSmsDispatcher, times(2)).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));
+        assertNull(holder.getConnection());
+        assertFalse(holder.isDomainSelectionRequested());
+        assertEquals(0, holder.getPendingRequests().size());
+    }
+
+    @Test
+    @SmallTest
+    public void testSendTextFallbackWhenDomainSelectionConnectionNotCreated() throws Exception {
+        mSmsDispatchersController.setDomainSelectionResolverProxy(
+                new SmsDispatchersController.DomainSelectionResolverProxy() {
+                    @Override
+                    @Nullable
+                    public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+                            @DomainSelectionService.SelectorType int selectorType,
+                            boolean isEmergency) {
+                        return null;
+                    }
+
+                    @Override
+                    public boolean isDomainSelectionSupported() {
+                        return true;
+                    }
+                });
+        when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(true);
+        setUpSmsDispatchers();
+        when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
+
+        // Expect that creating a domain selection connection is failed and
+        // fallback to the legacy implementation.
+        mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
+
+        SmsDispatchersController.DomainSelectionConnectionHolder holder =
+                mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
+        assertNotNull(holder);
+        assertNull(holder.getConnection());
+        assertFalse(holder.isDomainSelectionRequested());
+        assertEquals(0, holder.getPendingRequests().size());
+
+        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 testSendTextFallbackForEmergencyWhenDomainSelectionConnectionNotCreated()
+            throws Exception {
+        mSmsDispatchersController.setDomainSelectionResolverProxy(
+                new SmsDispatchersController.DomainSelectionResolverProxy() {
+                    @Override
+                    @Nullable
+                    public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+                            @DomainSelectionService.SelectorType int selectorType,
+                            boolean isEmergency) {
+                        return null;
+                    }
+
+                    @Override
+                    public boolean isDomainSelectionSupported() {
+                        return true;
+                    }
+                });
+        when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(true);
+        setUpSmsDispatchers();
+        setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+        when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
+
+        // Expect that creating a domain selection connection is failed and
+        // fallback to the legacy implementation.
+        mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
+                "test-app", false, 0, false, 10, false, 1L, false);
+        processAllMessages();
+
+        SmsDispatchersController.DomainSelectionConnectionHolder holder =
+                mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true);
+        assertNotNull(holder);
+        assertNull(holder.getConnection());
+        assertTrue(holder.isEmergency());
+        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));
     }
 
     private void switchImsSmsFormat(int phoneType) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index 4b02cc1..4896671 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -237,10 +237,7 @@
 
             clearInvocations(mMockSatelliteModemInterface);
             clearInvocations(mMockDatagramController);
-            mResultListener.clear();
-
-            clearInvocations(mMockSatelliteModemInterface);
-            clearInvocations(mMockDatagramController);
+            clearInvocations(mMockSessionMetricsStats);
             mResultListener.clear();
             doReturn(true).when(mMockDatagramController)
                     .needsWaitingForSatelliteConnected(eq(datagramType));
@@ -282,6 +279,7 @@
 
             clearInvocations(mMockSatelliteModemInterface);
             clearInvocations(mMockDatagramController);
+            clearInvocations(mMockSessionMetricsStats);
             mResultListener.clear();
             mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
                     true, mResultListener::offer);
@@ -356,6 +354,7 @@
         verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulOutgoingDatagram();
         clearInvocations(mMockSatelliteModemInterface);
         clearInvocations(mMockDatagramController);
+        clearInvocations(mMockSessionMetricsStats);
         mResultListener.clear();
 
         // No response for the send request from modem
@@ -385,7 +384,7 @@
                 any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
         verify(mMockSatelliteModemInterface).abortSendingSatelliteDatagrams(any(Message.class));
         assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_MODEM_TIMEOUT);
-        verify(mMockSessionMetricsStats, never()).addCountOfFailedOutgoingDatagram();
+        verify(mMockSessionMetricsStats, times(1)).addCountOfFailedOutgoingDatagram();
     }
 
     @Test