Merge "Support Allowed service info fields service type and Service policy" into main
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index 906abfc..65cfbaf 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -69,4 +69,5 @@
     namespace: "telephony"
     description: "Used to notify the emergency callback mode for call/SMS to other applications."
     bug:"359064059"
+    is_exported: true
 }
diff --git a/flags/data.aconfig b/flags/data.aconfig
index ba1be88..17d1adb 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -127,4 +127,5 @@
   namespace: "telephony"
   description: "Support OEM_PAID and OEM_PRIVATE networks"
   bug: "366194627"
+  is_exported: true
 }
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index 4ce7508..703440f 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -155,6 +155,7 @@
     namespace: "telephony"
     description: "Used to expose SMS related hidden APIs for SMS over IMS to public API."
     bug:"359721349"
+    is_exported: true
 }
 
 # OWNER=jhyoon TARGET=25Q2
@@ -163,4 +164,5 @@
     namespace: "telephony"
     description: "This flag controls the type of API regarding MmTelFeature, either hidden or system type."
     bug:"359721349"
+    is_exported: true
 }
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 8662572..ee4570e 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -41,6 +41,7 @@
     namespace: "telephony"
     description: "This flag enables satellite carrier roaming to nb iot ntn."
     bug:"348253735"
+    is_exported: true
 }
 
 # OWNER=tnd TARGET=24Q4
@@ -78,4 +79,5 @@
   namespace: "telephony"
   description: "Introduce SatelliteManager APIs for carrier apps to monitor satellite state change"
   bug: "357638490"
+  is_exported: true
 }
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index aea9bd0..0522a3c 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -88,4 +88,5 @@
   namespace: "telephony"
   description: "Provide APIs to retrieve the status and recurrence rule info on a subscription plan"
   bug: "357272015"
+  is_exported: true
 }
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index aed4bff..edb4ce2 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -49,6 +49,7 @@
     namespace: "telephony"
     description: "This flag controls the visibility of the setCarrierRestrictionStatus API in carrierRestrictionRules class."
     bug:"342411308"
+    is_exported: true
 }
 
 # OWNER=arunvoddu TARGET=24Q4
@@ -87,6 +88,7 @@
     namespace: "telephony"
     description: "This flag controls the type of API that retrieves ISIM records, either hidden or system type."
     bug:"359721349"
+    is_exported: true
 }
 
 # OWNER=jinjeong TARGET=25Q2
@@ -95,6 +97,7 @@
     namespace: "telephony"
     description: "This flag controls to get a carrier id using a carrier identifier."
     bug:"378778278"
+    is_exported: true
 }
 
 # OWNER=arunvoddu TARGET=25Q2
@@ -107,3 +110,11 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+# OWNER=jinjeong TARGET=25Q2
+flag {
+    name: "get_group_id_level2"
+    namespace: "telephony"
+    description: "This flag controls to get a group id level2."
+    bug:"381171540"
+}
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index ee7447c..1b19c99 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -2952,4 +2952,39 @@
      * @param h Handler to be removed from the registrant list.
      */
     default void unregisterForSecurityAlgorithmUpdates(Handler h) {}
+
+    /**
+     * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
+     *                        supported by user subscription.
+     * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
+     *                             PLMNs that are not supported by the carrier and make sure not to
+     *                             attach to them.
+     * @param result Callback message to receive the result.
+     */
+    default void setSatellitePlmn(int simSlot,
+            @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList,
+            Message result) {}
+
+    /**
+     * Enable or disable satellite in the cellular modem associated with a carrier.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+     * @param result Callback message to receive the result.
+     */
+    default void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+            Message result) {}
+
+    /**
+     * Check whether satellite is enabled in the cellular modem associated with a carrier.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied.
+     * @param result Callback message to receive the result.
+     */
+    default void isSatelliteEnabledForCarrier(int simSlot, Message result) {}
 }
