Merge cherrypicks of ['googleplex-android-review.googlesource.com/30772089', 'googleplex-android-review.googlesource.com/30827344', 'googleplex-android-review.googlesource.com/30664691'] into 25Q1-release.

Change-Id: I5e84ec08125e75fc3b507686fc989c0b83b3fe02
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 113c3ee..5c3bcb0 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -20,6 +20,7 @@
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SMS;
 import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
@@ -418,7 +419,7 @@
             case EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT: {
                 synchronized (mLock) {
                     mIsMtSmsPollingThrottled = false;
-                    if (mIsAligned && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
+                    if (allowMtSmsPolling()) {
                         sendMtSmsPollingMessage();
                     }
                 }
@@ -514,8 +515,7 @@
             mIsAligned = isAligned;
             plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
             if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
-            if (isAligned && !mIsMtSmsPollingThrottled
-                    && mModemState == SATELLITE_MODEM_STATE_CONNECTED) {
+            if (allowMtSmsPolling()) {
                 sendMtSmsPollingMessage();
             }
         }
@@ -810,9 +810,6 @@
                     stopDatagramWaitForConnectedStateTimer();
                     sendPendingMessages();
                 }
-                if (mIsAligned && !mIsMtSmsPollingThrottled) {
-                    sendMtSmsPollingMessage();
-                }
             }
 
             if (state == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
@@ -821,6 +818,10 @@
                     mShouldPollMtSms = shouldPollMtSms();
                 }
             }
+
+            if (allowMtSmsPolling()) {
+                sendMtSmsPollingMessage();
+            }
         }
     }
 
@@ -1334,6 +1335,32 @@
         removeMessages(EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT);
     }
 
+    @GuardedBy("mLock")
+    private boolean allowMtSmsPolling() {
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) return false;
+
+        if (mIsMtSmsPollingThrottled) return false;
+
+        if (!mIsAligned) return false;
+
+        boolean isModemStateConnectedOrTransferring =
+                mModemState == SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED
+                        || mModemState
+                                == SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
+        if (!isModemStateConnectedOrTransferring && !allowCheckMessageInNotConnected()) {
+            plogd("EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT:"
+                    + " allow_check_message_in_not_connected is disabled");
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean allowCheckMessageInNotConnected() {
+        return mContext.getResources()
+                .getBoolean(R.bool.config_satellite_allow_check_message_in_not_connected);
+    }
+
     private static void logd(@NonNull String log) {
         Rlog.d(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index a1354ac..a44b251 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -139,6 +139,7 @@
 import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
 import android.telephony.satellite.NtnSignalStrength;
 import android.telephony.satellite.SatelliteCapabilities;
+import android.telephony.satellite.SatelliteCommunicationAllowedStateCallback;
 import android.telephony.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteModemEnableRequestAttributes;
@@ -146,6 +147,7 @@
 import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
 import android.telephony.satellite.SatelliteSubscriptionInfo;
 import android.telephony.satellite.SystemSelectionSpecifier;
+import android.telephony.satellite.SatelliteAccessConfiguration;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
@@ -319,6 +321,7 @@
     @NonNull private final ProvisionMetricsStats mProvisionMetricsStats;
     @NonNull private SessionMetricsStats mSessionMetricsStats;
     @NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats;
+
     @NonNull private final SubscriptionManagerService mSubscriptionManagerService;
     @NonNull private final TelephonyCountryDetector mCountryDetector;
     @NonNull private final TelecomManager mTelecomManager;
@@ -391,6 +394,8 @@
             new AtomicBoolean(false);
     private final AtomicBoolean mRegisteredForTerrestrialNetworkAvailableChanged =
             new AtomicBoolean(false);
+    private final AtomicBoolean mRegisteredForSatelliteCommunicationAllowedStateChanged =
+        new AtomicBoolean(false);
     /**
      * Map key: subId, value: callback to get error code of the provision request.
      */
@@ -725,6 +730,15 @@
     // device.
     private List<DeviceState> mDeviceStates = new ArrayList();
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected final Object mSatelliteAccessConfigLock = new Object();
+    @GuardedBy("mSatelliteAccessConfigLock")
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected List<Integer> mCurrentLocationTagIds = new ArrayList();
+    @GuardedBy("mSatelliteAccessConfigLock")
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected boolean mSatelliteAccessAllowed = false;
+
     public static final int RESULT_RECEIVER_COUNT_ANOMALY_THRESHOLD = 500;
     protected final Object mResultReceiverTotalCountLock = new Object();
     @GuardedBy("mResultReceiverTotalCountLock")
@@ -884,6 +898,7 @@
         registerForSatelliteModemStateChanged();
         registerForServiceStateChanged();
         registerForSignalStrengthChanged();
+        registerForSatelliteCommunicationAllowedStateChanged();
         mContentResolver = mContext.getContentResolver();
         mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
 
@@ -3961,28 +3976,30 @@
     }
 
     /**
-     * @return {@code true} if the device is connected to satellite via any carrier within the
+     * @return {@code true} and the corresponding subId if the device is connected to
+     * satellite via any carrier within the
      * {@link CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
-     * duration, {@code false} otherwise.
+     * duration, {@code false} and null otherwise.
      */
-    public boolean isSatelliteConnectedViaCarrierWithinHysteresisTime() {
+    public Pair<Boolean, Integer> isSatelliteConnectedViaCarrierWithinHysteresisTime() {
         if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
             logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: carrierEnabledSatelliteFlag"
                     + " is disabled");
-            return false;
+            return new Pair<>(false, null);
         }
-        if (isUsingNonTerrestrialNetworkViaCarrier().first) {
-            return true;
+        Pair<Boolean, Integer> ntnConnectedState = isUsingNonTerrestrialNetworkViaCarrier();
+        if (ntnConnectedState.first) {
+            return ntnConnectedState;
         }
         for (Phone phone : PhoneFactory.getPhones()) {
             if (isInSatelliteModeForCarrierRoaming(phone)) {
                 logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: "
                         + "subId:" + phone.getSubId()
                         + " is connected to satellite within hysteresis time");
-                return true;
+                return new Pair<>(true, phone.getSubId());
             }
         }
-        return false;
+        return new Pair<>(false, null);
     }
 
     /**
@@ -4185,7 +4202,7 @@
         return DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS;
     }
 
-    private int getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId) {
+    public int getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId) {
         PersistableBundle config = getPersistableBundle(subId);
         return config.getInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT);
     }
@@ -4546,12 +4563,22 @@
             return null;
         }
         String iccid = subInfo.getIccId();
-        String apn = getConfigForSubId(subId).getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
+        String apn = getNiddApnName(subId);
         return new SatelliteModemEnableRequestAttributes(
                 arg.enableSatellite, arg.enableDemoMode, arg.isEmergency,
                 new SatelliteSubscriptionInfo(iccid, apn));
     }
 
+    @NonNull private String getNiddApnName(int subId) {
+        if (SatelliteServiceUtils.isNtnOnlySubscriptionId(subId)) {
+            String apn = mContext.getResources().getString(R.string.config_satellite_nidd_apn_name);
+            if (!TextUtils.isEmpty(apn)) {
+                return apn;
+            }
+        }
+        return getConfigForSubId(subId).getString(KEY_SATELLITE_NIDD_APN_NAME_STRING, "");
+    }
+
     private void handleRequestSatelliteAttachRestrictionForCarrierCmd(
             SatelliteControllerHandlerRequest request) {
         RequestHandleSatelliteAttachRestrictionForCarrierArgument argument =
@@ -5625,7 +5652,7 @@
                 KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL);
     }
 
-    public int getCarrierRoamingNtnConnectType(int subId) {
+    private int getCarrierRoamingNtnConnectType(int subId) {
         return getConfigForSubId(subId).getInt(KEY_CARRIER_ROAMING_NTN_CONNECT_TYPE_INT);
     }
 
@@ -6080,6 +6107,8 @@
             return;
         }
 
+        registerForSatelliteCommunicationAllowedStateChanged();
+
         boolean eligible = isCarrierRoamingNtnEligible(getSatellitePhone());
         plogd("evaluateCarrierRoamingNtnEligibilityChange: "
                 + "isCarrierRoamingNtnEligible=" + eligible);
@@ -6532,7 +6561,7 @@
                         /*visible*/ true);
             }
         } else if (mIsNotificationShowing
-                && !isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+                && !isSatelliteConnectedViaCarrierWithinHysteresisTime().first) {
             // Dismiss the notification if it is still displaying.
             dismissSatelliteNotification();
         }