diff --git a/src/java/com/android/internal/telephony/NetworkResponse.java b/src/java/com/android/internal/telephony/NetworkResponse.java
index b4a37b3..ccf066f 100644
--- a/src/java/com/android/internal/telephony/NetworkResponse.java
+++ b/src/java/com/android/internal/telephony/NetworkResponse.java
@@ -551,6 +551,36 @@
         }
     }
 
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error
+     */
+    public void setSatellitePlmnResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_NETWORK, mRil, responseInfo);
+    }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error
+     */
+    public void setSatelliteEnabledForCarrierResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_NETWORK, mRil, responseInfo);
+    }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error.
+     * @param isEnabled Indicates whether satellite is enabled for carrier or not.
+     */
+    public void isSatelliteEnabledForCarrierResponse(RadioResponseInfo responseInfo,
+            boolean isEnabled) {
+        RILRequest rr = mRil.processResponse(HAL_SERVICE_NETWORK, responseInfo);
+
+        if (rr != null) {
+            if (responseInfo.error == RadioError.NONE) {
+                RadioResponse.sendMessageResponse(rr.mResult, isEnabled);
+            }
+            mRil.processResponseDone(rr, responseInfo, isEnabled);
+        }
+    }
+
     @Override
     public String getInterfaceHash() {
         return IRadioNetworkResponse.HASH;
diff --git a/src/java/com/android/internal/telephony/PhoneSubInfoController.java b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
index c40193e..9801542 100644
--- a/src/java/com/android/internal/telephony/PhoneSubInfoController.java
+++ b/src/java/com/android/internal/telephony/PhoneSubInfoController.java
@@ -659,6 +659,20 @@
                 });
     }
 
+    /**
+     * Return GroupIdLevel2 for the subscriber
+     */
+    public String getGroupIdLevel2ForSubscriber(int subId, String callingPackage,
+            String callingFeatureId) {
+        return callPhoneMethodForSubIdWithPrivilegedCheck(subId,
+                "getGroupIdLevel2", (phone)-> {
+                    enforceTelephonyFeatureWithException(callingPackage,
+                            PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+                            "getGroupIdLevel2ForSubscriber");
+                    return phone.getGroupIdLevel2();
+                });
+    }
+
     /** Below are utility methods that abstracts the flow that many public methods use:
      *  1. Check permission: pass, throw exception, or fails (returns false).
      *  2. clearCallingIdentity.
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 34ac832..1bb9984 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -181,6 +181,9 @@
     /** @hide */
     public static final HalVersion RADIO_HAL_VERSION_2_3 = new HalVersion(2, 3);
 
+    /** @hide */
+    public static final HalVersion RADIO_HAL_VERSION_2_4 = new HalVersion(2, 4);
+
     // Hal version
     private final Map<Integer, HalVersion> mHalVersion = new HashMap<>();
 
@@ -5352,6 +5355,102 @@
             });
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSatellitePlmn(int simSlot, @NonNull List<String> carrierPlmnList,
+            @NonNull List<String> allSatellitePlmnList, Message result) {
+        RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+        if (!canMakeRequest(
+                "setSatellitePlmn",
+                networkProxy,
+                result,
+                RADIO_HAL_VERSION_2_4)) {
+            return;
+        }
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_PLMN, result,
+                mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+                    + " simSlot=" + simSlot + " carrierPlmnList=" + carrierPlmnList
+                    + " allSatellitePlmnList=" + allSatellitePlmnList);
+        }
+
+        radioServiceInvokeHelper(
+                HAL_SERVICE_NETWORK,
+                rr,
+                "setSatellitePlmn",
+                () -> {
+                    networkProxy.setSatellitePlmn(rr.mSerial, simSlot, carrierPlmnList,
+                            allSatellitePlmnList);
+                });
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+            Message result) {
+        RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+        if (!canMakeRequest(
+                "setSatelliteEnabledForCarrier",
+                networkProxy,
+                result,
+                RADIO_HAL_VERSION_2_4)) {
+            return;
+        }
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER, result,
+                mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+                    + " simSlot=" + simSlot + " satelliteEnabled=" + satelliteEnabled);
+        }
+
+        radioServiceInvokeHelper(
+                HAL_SERVICE_NETWORK,
+                rr,
+                "setSatelliteEnabledForCarrier",
+                () -> {
+                    networkProxy.setSatelliteEnabledForCarrier(rr.mSerial, simSlot,
+                            satelliteEnabled);
+                });
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void isSatelliteEnabledForCarrier(int simSlot, Message result) {
+        RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+        if (!canMakeRequest(
+                "isSatelliteEnabledForCarrier",
+                networkProxy,
+                result,
+                RADIO_HAL_VERSION_2_4)) {
+            return;
+        }
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER, result,
+                mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+                    + " simSlot=" + simSlot);
+        }
+
+        radioServiceInvokeHelper(
+                HAL_SERVICE_NETWORK, rr, "isSatelliteEnabledForCarrier", () -> {
+                    networkProxy.isSatelliteEnabledForCarrier(rr.mSerial, simSlot);
+                });
+    }
+
+
     //***** Private Methods
     /**
      * This is a helper function to be called when an indication callback is called for any radio
@@ -6216,6 +6315,7 @@
             case 2: return RADIO_HAL_VERSION_2_1;
             case 3: return RADIO_HAL_VERSION_2_2;
             case 4: return RADIO_HAL_VERSION_2_3;
+            case 5: return RADIO_HAL_VERSION_2_4;
             default: return RADIO_HAL_VERSION_UNKNOWN;
         }
     }
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index cbf2330..e39e135 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -121,6 +121,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_N1_MODE_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NULL_CIPHER_AND_INTEGRITY_ENABLED;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_SECURITY_ALGORITHMS_UPDATED_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_VONR_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_CALL_FAIL_CAUSE;
@@ -180,6 +181,8 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_RADIO_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_PLMN;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIM_CARD_POWER;
@@ -5288,6 +5291,12 @@
                 return "IS_SECURITY_ALGORITHMS_UPDATED_ENABLED";
             case RIL_REQUEST_GET_SIMULTANEOUS_CALLING_SUPPORT:
                 return "GET_SIMULTANEOUS_CALLING_SUPPORT";
+            case RIL_REQUEST_SET_SATELLITE_PLMN:
+                return "SET_SATELLITE_PLMN";
+            case RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER:
+                return "SET_SATELLITE_ENABLED_FOR_CARRIER";
+            case RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER:
+                return "IS_SATELLITE_ENABLED_FOR_CARRIER";
             default:
                 return "<unknown request " + request + ">";
         }
diff --git a/src/java/com/android/internal/telephony/RadioNetworkProxy.java b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
index 4acc71a..12e6c90 100644
--- a/src/java/com/android/internal/telephony/RadioNetworkProxy.java
+++ b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
@@ -979,4 +979,60 @@
         }
         // Only supported on AIDL.
     }
+
+   /**
+     * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+     *
+     * @param serial Serial number of request.
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
+     *                        supported by user subscription.
+     * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
+     *                             PLMNs that are not supported by the carrier and make sure not to
+     *                             attach to them.
+     */
+    public void setSatellitePlmn(int serial, int simSlot, List<String> carrierPlmnList,
+            List<String> allSatellitePlmnList) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            String[] carrierPlmnArray = carrierPlmnList.toArray(new String[0]);
+            String[] allSatellitePlmnArray = allSatellitePlmnList.toArray(new String[0]);
+            mNetworkProxy.setSatellitePlmn(serial, simSlot, carrierPlmnArray,
+                    allSatellitePlmnArray);
+        }
+        // Only supported on AIDL.
+    }
+
+    /**
+     * Enable or disable satellite in the cellular modem associated with a carrier.
+     *
+     * @param serial Serial number of request.
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+     */
+    public void setSatelliteEnabledForCarrier(int serial, int simSlot,
+            boolean satelliteEnabled) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mNetworkProxy.setSatelliteEnabledForCarrier(serial, simSlot, satelliteEnabled);
+        }
+        // Only supported on AIDL.
+    }
+
+    /**
+     * Check whether satellite is enabled in the cellular modem associated with a carrier.
+     *
+     * @param serial Serial number of request.
+     * @param simSlot Indicates the SIM slot to which this API will be applied.
+     */
+    public void isSatelliteEnabledForCarrier(int serial, int simSlot)
+            throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mNetworkProxy.isSatelliteEnabledForCarrier(serial, simSlot);
+        }
+        // Only supported on AIDL.
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index 9f6edf2..acd3fd1 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony.satellite;
 
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@@ -419,6 +420,15 @@
                     && mSatelltieModemState == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
                 return false;
             }