@@ -7041,6 +7070,8 @@
                         mSubscriptionManagerService.getDefaultSmsSubId() == subId;
                 boolean isNtnOnly = info.isOnlyNonTerrestrialNetwork();
                 boolean isESOSSupported = info.isSatelliteESOSSupported();
+                boolean isCarrierSatelliteHigherPriority =
+                    isCarrierSatelliteHigherPriority(info);
                 if (!isNtnOnly && !isESOSSupported) {
                     continue;
                 }
@@ -7053,9 +7084,13 @@
                     continue;
                 }
 
-                int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId) ? 0
-                        : (isESOSSupported && isActive) ? 1
-                                : (isNtnOnly) ? 2 : (isESOSSupported) ? 3 : -1;
+                int keyPriority = (isESOSSupported && isActive && isDefaultSmsSubId
+                    && isCarrierSatelliteHigherPriority)
+                    ? 0 : (isESOSSupported && isActive &&
+                        isCarrierSatelliteHigherPriority)
+                        ? 1 : (isNtnOnly)
+                            ? 2 : (isESOSSupported)
+                                ? 3 : -1;
                 if (keyPriority != -1) {
                     newSubsInfoListPerPriority.computeIfAbsent(keyPriority,
                             k -> new ArrayList<>()).add(info);
@@ -7367,11 +7402,14 @@
         int selectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
         List<SatelliteSubscriberProvisionStatus> satelliteSubscribers =
                 getPrioritizedSatelliteSubscriberProvisionStatusList();
+
         for (SatelliteSubscriberProvisionStatus status : satelliteSubscribers) {
-            // TODO: need to check if satellite is allowed at current location for the subscription
             int subId = getSubIdFromSubscriberId(
                     status.getSatelliteSubscriberInfo().getSubscriberId());
-            if (status.isProvisioned() && isActiveSubId(subId)) {
+
+            if (status.isProvisioned() && isActiveSubId(subId) &&
+                isSatelliteAvailableAtCurrentLocation(
+                    mSubscriptionManagerService.getSubscriptionInfo(subId))) {
                 selectedSubId = subId;
                 break;
             }
@@ -7390,6 +7428,67 @@
         handleEventSelectedNbIotSatelliteSubscriptionChanged(selectedSubId);
     }
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    protected boolean isCarrierSatelliteHigherPriority(SubscriptionInfo info) {
+        if(!isSatelliteAccessAllowedAtCurrentLocation()) {
+            return true;
+        }
+        if(isSatelliteAvailableAtCurrentLocation(info)) {
+            return true;
+        }
+        return false;
+    }
+
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    protected boolean isSatelliteAvailableAtCurrentLocation(@Nullable SubscriptionInfo info) {
+        if(info == null) {
+            plogd("isSatelliteAvailableAtCurrentLocation: subscriptionInfo is null");
+            return false;
+        }
+        if (!isSatelliteAccessAllowedAtCurrentLocation()) {
+            plogd("isSatelliteAvailableAtCurrentLocation: satellite access is not allowed at " +
+                    "current location");
+            return false;
+        }
+        if(info.isOnlyNonTerrestrialNetwork()) {
+            return true;
+        }
+
+        int[] carrierTagIdsArray = mContext.getResources().getIntArray(
+            R.array.config_verizon_satellite_enabled_tagids);
+        List<Integer> carrierTagIds = null;
+
+        if(carrierTagIdsArray != null && carrierTagIdsArray.length > 0) {
+            carrierTagIds = Arrays.stream(carrierTagIdsArray)
+                .boxed()
+                .collect(Collectors.toList());
+        }
+
+        if(carrierTagIds == null) {
+            plogd("isSatelliteAvailableAtCurrentLocation: tagids for carrier satellite enabled " +
+                    "are not available");
+            return false;
+        }
+
+        return isCarrierSatelliteAvailableAtCurrentLocation(carrierTagIds);
+    }
+
+    /**
+     * Compares tagIds and determine if
+     * carrier satellite is available at current location while selecting highest priority profile.
+     *
+     * @param carrierTagIds a list of integer tagIds representing regions where carrier satellite
+     * coverage is available.
+     * @return {@code true} if the carrier satellite is available at current location,
+     *      {@code false} otherwise.
+     */
+    public boolean isCarrierSatelliteAvailableAtCurrentLocation(
+        List<Integer> carrierTagIds) {
+        synchronized (mSatelliteAccessConfigLock) {
+            return !Collections.disjoint(carrierTagIds, mCurrentLocationTagIds);
+        }
+    }
+
     private int getSubIdFromSubscriberId(String subscriberId) {
         synchronized (mSatelliteTokenProvisionedLock) {
             return mSubscriberIdPerSub.getOrDefault(subscriberId,
@@ -7807,6 +7906,71 @@
         }
     }
 
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected void registerForSatelliteCommunicationAllowedStateChanged() {
+        if (mRegisteredForSatelliteCommunicationAllowedStateChanged.get()) {
+            if (DEBUG) {
+                plogd("registerForSatelliteCommunicationAllowedStateChanged: already registered.");
+            }
+            return;
+        }
+
+        SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
+        if (satelliteManager == null) {
+            ploge("registerForSatelliteCommunicationAllowedStateChanged: SatelliteManager is null");
+            return;
+        }
+
+        SatelliteCommunicationAllowedStateCallback allowedStateCallback =
+            new SatelliteCommunicationAllowedStateCallback() {
+                @Override
+                public void onSatelliteCommunicationAllowedStateChanged(boolean isAllowed) {
+                    plogd("onSatelliteCommunicationAllowedStateChanged: isAllowed="
+                        + isAllowed);
+                    synchronized (mSatelliteAccessConfigLock) {
+                        mSatelliteAccessAllowed = isAllowed;
+                    }
+                }
+
+                @Override
+                public void onSatelliteAccessConfigurationChanged(
+                    SatelliteAccessConfiguration satelliteAccessConfiguration) {
+                    plogd("onSatelliteAccessConfigurationChanged: satelliteAccessConfiguration="
+                        + satelliteAccessConfiguration);
+                    handleSatelliteAccessConfigUpdateResult(satelliteAccessConfiguration);
+                }
+            };
+        try {
+            satelliteManager.registerForCommunicationAllowedStateChanged(
+                    this::post, allowedStateCallback);
+        } catch(RuntimeException e) {
+            plogd("registerForSatelliteCommunicationAllowedStateChanged: " +
+                    "satelliteManager.registerForCommunicationAllowedStateChanged() failed, " +
+                    "e=" + e);
+            return;
+        }
+        mRegisteredForSatelliteCommunicationAllowedStateChanged.set(true);
+    }
+
+    private void handleSatelliteAccessConfigUpdateResult(
+        SatelliteAccessConfiguration satelliteAccessConfig) {
+        if(satelliteAccessConfig != null) {
+            synchronized (mSatelliteAccessConfigLock) {
+                plogd("handleSatelliteAccessConfigUpdateResult:" + " satelliteAccessConfig="
+                    + satelliteAccessConfig);
+                List<Integer> tagIds = satelliteAccessConfig.getTagIds();
+                if (!mCurrentLocationTagIds.equals(tagIds)) {
+                    mCurrentLocationTagIds = tagIds;
+                    sendMessageDelayed(obtainMessage(CMD_EVALUATE_ESOS_PROFILES_PRIORITIZATION),
+                        mEvaluateEsosProfilesPrioritizationDurationMillis);
+                }
+            }
+        } else {
+                plogd("handleSatelliteAccessConfigUpdateResult: "
+                    + "satelliteAccessConfiguration is null");
+        }
+    }
+
     private void handleEventSatelliteRegistrationFailure(int causeCode) {
         plogd("handleEventSatelliteRegistrationFailure: " + causeCode);
 
@@ -8313,6 +8477,12 @@
         }
     }
 
+    private boolean isSatelliteAccessAllowedAtCurrentLocation() {
+        synchronized (mSatelliteAccessConfigLock) {
+            return mSatelliteAccessAllowed;
+        }
+    }
+
     @Nullable
     private Boolean getIsSatelliteEnabled() {
         synchronized (mIsSatelliteEnabledLock) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index e924878..ea6dedd 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -52,6 +52,7 @@
 import android.telephony.PersistentLogger;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.ImsRegistrationAttributes;
@@ -79,6 +80,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 
 /**
@@ -119,8 +121,10 @@
     private boolean mCheckingAccessRestrictionInProgress = false;
     protected long mTimeoutMillis = 0;
     private final long mOemEnabledTimeoutMillis;
-    private final AtomicBoolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime =
+    protected final AtomicBoolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime =
             new AtomicBoolean(false);
+    protected final AtomicInteger mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime =
+            new AtomicInteger(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
     @GuardedBy("mLock")
     private boolean mIsTimerTimedOut = false;
     protected int mCountOfTimerStarted = 0;
@@ -238,8 +242,7 @@
          * should do this check now so that we have higher chance of sending the event
          * EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.
          */
-        mIsSatelliteConnectedViaCarrierWithinHysteresisTime.set(
-                mSatelliteController.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+        updateSatelliteConnectedViaCarrierWithinHysteresisTimeState();
         sendMessage(obtainMessage(EVENT_EMERGENCY_CALL_STARTED, connection));
     }
 
@@ -377,8 +380,7 @@
 
     private void updateSatelliteViaCarrierAvailability() {
         if (!mIsSatelliteConnectedViaCarrierWithinHysteresisTime.get()) {
-            mIsSatelliteConnectedViaCarrierWithinHysteresisTime.set(
-                    mSatelliteController.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+            updateSatelliteConnectedViaCarrierWithinHysteresisTimeState();
         }
     }
 
@@ -571,10 +573,19 @@
 
     private void selectEmergencyCallWaitForConnectionTimeoutDuration() {
         if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+            int satelliteSubId = mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.get();
             mTimeoutMillis =
-                    mSatelliteController.getCarrierEmergencyCallWaitForConnectionTimeoutMillis();
+                    mSatelliteController.getCarrierEmergencyCallWaitForConnectionTimeoutMillis(
+                            satelliteSubId);
         } else {
-            mTimeoutMillis = mOemEnabledTimeoutMillis;
+            int satelliteSubId = mSatelliteController.getSelectedSatelliteSubId();
+            if (!SatelliteServiceUtils.isNtnOnlySubscriptionId(satelliteSubId)) {
+                mTimeoutMillis =
+                    mSatelliteController.getCarrierEmergencyCallWaitForConnectionTimeoutMillis(
+                        satelliteSubId);
+            } else {
+                mTimeoutMillis = mOemEnabledTimeoutMillis;
+            }
         }
         plogd("mTimeoutMillis = " + mTimeoutMillis);
     }
@@ -763,17 +774,18 @@
 
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public int getEmergencyCallToSatelliteHandoverType() {
-        if (Flags.carrierRoamingNbIotNtn()
-                && isDeviceProvisioned()
-                && isSatelliteAllowedByReasons()
-                && isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
-            int satelliteSubId = mSatelliteController.getSelectedSatelliteSubId();
+        if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
+            int satelliteSubId = mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.get();
             return mSatelliteController.getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(
                     satelliteSubId);
-        } else if (isSatelliteConnectedViaCarrierWithinHysteresisTime()) {
-            return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
         } else {
-            return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
+            int satelliteSubId = mSatelliteController.getSelectedSatelliteSubId();
+            if (!SatelliteServiceUtils.isNtnOnlySubscriptionId(satelliteSubId)) {
+                return mSatelliteController
+                    .getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(satelliteSubId);
+            } else {
+                return EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
+            }
         }
     }
 
@@ -831,6 +843,19 @@
         return (provisioned != null) && provisioned;
     }
 
+    private void updateSatelliteConnectedViaCarrierWithinHysteresisTimeState() {
+        Pair<Boolean, Integer> satelliteConnectedState =
+                mSatelliteController.isSatelliteConnectedViaCarrierWithinHysteresisTime();
+        mIsSatelliteConnectedViaCarrierWithinHysteresisTime.set(satelliteConnectedState.first);
+        if (satelliteConnectedState.first) {
+            mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.set(
+                    satelliteConnectedState.second);
+        } else {
+            mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.set(
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+        }
+    }
+
     private static void logv(@NonNull String log) {
         Rlog.v(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index b55c622..2ee9759 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
@@ -366,6 +366,29 @@
     }
 
     /**
+     * Check if the subscription ID is a NTN only subscription ID.
+     *
+     * @return {@code true} if the subscription ID is a NTN only subscription ID,
+     * {@code false} otherwise.
+    */
+    public static boolean isNtnOnlySubscriptionId(int subId) {
+        SubscriptionManagerService subscriptionManagerService =
+            SubscriptionManagerService.getInstance();
+        if (subscriptionManagerService == null) {
+            logd("isNtnOnlySubscriptionId: subscriptionManagerService is null");
+            return false;
+        }
+
+        SubscriptionInfo subInfo = subscriptionManagerService.getSubscriptionInfo(subId);
+        if (subInfo == null) {
+            logd("isNtnOnlySubscriptionId: subInfo is null for subId=" + subId);
+            return false;
+        }
+
+        return subInfo.isOnlyNonTerrestrialNetwork();
+    }
+
+    /**
      * Expected format of the input dictionary bundle is:
      * <ul>
      *     <li>Key: PLMN string.</li>
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 dc973af..566e5b9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -60,6 +60,7 @@
 import android.testing.TestableLooper;
 
 import com.android.internal.R;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.SmsDispatchersController;
@@ -1140,6 +1141,166 @@
         assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
     }
 
+   @Test
+   public void testHandleMessage_eventMtSmsPollingThrottleTimedOut_sendsMtSmsPollInNotConnected() {
+        setShouldPollMtSmsTrue();
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+        mDatagramDispatcherUT.handleMessage(
+                mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+                        new AsyncResult(null, null, null)));
+
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+   }
+
+    @Test
+    public void
+            testHandleMessage_eventMtSmsPollingThrottleTimedOut_configDisabled_doesNotSendMtSmsPoll() {
+        setShouldPollMtSmsTrue();
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        // Set config_satellite_allow_check_message_in_not_connected to false
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, false);
+
+        mDatagramDispatcherUT.handleMessage(
+                mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+                        new AsyncResult(null, null, null)));
+
+        verifyZeroInteractions(mMockSmsDispatchersController);
+   }
+
+    @Test
+    public void
+            testHandleMessage_eventMtSmsPollingThrottleTimedOut_flagDisabled_doesNotSendMtSmsPoll() {
+        setShouldPollMtSmsTrue();
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        // Set flag to false
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(false);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+        mDatagramDispatcherUT.handleMessage(
+                mDatagramDispatcherUT.obtainMessage(10 /*EVENT_MT_SMS_POLLING_THROTTLE_TIMED_OUT*/,
+                        new AsyncResult(null, null, null)));
+
+        verifyZeroInteractions(mMockSmsDispatchersController);
+   }
+
+
+
+    @Test
+    public void testSetDeviceAlignedWithSatellite_isAligned_notConnected_sendsMtSmsPoll() {
+        setShouldPollMtSmsTrue();
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+    }
+
+    @Test
+    public void testSetDeviceAlignedWithSatellite_notAligned_doesNotSendsMtSmsPoll() {
+        setShouldPollMtSmsTrue();
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+
+        verifyZeroInteractions(mMockSmsDispatchersController);
+    }
+
+    @Test
+    public void testOnSatelliteModemStateChanged_notConnected_sendsMtSmsPoll() {
+        setShouldPollMtSmsTrue();
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+    }
+
+    @Test
+    public void testOnSatelliteModemStateChanged_connected_sendsMtSmsPoll() {
+        setShouldPollMtSmsTrue();
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+    }
+
+    @Test
+    public void testOnSatelliteModemStateChanged_transferring_sendsMtSmsPoll() {
+        setShouldPollMtSmsTrue();
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+
+        verify(mMockSmsDispatchersController, times(1)).sendMtSmsPollingMessage();
+    }
+
+    @Test
+    public void testOnSatelliteModemStateChanged_throttled_doesNotSendMtSmsPoll() {
+        startMtSmsPollingThrottle();
+        setShouldPollMtSmsTrue();
+        mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putBooleanResource(
+                R.bool.config_satellite_allow_check_message_in_not_connected, true);
+
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(
+                SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+        verify(mMockSmsDispatchersController, times(0)).sendMtSmsPollingMessage();
+    }
+
+    private void setModemState(int state) {
+        mDatagramDispatcherUT.onSatelliteModemStateChanged(state);
+    }
+
+    private void setShouldPollMtSmsTrue() {
+        // Set mHasEnteredConnectedState true
+        setModemState(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+        // Set the following so shouldPollMtSms returns true
+        mContextFixture.putBooleanResource(R.bool.config_enabled_mt_sms_polling, true);
+        when(mMockSatelliteController.shouldSendSmsToDatagramDispatcher(any(Phone.class)))
+                .thenReturn(true);
+        // This will trigger mShouldPollMtSms = shouldPollMtSms
+        setModemState(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+    }
+
+    private void startMtSmsPollingThrottle() {
+        // Call sendSms to put message in mPendingSmsMap with isMtSmsPolling=true
+        PendingRequest pendingRequest = new PendingRequest(
+                SmsDispatchersController.PendingRequest.TYPE_TEXT, null, "test-app",
+                Binder.getCallingUserHandle().getIdentifier(), "1111", "2222", asArrayList(null),
+                asArrayList(null), false, null, 0, asArrayList("text"), null, false, 0, false,
+                10, 100L, false, /* isMtSmsPolling= */ true);
+        mDatagramDispatcherUT.sendSms(pendingRequest);
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = mPhone.getSubId();
+        args.arg2 = pendingRequest.uniqueMessageId;
+        args.arg3 = true;
+        // EVENT_SEND_SMS_DONE to trigger handleEventSendSmsDone which will start the throttle
+        mDatagramDispatcherUT.handleMessage(
+                mDatagramDispatcherUT.obtainMessage(9 /*EVENT_SEND_SMS_DONE*/, args));
+    }
+
     private boolean waitForIntegerConsumerResult(int expectedNumberOfEvents) {
         for (int i = 0; i < expectedNumberOfEvents; i++) {
             try {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index 6f716b5..f3061c8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -169,6 +169,7 @@
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
 import android.telephony.satellite.NtnSignalStrength;
+import android.telephony.satellite.SatelliteAccessConfiguration;
 import android.telephony.satellite.SatelliteCapabilities;
 import android.telephony.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteInfo;
@@ -258,6 +259,9 @@
     private PersistableBundle mCarrierConfigBundle;
     private ServiceState mServiceState2;
 
+    private SubscriptionInfo testSubscriptionInfo;
+    private SubscriptionInfo testSubscriptionInfo2;
+
     @Mock private SatelliteController mMockSatelliteController;
     @Mock private DatagramController mMockDatagramController;
     @Mock private SatelliteModemInterface mMockSatelliteModemInterface;
@@ -1769,7 +1773,7 @@
         assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
 
         try {
-            setSatelliteSubscriberTesting();
+            setSatelliteSubscriberTesting(true);
         } catch (Exception ex) {
             fail("provisionSatelliteService.setSatelliteSubscriberTesting: ex=" + ex);
         }
@@ -2974,7 +2978,8 @@
     @Test
     public void testCarrierEnabledSatelliteConnectionHysteresisTime() throws Exception {
         when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-        assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+        assertFalse(mSatelliteControllerUT
+                        .isSatelliteConnectedViaCarrierWithinHysteresisTime().first);
 
         when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
         when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
@@ -2994,7 +2999,8 @@
         doReturn(cellSignalStrengthList).when(mSignalStrength).getCellSignalStrengths();
         processAllMessages();
         mSatelliteControllerUT.elapsedRealtime = 0;
-        assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+        assertFalse(mSatelliteControllerUT
+                        .isSatelliteConnectedViaCarrierWithinHysteresisTime().first);
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
 
@@ -3002,7 +3008,8 @@
         when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(false);
         sendServiceStateChangedEvent();
         processAllMessages();
-        assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+        assertFalse(mSatelliteControllerUT
+                        .isSatelliteConnectedViaCarrierWithinHysteresisTime().first);
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
         verify(mPhone, times(1)).notifyCarrierRoamingNtnModeChanged(eq(false));
@@ -3017,7 +3024,8 @@
         // 2 minutes later and hysteresis timeout is 1 minute
         mSatelliteControllerUT.elapsedRealtime = 2 * 60 * 1000;
         // But Phone2 is connected to NTN right now
-        assertTrue(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+        assertTrue(mSatelliteControllerUT
+                       .isSatelliteConnectedViaCarrierWithinHysteresisTime().first);
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
         assertTrue(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
         verify(mPhone, times(0)).notifyCarrierRoamingNtnModeChanged(eq(false));
@@ -3030,7 +3038,8 @@
         sendServiceStateChangedEvent();
         processAllMessages();
         // Current time (2) - last disconnected time (2) < hysteresis timeout (1)
-        assertTrue(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+        assertTrue(mSatelliteControllerUT
+                       .isSatelliteConnectedViaCarrierWithinHysteresisTime().first);
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
         assertTrue(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
         verify(mPhone, times(0)).notifyCarrierRoamingNtnModeChanged(eq(false));
@@ -3042,7 +3051,8 @@
         mSatelliteControllerUT.elapsedRealtime = 4 * 60 * 1000;
         moveTimeForward(2 * 60 * 1000);
         processAllMessages();
-        assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+        assertFalse(mSatelliteControllerUT
+                        .isSatelliteConnectedViaCarrierWithinHysteresisTime().first);
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
         assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
         verify(mPhone, times(0)).notifyCarrierRoamingNtnModeChanged(eq(false));
@@ -4633,7 +4643,7 @@
     }
 
     private void verifyRequestSatelliteSubscriberProvisionStatus() throws Exception {
-        setSatelliteSubscriberTesting();
+        setSatelliteSubscriberTesting(true);
         List<SatelliteSubscriberInfo> list = getExpectedSatelliteSubscriberInfoList();
         mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
         mCarrierConfigBundle.putString(KEY_SATELLITE_NIDD_APN_NAME_STRING, mNiddApn);
@@ -4849,26 +4859,31 @@
         assertTrue(mDeprovisionDone);
     }
 
-    private void setSatelliteSubscriberTesting() throws Exception {
+    private void setSatelliteSubscriberTesting(boolean sameCarrier) throws Exception {
         doReturn("123").when(mContext).getAttributionTag();
-        final int carrierId = 0;
+        final int carrierId_subID = 0;
+        final int carrierId_subID1 = sameCarrier ? 0 : 1;
         SubscriptionInfo subscriptionInfo = new SubscriptionInfo.Builder()
                 .setId(SUB_ID).setIccId(mIccId).setSimSlotIndex(0).setOnlyNonTerrestrialNetwork(
-                        false).setSatelliteESOSSupported(true).setCarrierId(carrierId).build();
+                        false).setSatelliteESOSSupported(true).setCarrierId(
+                            carrierId_subID).build();
         SubscriptionInfo subscriptionInfo2 = new SubscriptionInfo.Builder()
                 .setId(SUB_ID1).setIccId(mIccId2).setSimSlotIndex(1).setOnlyNonTerrestrialNetwork(
-                        true).setSatelliteESOSSupported(false).setCarrierId(carrierId).build();
+                        true).setSatelliteESOSSupported(false).setCarrierId(
+                            carrierId_subID1).build();
         List<SubscriptionInfo> allSubInfos = new ArrayList<>();
         allSubInfos.add(subscriptionInfo);
         allSubInfos.add(subscriptionInfo2);
+        testSubscriptionInfo = subscriptionInfo;
+        testSubscriptionInfo2 = subscriptionInfo2;
         doReturn(allSubInfos).when(mMockSubscriptionManagerService).getAllSubInfoList(
                 anyString(), anyString());
         SubscriptionInfoInternal subInfoInternal =
-                new SubscriptionInfoInternal.Builder().setCarrierId(0).setImsi(mImsi).setIccId(
-                        mIccId).build();
+                new SubscriptionInfoInternal.Builder().setCarrierId(
+                    carrierId_subID).setImsi(mImsi).setIccId(mIccId).build();
         SubscriptionInfoInternal subInfoInternal2 =
-                new SubscriptionInfoInternal.Builder().setCarrierId(0).setImsi(mImsi2).setIccId(
-                        mIccId2).build();
+                new SubscriptionInfoInternal.Builder().setCarrierId(
+                    carrierId_subID1).setImsi(mImsi2).setIccId(mIccId2).build();
         doReturn(subscriptionInfo).when(mMockSubscriptionManagerService).getSubscriptionInfo(
                 eq(SUB_ID));
         doReturn(subscriptionInfo2).when(mMockSubscriptionManagerService).getSubscriptionInfo(
@@ -5012,10 +5027,79 @@
     }
 
     @Test
+    public void testRegisterForSatelliteCommunicationAllowedStateChanged() throws Exception {
+        when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+        mContextFixture.putIntArrayResource(
+                R.array.config_verizon_satellite_enabled_tagids,
+                new int[]{1001});
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getIntArray(
+                R.array.config_verizon_satellite_enabled_tagids)).thenReturn(new int[]{1001});
+        // carrierID is same as SUBID for this test
+        final int carrierSubId = SUB_ID;
+        final int oemSubId = SUB_ID1;
+        final String carrierSubscriberId = mSubscriberId;
+        final String oemSubscriberId = mSubscriberId2;
+        mCarrierConfigBundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+        setSatelliteSubscriberTesting(false);
+        invokeCarrierConfigChanged();
+
+        Field provisionedSubscriberIdField = SatelliteController.class.getDeclaredField(
+                "mProvisionedSubscriberId");
+        provisionedSubscriberIdField.setAccessible(true);
+        Map<String, Boolean> testProvisionedSubscriberId = new HashMap<>();;
+        testProvisionedSubscriberId.put(carrierSubscriberId, true);
+        testProvisionedSubscriberId.put(oemSubscriberId, true);
+        provisionedSubscriberIdField.set(mSatelliteControllerUT, testProvisionedSubscriberId);
+
+        Field currentLocationTagIdsField = SatelliteController.class.getDeclaredField(
+                "mCurrentLocationTagIds");
+        currentLocationTagIdsField.setAccessible(true);
+
+        setComponentName();
+        mSatelliteControllerUT.setIsSatelliteAllowedState(true);
+
+        mSatelliteControllerUT.registerForSatelliteCommunicationAllowedStateChanged();
+
+        // Test satelliteAccessConfigCallback.onSuccess
+        // with current location NOT supporting carrier satellite
+        // OEM satellite subscription should be selected
+        currentLocationTagIdsField.set(mSatelliteControllerUT, Arrays.asList(100));
+
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo), k -> new ArrayList<>())
+                .add(testSubscriptionInfo);
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo2), k -> new ArrayList<>())
+                .add(testSubscriptionInfo2);
+
+        mSatelliteControllerUT.evaluateESOSProfilesPrioritizationTest();
+        processAllMessages();
+        assertEquals(oemSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
+
+        // Test satelliteAccessConfigCallback.onSuccess
+        // with current location supporting carrier satellite
+        // Carrier satellite subscription should be selected
+        currentLocationTagIdsField.set(mSatelliteControllerUT, Arrays.asList(1001, 100));
+
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo), k -> new ArrayList<>())
+                .add(testSubscriptionInfo);
+        mSatelliteControllerUT.subsInfoListPerPriority().computeIfAbsent(
+                        getKeyPriority(testSubscriptionInfo2), k -> new ArrayList<>())
+                .add(testSubscriptionInfo2);
+
+        mSatelliteControllerUT.evaluateESOSProfilesPrioritizationTest();
+        processAllMessages();
+        assertEquals(carrierSubId, mSatelliteControllerUT.getSelectedSatelliteSubId());
+    }
+
+
+    @Test
     public void testProvisionStatusPerSubscriberIdGetFromDb() throws Exception {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
 
-        setSatelliteSubscriberTesting();
+        setSatelliteSubscriberTesting(true);
         // Check if the cache is not updated when the value read from the database is false.
         verifyProvisionStatusPerSubscriberIdGetFromDb(false);
 
@@ -5027,7 +5111,7 @@
     public void testProvisionStatusPerSubscriberIdStoreToDb() throws Exception {
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
 
-        setSatelliteSubscriberTesting();
+        setSatelliteSubscriberTesting(true);
         // Check if the cache is not updated when the value read from the database is false.
         verifyProvisionStatusPerSubscriberIdGetFromDb(false);
 
@@ -5327,9 +5411,12 @@
         boolean isActive = subscriptionInfo.isActive();
         boolean isNtnOnly = subscriptionInfo.isOnlyNonTerrestrialNetwork();
         boolean isESOSSupported = subscriptionInfo.isSatelliteESOSSupported();
+        boolean isCarrierSatelliteHigherPriority =
+                mSatelliteControllerUT.isCarrierSatelliteHigherPriorityTest(
+                        subscriptionInfo);
 
         int keyPriority;
-        if (isESOSSupported && isActive) {
+        if (isESOSSupported && isActive && isCarrierSatelliteHigherPriority) {
             keyPriority = 1;
         } else if (isNtnOnly) {
             keyPriority = 2;
@@ -5925,7 +6012,7 @@
         verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
 
         try {
-            setSatelliteSubscriberTesting();
+            setSatelliteSubscriberTesting(true);
         } catch (Exception ex) {
             fail("provisionSatelliteService.setSatelliteSubscriberTesting: ex=" + ex);
         }
@@ -6151,6 +6238,11 @@
             return elapsedRealtime;
         }
 
+        @Override
+        protected void registerForSatelliteCommunicationAllowedStateChanged() {
+            logd("registerForSatelliteCommunicationAllowedStateChanged");
+        }
+
         void setSatelliteSessionController(SatelliteSessionController satelliteSessionController) {
             mSatelliteSessionController = satelliteSessionController;
         }
@@ -6257,6 +6349,10 @@
             evaluateESOSProfilesPrioritization();
         }
 
+        public boolean isCarrierSatelliteHigherPriorityTest(SubscriptionInfo info) {
+            return isCarrierSatelliteHigherPriority(info);
+        }
+
         public String getStringFromOverlayConfigTest(int resourceId) {
             return getStringFromOverlayConfig(resourceId);
         }
@@ -6276,6 +6372,12 @@
                 return mResultReceiverCountPerMethodMap;
             }
         }
+
+        public void setIsSatelliteAllowedState(boolean isAllowed) {
+            synchronized(mSatelliteAccessConfigLock) {
+                mSatelliteAccessAllowed = isAllowed;
+            }
+        }
     }
 
     @Test
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 529088b..a5fd30d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -29,6 +29,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -48,11 +49,13 @@
 import android.os.Looper;
 import android.os.OutcomeReceiver;
 import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.telecom.Connection;
 import android.telecom.TelecomManager;
 import android.telephony.BinderCacheManager;
 import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.RegistrationManager;
@@ -62,6 +65,7 @@
 import android.testing.TestableLooper;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 
 import com.android.ims.ImsException;
 import com.android.ims.ImsManager;
@@ -72,6 +76,7 @@
 import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
 
 import org.junit.After;
 import org.junit.Before;
@@ -98,9 +103,11 @@
 public class SatelliteSOSMessageRecommenderTest extends TelephonyTest {
     private static final String TAG = "SatelliteSOSMessageRecommenderTest";
     private static final int TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS = 500;
+    private static final int TEST_EMERGENCY_CALL_TO_T911_MSG_HYSTERESIS_TIMEOUT_MILLIS = 1000;
     private static final int PHONE_ID = 0;
     private static final int PHONE_ID2 = 1;
     private static final int SUB_ID = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+    private static final int SUB_ID1 = 1;
     private static final String CALL_ID = "CALL_ID";
     private static final String WRONG_CALL_ID = "WRONG_CALL_ID";
     private static final String DEFAULT_SATELLITE_MESSAGING_PACKAGE = "android.com.google.default";
@@ -108,6 +115,12 @@
             "android.com.google.default.SmsMmsApp";
     private static final String DEFAULT_HANDOVER_INTENT_ACTION =
             "android.com.vendor.action.EMERGENCY_MESSAGING";
+    private static final String DEFAULT_SOS_HANDOVER_APP =
+            "android.com.vendor.message;android.com.vendor.message.SosHandoverApp";
+    private static final String DEFAULT_SATELLITE_SOS_HANDOVER_PACKAGE =
+        "android.com.vendor.message";
+    private static final String DEFAULT_SATELLITE_SOS_HANDOVER_CLASS =
+            "android.com.vendor.message.SosHandoverApp";
     private static final String DEFAULT_T911_HANDOVER_INTENT_ACTION = Intent.ACTION_SENDTO;
     private TestSatelliteController mTestSatelliteController;
     private TestImsManager mTestImsManager;
@@ -125,6 +138,7 @@
     private ServiceState mServiceState2;
     @Mock
     private SatelliteStats mMockSatelliteStats;
+    @Mock private SubscriptionManagerService mMockSubscriptionManagerService;
 
     @Before
     public void setUp() throws Exception {
@@ -139,6 +153,8 @@
         when(mResources.getInteger(
                 R.integer.config_emergency_call_wait_for_connection_timeout_millis))
                 .thenReturn(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
+        when(mResources.getString(R.string.config_oem_enabled_satellite_sos_handover_app))
+                .thenReturn(DEFAULT_SOS_HANDOVER_APP);
         when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         when(mFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
         mTestSatelliteController = new TestSatelliteController(mContext,
@@ -164,8 +180,19 @@
         when(mPhone2.isImsRegistered()).thenReturn(false);
         replaceInstance(SatelliteStats.class, "sInstance", null,
                 mMockSatelliteStats);
+        replaceInstance(SubscriptionManagerService.class, "sInstance", null,
+                mMockSubscriptionManagerService);
         doNothing().when(mMockSatelliteStats).onSatelliteSosMessageRecommender(
                 any(SatelliteStats.SatelliteSosMessageRecommenderParams.class));
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            false, -1);
+        mTestSOSMessageRecommender.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            false, -1);
+        mTestSatelliteController.selectedSatelliteSubId = SUB_ID1;
+        SubscriptionInfo subscriptionInfo = new SubscriptionInfo.Builder()
+                .setId(SUB_ID1).setOnlyNonTerrestrialNetwork(true).build();
+        when(mMockSubscriptionManagerService.getSubscriptionInfo(eq(SUB_ID1)))
+            .thenReturn(subscriptionInfo);
     }
 
     @After
@@ -175,9 +202,14 @@
 
     @Test
     public void testTimeoutBeforeEmergencyCallEnd_T911() {
-        testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
-                DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS,
-                DEFAULT_T911_HANDOVER_INTENT_ACTION);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            true, SUB_ID1);
+        testTimeoutBeforeEmergencyCallEnd(
+            TEST_EMERGENCY_CALL_TO_T911_MSG_HYSTERESIS_TIMEOUT_MILLIS,
+            EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
+            DEFAULT_SATELLITE_MESSAGING_PACKAGE,
+            DEFAULT_SATELLITE_MESSAGING_CLASS,
+            DEFAULT_T911_HANDOVER_INTENT_ACTION);
         verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
         assertTrue(mTestSOSMessageRecommender.isDialerNotified());
     }
@@ -188,10 +220,12 @@
                 "android.com.vendor.message;android.com.vendor.message.SmsApp";
         when(mResources.getString(R.string.config_oem_enabled_satellite_sos_handover_app))
                 .thenReturn(satelliteHandoverApp);
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
-        testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
-                "android.com.vendor.message", "android.com.vendor.message.SmsApp",
-                DEFAULT_HANDOVER_INTENT_ACTION);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
+        testTimeoutBeforeEmergencyCallEnd(
+            TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
+            EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+            "android.com.vendor.message", "android.com.vendor.message.SmsApp",
+            DEFAULT_HANDOVER_INTENT_ACTION);
         verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
         assertTrue(mTestSOSMessageRecommender.isDialerNotified());
     }
@@ -202,9 +236,11 @@
                 "android.com.vendor.message;android.com.vendor.message.SmsApp;abc";
         when(mResources.getString(R.string.config_oem_enabled_satellite_sos_handover_app))
                 .thenReturn(satelliteHandoverApp);
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
-        testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
-                DEFAULT_HANDOVER_INTENT_ACTION);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
+        testTimeoutBeforeEmergencyCallEnd(
+            TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
+            EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
+            DEFAULT_HANDOVER_INTENT_ACTION);
         verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
         assertTrue(mTestSOSMessageRecommender.isDialerNotified());
     }