+            boolean allowCheckMessageInNotConnected =
+                    mContext.getResources().getBoolean(
+                            R.bool.config_satellite_allow_check_message_in_not_connected);
+            if (datagramType == DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS
+                    && mSatelltieModemState == SATELLITE_MODEM_STATE_NOT_CONNECTED
+                    && allowCheckMessageInNotConnected
+                    && mFeatureFlags.carrierRoamingNbIotNtn()) {
+                return false;
+            }
             if (mSatelltieModemState != SATELLITE_MODEM_STATE_CONNECTED
                     && mSatelltieModemState != SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING) {
                 return true;
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 6937b74..64bd2b7 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -307,7 +307,8 @@
     }
 
     private void handleSatelliteProvisionStateChangedEvent(boolean provisioned) {
-        if (!provisioned) {
+        if (!provisioned
+                && !isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
             cleanUpResources(false);
         }
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
index 21731f0..271e0ad 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -16,10 +16,12 @@
 
 package com.android.internal.telephony.satellite;
 
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@@ -44,6 +46,7 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import com.android.internal.R;
 import com.android.internal.telephony.TelephonyTest;
 
 import org.junit.After;
@@ -187,6 +190,76 @@
         }
     }
 
+    @Test
+    public void testNeedsWaitingForSatelliteConnected_checkMessageInNotConnected_returnsFalse()
+            throws Exception {
+        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+        mDatagramControllerUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+        boolean result =
+                mDatagramControllerUT.needsWaitingForSatelliteConnected(
+                        DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS);
+
+        assertFalse(result);
+    }
+
+    @Test
+    public void testNeedsWaitingForSatelliteConnected_regularSmsInNotConnected_returnsTrue()
+            throws Exception {
+        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+        mDatagramControllerUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+        boolean result =
+                mDatagramControllerUT.needsWaitingForSatelliteConnected(
+                        DATAGRAM_TYPE_SMS);
+
+        assertTrue(result);
+    }
+
+    @Test
+    public void
+            testNeedsWaitingForSatelliteConnected_checkMessageInNotConnected_allowCheckMessageFalse_returnsTrue()
+                    throws Exception {
+        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, false);
+        mDatagramControllerUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+        boolean result =
+                mDatagramControllerUT.needsWaitingForSatelliteConnected(
+                        DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS);
+
+        assertTrue(result);
+    }
+
+    @Test
+    public void
+            testNeedsWaitingForSatelliteConnected_checkMessageInNotConnected_carrierRoamingNbIotNtnFalse_returnsTrue()
+                    throws Exception {
+        when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+        mDatagramControllerUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+        boolean result =
+                mDatagramControllerUT.needsWaitingForSatelliteConnected(
+                        DATAGRAM_TYPE_CHECK_PENDING_INCOMING_SMS);
+
+        assertTrue(result);
+    }
+
     private void testUpdateSendStatus(boolean isDemoMode, int datagramType, int sendState) {
         mDatagramControllerUT.setDemoMode(isDemoMode);
         clearAllInvocations();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
index 46847aa..529088b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -373,6 +373,7 @@
 
     @Test
     public void testSatelliteProvisionStateChangedBeforeTimeout() {
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
 
@@ -393,6 +394,7 @@
         assertFalse(mTestSOSMessageRecommender.isDialerNotified());
         reset(mMockSatelliteStats);
 
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());