@@ -213,9 +249,11 @@
     public void testTimeoutBeforeEmergencyCallEnd_SOS_WithoutHandoverAppConfigured() {
         when(mResources.getString(R.string.config_oem_enabled_satellite_sos_handover_app))
                 .thenReturn("");
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
-        testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
-                DEFAULT_HANDOVER_INTENT_ACTION);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
+        testTimeoutBeforeEmergencyCallEnd(
+            TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
+            EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS, "", "",
+            DEFAULT_HANDOVER_INTENT_ACTION);
         verify(mMockSatelliteStats, times(1)).onSatelliteSosMessageRecommender(any());
         assertTrue(mTestSOSMessageRecommender.isDialerNotified());
     }
@@ -232,7 +270,7 @@
         verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
     }
 
-    private void testTimeoutBeforeEmergencyCallEnd(int expectedHandoverType,
+    private void testTimeoutBeforeEmergencyCallEnd(int timeoutMillis, int expectedHandoverType,
             String expectedPackageName, String expectedClassName, String expectedAction) {
         mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
@@ -250,7 +288,7 @@
 
         // Wait for the timeout to expires
         mTestSOSMessageRecommender.isSatelliteAllowedCallback.onResult(true);
-        moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
+        moveTimeForward(timeoutMillis);
         processAllMessages();
         if (TextUtils.isEmpty(expectedPackageName) || TextUtils.isEmpty(expectedClassName)) {
             assertTrue(mTestConnection.isEventWithoutLaunchIntentSent(
@@ -267,7 +305,7 @@
 
     @Test
     public void testTimeoutBeforeEmergencyCallEnd_EventDisplayEmergencyMessageNotSent() {
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
         mTestSatelliteController.setDeviceProvisioned(false);
         mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
@@ -297,7 +335,7 @@
     @Test
     public void testTimeoutBeforeEmergencyCallEnd_T911_FromNotConnectedToConnected() {
         mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
         mTestSatelliteController.isOemEnabledSatelliteSupported = false;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
@@ -312,7 +350,8 @@
         processAllMessages();
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
 
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            true, SUB_ID1);
         // Wait for the timeout to expires
         moveTimeForward(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
         processAllMessages();
@@ -362,8 +401,9 @@
         processAllMessages();
 
         assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
-                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
-                DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
+                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+                DEFAULT_SATELLITE_SOS_HANDOVER_PACKAGE,
+                DEFAULT_SATELLITE_SOS_HANDOVER_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
         assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
         assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -373,7 +413,7 @@
 
     @Test
     public void testSatelliteProvisionStateChangedBeforeTimeout() {
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
 
@@ -394,7 +434,6 @@
         assertFalse(mTestSOSMessageRecommender.isDialerNotified());
         reset(mMockSatelliteStats);
 
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
         assertTrue(mTestSOSMessageRecommender.isTimerStarted());
@@ -418,8 +457,9 @@
         processAllMessages();
 
         assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
-                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
-                DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
+                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+                DEFAULT_SATELLITE_SOS_HANDOVER_PACKAGE,
+                DEFAULT_SATELLITE_SOS_HANDOVER_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
         assertFalse(mTestSOSMessageRecommender.isTimerStarted());
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
         assertUnregisterForStateChangedEventsTriggered(mPhone, 2, 2);
@@ -459,8 +499,9 @@
         processAllMessages();
 
         assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
-                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
-                DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
+                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+                DEFAULT_SATELLITE_SOS_HANDOVER_PACKAGE,
+                DEFAULT_SATELLITE_SOS_HANDOVER_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
         assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
         assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -527,7 +568,6 @@
     @Test
     public void testSatelliteNotAllowedInCurrentLocation() {
         mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
         assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
@@ -562,7 +602,8 @@
                 mContext,
                 Looper.myLooper(),
                 satelliteController, mTestImsManager);
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            true, SUB_ID1);
         testSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
 
@@ -608,11 +649,8 @@
 
         // Both OEM and carrier support satellite, but device is not connected to carrier satellite
         // within hysteresis time. Thus, OEM timer will be used.
-        long carrierTimeoutMillis = 1000;
         mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = true;
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
-        mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
-                carrierTimeoutMillis;
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         processAllMessages();
         assertEquals(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
@@ -621,8 +659,26 @@
 
         // Both OEM and carrier support satellite, and device is connected to carrier satellite
         // within hysteresis time. Thus, carrier timer will be used.
+        int carrierTimeoutMillis = 1000;
         mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = true;
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            true, SUB_ID1);
+        mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
+                carrierTimeoutMillis;
+        mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
+        processAllMessages();
+        assertEquals(carrierTimeoutMillis, mTestSOSMessageRecommender.getTimeOutMillis());
+        verify(mMockSatelliteStats, never()).onSatelliteSosMessageRecommender(any());
+
+        // Both OEM and carrier support satellite, device is not connected to carrier satellite
+        // within hysteresis time, but selected satellite subId is not NTN only. Thus, carrier
+        // timer will be used.
+        carrierTimeoutMillis = 2000;
+        SubscriptionInfo subscriptionInfo = new SubscriptionInfo.Builder()
+                .setId(SUB_ID1).setOnlyNonTerrestrialNetwork(false).build();
+        when(mMockSubscriptionManagerService.getSubscriptionInfo(eq(SUB_ID1)))
+            .thenReturn(subscriptionInfo);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
         mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
                 carrierTimeoutMillis;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
@@ -635,7 +691,8 @@
     public void testGetEmergencyCallToSatelliteHandoverType_SatelliteViaCarrierAndOemAvailable() {
         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
 
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            true, SUB_ID1);
         mTestSatelliteController.mIsDeviceProvisionedForTest = true;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
@@ -649,7 +706,8 @@
     public void testGetEmergencyCallToSatelliteHandoverType_OnlySatelliteViaCarrierAvailable() {
         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
 
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(true);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(
+            true, SUB_ID1);
         mTestSatelliteController.mIsDeviceProvisionedForTest = false;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
@@ -663,13 +721,13 @@
     public void testGetEmergencyCallToSatelliteHandoverType_OemAndCarrierNotAvailable() {
         mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN);
 
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
         mTestSatelliteController.mIsDeviceProvisionedForTest = true;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
                 mTestSOSMessageRecommender.getEmergencyCallToSatelliteHandoverType());
 
-        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false);
+        mTestSatelliteController.setSatelliteConnectedViaCarrierWithinHysteresisTime(false, -1);
         mTestSatelliteController.mIsDeviceProvisionedForTest = false;
         mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection, false);
         assertEquals(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
@@ -745,8 +803,9 @@
         processAllMessages();
 
         assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
-                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
-                DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
+                EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS,
+                DEFAULT_SATELLITE_SOS_HANDOVER_PACKAGE,
+                DEFAULT_SATELLITE_SOS_HANDOVER_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
         assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 1);
         assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 1);
         assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -777,11 +836,18 @@
         private int mUnregisterForSatelliteProvisionStateChangedCalls = 0;
         private Boolean mIsDeviceProvisionedForTest = true;
         private boolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime = true;
+        private int mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime = -1;
         public boolean isOemEnabledSatelliteSupported = true;
         public boolean isCarrierEnabledSatelliteSupported = true;
         public boolean isSatelliteEmergencyMessagingSupportedViaCarrier = true;
-        public long carrierEmergencyCallWaitForConnectionTimeoutMillis =
-                TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS;
+        public int carrierEmergencyCallWaitForConnectionTimeoutMillis =
+                TEST_EMERGENCY_CALL_TO_T911_MSG_HYSTERESIS_TIMEOUT_MILLIS;
+        public int overrideEmergencyCallToSatelliteHandoverType =
+            SatelliteController.INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
+        public boolean isSatelliteEsosSupported = false;
+        public int carrierRoamingNtnEmergencyCallToSatelliteHandoverType =
+            EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
+        public int selectedSatelliteSubId = -1;
 
         /**
          * Create a SatelliteController to act as a backend service of
@@ -811,6 +877,11 @@
         }
 
         @Override
+        protected void registerForSatelliteCommunicationAllowedStateChanged() {
+            logd("registerForSatelliteCommunicationAllowedStateChanged");
+        }
+
+        @Override
         @SatelliteManager.SatelliteResult public int registerForSatelliteProvisionStateChanged(
                 @NonNull ISatelliteProvisionStateCallback callback) {
             mRegisterForSatelliteProvisionStateChangedCalls++;
@@ -833,13 +904,14 @@
         }
 
         @Override
-        public boolean isSatelliteConnectedViaCarrierWithinHysteresisTime() {
-            return mIsSatelliteConnectedViaCarrierWithinHysteresisTime;
+        public Pair<Boolean,Integer> isSatelliteConnectedViaCarrierWithinHysteresisTime() {
+            return new Pair(mIsSatelliteConnectedViaCarrierWithinHysteresisTime,
+                mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime);
         }
 
         @Override
         protected int getEnforcedEmergencyCallToSatelliteHandoverType() {
-            return INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
+            return overrideEmergencyCallToSatelliteHandoverType;
         }
 
         @Override
@@ -853,14 +925,35 @@
         }
 
         @Override
+        public int getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId) {
+            return carrierEmergencyCallWaitForConnectionTimeoutMillis;
+        }
+
+        @Override
         protected List<DeviceState> getSupportedDeviceStates() {
             return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
                     "DEFAULT" /* name */).build()));
         }
 
+        @Override
+        public boolean isSatelliteEsosSupported(int subId) {
+            return isSatelliteEsosSupported;
+        }
+
+        @Override
+        public int getCarrierRoamingNtnEmergencyCallToSatelliteHandoverType(int subId) {
+            return carrierRoamingNtnEmergencyCallToSatelliteHandoverType;
+        }
+
+        @Override
+        public int getSelectedSatelliteSubId() {
+            return selectedSatelliteSubId;
+        }
+
         public void setSatelliteConnectedViaCarrierWithinHysteresisTime(
-                boolean connectedViaCarrier) {
+                boolean connectedViaCarrier, int subId) {
             mIsSatelliteConnectedViaCarrierWithinHysteresisTime = connectedViaCarrier;
+            mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime = subId;
         }
 
         public int getRegisterForSatelliteProvisionStateChangedCalls() {
@@ -909,6 +1002,11 @@
             return List.of(new DeviceState(new DeviceState.Configuration.Builder(0 /* identifier */,
                     "DEFAULT" /* name */).build()));
         }
+
+        @Override
+        protected void registerForSatelliteCommunicationAllowedStateChanged() {
+            logd("registerForSatelliteCommunicationAllowedStateChanged");
+        }
     }
 
     private static class TestImsManager extends ImsManager {
@@ -986,7 +1084,7 @@
                 DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS);
         private boolean mIsDialerNotified;
         private boolean mProvisionState = true;
-        private boolean mSatelliteAllowedByReasons = true;
+        public boolean isSatelliteAllowedByReasons = true;
 
         /**
          * Create an instance of SatelliteSOSMessageRecommender.
@@ -1028,7 +1126,7 @@
 
         @Override
         protected boolean isSatelliteAllowedByReasons() {
-            return mSatelliteAllowedByReasons;
+            return isSatelliteAllowedByReasons;
         }
 
         public boolean isTimerStarted() {
@@ -1050,6 +1148,12 @@
         public boolean isDialerNotified() {
             return mIsDialerNotified;
         }
+
+        public void setSatelliteConnectedViaCarrierWithinHysteresisTime(
+                boolean connectedViaCarrier, int subId) {
+            mIsSatelliteConnectedViaCarrierWithinHysteresisTime.set(connectedViaCarrier);
+            mSubIdOfSatelliteConnectedViaCarrierWithinHysteresisTime.set(subId);
+        }
     }
 
     private static class TestConnection extends Connection {