Merge changes from topic "carrier-config-n1-mode" into main

* changes:
  Hook CarrierConfig 5G Capability to setN1ModeEnabled HAL
  Add FeatureFlags to the Phone Objects
  Add a Network flags file and flag for b/302033535
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 55f1ccc..59685b1 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -9,7 +9,8 @@
       ]
     },
     {
-      "name": "CarrierAppIntegrationTestCases"
+      "name": "CarrierAppIntegrationTestCases",
+      "keywords": ["internal"]
     },
     {
       "name": "CtsTelephony2TestCases",
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 9a5b506..c769bcc 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -1 +1,8 @@
 package: "com.android.internal.telephony.flags"
+
+flag {
+  name: "relax_ho_teardown"
+  namespace: "telephony"
+  description: "Relax handover tear down if the device is currently in voice call."
+  bug: "270895912"
+}
\ No newline at end of file
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 84e491e..777edb7 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -1 +1,8 @@
-package: "com.android.internal.telephony.flags"
\ No newline at end of file
+package: "com.android.internal.telephony.flags"
+
+flag {
+  name: "reject_bad_sub_id_interaction"
+  namespace: "telephony"
+  description: "Previously, the DB allows insertion of a random sub Id, but doesn't allow query it. This change rejects such interaction."
+  bug: "294125411"
+}
\ No newline at end of file
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 84e491e..58d31f2 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -1 +1,9 @@
-package: "com.android.internal.telephony.flags"
\ No newline at end of file
+package: "com.android.internal.telephony.flags"
+
+flag {
+  name: "do_not_override_precise_label"
+  namespace: "telephony"
+  description: "When set, Telecom will not override the precise label for certain disconnect causes."
+  bug: "296968778"
+  is_fixed_read_only: true
+}
\ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
index 8c905c3..1fd7485 100644
--- a/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/CarrierServiceStateTracker.java
@@ -24,6 +24,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.os.Handler;
 import android.os.HandlerExecutor;
@@ -153,7 +154,11 @@
                     }
                 });
 
-        registerNotificationTypes();
+        if (!mPhone.getContext().getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WATCH)) {
+            registerNotificationTypes();
+        }
+
         mAllowedNetworkType = RadioAccessFamily.getNetworkTypeFromRaf(
                 (int) mPhone.getAllowedNetworkTypes(
                         TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER));
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 826af3f..3c8c5f3 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -6063,6 +6063,7 @@
             case RIL_REQUEST_GET_IMEISV:
             case RIL_REQUEST_SIM_OPEN_CHANNEL:
             case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL:
+            case RIL_REQUEST_DEVICE_IMEI:
 
                 if (!RILJ_LOGV) {
                     // If not versbose logging just return and don't display IMSI and IMEI, IMEISV
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index c56c544..019ee21 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -99,6 +99,7 @@
 import com.android.internal.telephony.metrics.ServiceStateStats;
 import com.android.internal.telephony.metrics.TelephonyMetrics;
 import com.android.internal.telephony.satellite.NtnCapabilityResolver;
+import com.android.internal.telephony.satellite.SatelliteController;
 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
 import com.android.internal.telephony.subscription.SubscriptionManagerService;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState;
@@ -4971,6 +4972,7 @@
      */
     public void powerOffRadioSafely() {
         synchronized (this) {
+            SatelliteController.getInstance().onCellularRadioPowerOffRequested();
             if (!mPendingRadioPowerOffAfterDataOff) {
                 // hang up all active voice calls first
                 if (mPhone.isPhoneTypeGsm() && mPhone.isInCall()) {
@@ -5056,7 +5058,6 @@
         }
 
         mCi.setRadioPower(false, obtainMessage(EVENT_RADIO_POWER_OFF_DONE));
-
     }
 
     /** Cancel a pending (if any) pollState() operation */
diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java
index 310f72a..6858c6a 100644
--- a/src/java/com/android/internal/telephony/data/DataEvaluation.java
+++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java
@@ -145,13 +145,23 @@
     }
 
     /**
-     * Check if only the given reasons present in the disallowed reasons if there are any.
+     * Check if only one disallowed reason prevent data connection.
      *
-     * @param reasons The given reasons to check
-     * @return {@code true} if the disallowed reasons contain no disallowed reasons other than the
-     * given reasons.
+     * @param reason The given reason to check
+     * @return {@code true} if the given reason is the only one that prevents data connection
      */
-    public boolean containsOnly(DataDisallowedReason... reasons) {
+    public boolean containsOnly(DataDisallowedReason reason) {
+        return mDataDisallowedReasons.size() == 1 && contains(reason);
+    }
+
+    /**
+     * Check if all the disallowed reasons are a subset of the given reason.
+     *
+     * @param reasons The given reason to check
+     * @return {@code true} if it doesn't contain any disallowed reasons other than the given
+     * reasons.
+     */
+    public boolean isSubsetOf(DataDisallowedReason... reasons) {
         int matched = 0;
         for (DataDisallowedReason requestedReason : reasons) {
             if (mDataDisallowedReasons.contains(requestedReason)) matched++;
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index ab0d326..3073f49 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -3237,9 +3237,10 @@
                     + AccessNetworkConstants.transportTypeToString(targetTransport));
             dataNetwork.startHandover(targetTransport, dataHandoverRetryEntry);
         } else if (dataNetwork.shouldDelayImsTearDownDueToInCall()
-                && dataEvaluation.containsOnly(
+                && (dataEvaluation.containsOnly(DataDisallowedReason.NOT_IN_SERVICE)
+                || mFeatureFlags.relaxHoTeardown() && dataEvaluation.isSubsetOf(
                         DataDisallowedReason.NOT_IN_SERVICE,
-                        DataDisallowedReason.NOT_ALLOWED_BY_POLICY)) {
+                        DataDisallowedReason.NOT_ALLOWED_BY_POLICY))) {
             // We try our best to preserve the voice call by retrying later
             if (dataHandoverRetryEntry != null) {
                 dataHandoverRetryEntry.setState(DataRetryEntry.RETRY_STATE_FAILED);
@@ -3247,7 +3248,7 @@
             mDataRetryManager.evaluateDataHandoverRetry(dataNetwork,
                     DataFailCause.HANDOVER_FAILED,
                     DataCallResponse.RETRY_DURATION_UNDEFINED /* retry mills */);
-            logl("tryHandoverDataNetwork: Scheduled retry due to in voice call");
+            logl("tryHandoverDataNetwork: Scheduled retry due to in voice call and target OOS");
         } else if (dataEvaluation.containsAny(DataDisallowedReason.NOT_ALLOWED_BY_POLICY,
                 DataDisallowedReason.NOT_IN_SERVICE,
                 DataDisallowedReason.VOPS_NOT_SUPPORTED)) {
@@ -3256,7 +3257,8 @@
                     + AccessNetworkConstants.transportTypeToString(targetTransport));
             tearDownGracefully(dataNetwork,
                     DataNetwork.TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED);
-        } else if (dataEvaluation.containsAny(DataDisallowedReason.ILLEGAL_STATE)) {
+        } else if (dataEvaluation.containsAny(DataDisallowedReason.ILLEGAL_STATE,
+                DataDisallowedReason.RETRY_SCHEDULED)) {
             logl("tryHandoverDataNetwork: Handover not allowed. " + dataNetwork
                     + " will remain on " + AccessNetworkConstants.transportTypeToString(
                     dataNetwork.getTransport()));
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 01ba435..db40e88 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -79,6 +79,7 @@
 import com.android.internal.util.FunctionalUtils;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -223,11 +224,10 @@
      * {@link android.telephony.NetworkRegistrationInfo.ServiceType})
      */
     @GuardedBy("mSupportedSatelliteServicesLock")
-    @NonNull private final Map<Integer, Map<String, Set<Integer>>> mSupportedSatelliteServices =
-            new HashMap<>();
+    @NonNull private final Map<Integer, Map<String, Set<Integer>>>
+            mSatelliteServicesSupportedByCarriers = new HashMap<>();
     @NonNull private final Object mSupportedSatelliteServicesLock = new Object();
-    /** Key: PLMN, value: set of {@link android.telephony.NetworkRegistrationInfo.ServiceType} */
-    @NonNull private final Map<String, Set<Integer>> mSatelliteServicesSupportedByProviders;
+    @NonNull private final List<String> mSatellitePlmnListFromOverlayConfig;
     @NonNull private final CarrierConfigManager mCarrierConfigManager;
     @NonNull private final CarrierConfigManager.CarrierConfigChangeListener
             mCarrierConfigChangeListener;
@@ -331,7 +331,7 @@
                     false, satelliteModeRadiosContentObserver);
         }
 
-        mSatelliteServicesSupportedByProviders = readSupportedSatelliteServicesFromOverlayConfig();
+        mSatellitePlmnListFromOverlayConfig = readSatellitePlmnsFromOverlayConfig();
         updateSupportedSatelliteServicesForActiveSubscriptions();
         mCarrierConfigChangeListener =
                 (slotIndex, subId, carrierId, specificCarrierId) ->
@@ -1038,29 +1038,7 @@
             }
 
             case EVENT_RADIO_STATE_CHANGED: {
-                if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF
-                        || mCi.getRadioState() == TelephonyManager.RADIO_POWER_UNAVAILABLE) {
-                    mIsRadioOn = false;
-                    logd("Radio State Changed to " + mCi.getRadioState());
-                    if (isSatelliteEnabled()) {
-                        IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
-                            @Override
-                            public void accept(int result) {
-                                logd("RequestSatelliteEnabled: result=" + result);
-                            }
-                        };
-                        Phone phone = SatelliteServiceUtils.getPhone();
-                        Consumer<Integer> result = FunctionalUtils
-                                .ignoreRemoteException(errorCallback::accept);
-                        RequestSatelliteEnabledArgument message =
-                                new RequestSatelliteEnabledArgument(false, false, result);
-                        request = new SatelliteControllerHandlerRequest(message, phone);
-                        handleSatelliteEnabled(request);
-                    } else {
-                        logd("EVENT_RADIO_STATE_CHANGED: Satellite modem is currently disabled."
-                                + " Ignored the event");
-                    }
-                } else {
+                if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
                     mIsRadioOn = true;
                     if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
                         synchronized (mIsSatelliteSupportedLock) {
@@ -1899,6 +1877,10 @@
             @NonNull IIntegerConsumer callback) {
         if (DBG) logd("addSatelliteAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
         Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
+        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+            result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+            return;
+        }
 
         synchronized (mIsSatelliteEnabledLock) {
             if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault(
@@ -1930,8 +1912,13 @@
     public void removeSatelliteAttachRestrictionForCarrier(int subId,
             @SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
             @NonNull IIntegerConsumer callback) {
-        Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
         if (DBG) logd("removeSatelliteAttachRestrictionForCarrier(" + subId + ", " + reason + ")");
+        Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
+        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+            result.accept(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
+            return;
+        }
+
         synchronized (mIsSatelliteEnabledLock) {
             if (mSatelliteAttachRestrictionForCarrierArray.getOrDefault(
                     subId, Collections.emptySet()).isEmpty()
@@ -1956,7 +1943,10 @@
      *
      * @return Set of reasons for disallowing satellite attach for carrier.
      */
-    public @NonNull Set<Integer> getSatelliteAttachRestrictionReasonsForCarrier(int subId) {
+    @NonNull public Set<Integer> getSatelliteAttachRestrictionReasonsForCarrier(int subId) {
+        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+            return new HashSet<>();
+        }
         synchronized (mIsSatelliteEnabledLock) {
             Set<Integer> resultSet =
                     mSatelliteAttachRestrictionForCarrierArray.get(subId);
@@ -2086,6 +2076,27 @@
     }
 
     /**
+     * This function is used by {@link com.android.internal.telephony.ServiceStateTracker} to notify
+     * {@link SatelliteController} that it has received a request to power off the cellular radio
+     * modem. {@link SatelliteController} will then power off the satellite modem.
+     */
+    public void onCellularRadioPowerOffRequested() {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            return;
+        }
+
+        mIsRadioOn = false;
+        requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+                false /* enableSatellite */, false /* enableDemoMode */,
+                new IIntegerConsumer.Stub() {
+                    @Override
+                    public void accept(int result) {
+                        logd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result);
+                    }
+                });
+    }
+
+    /**
      * @return {@code true} is satellite is supported on the device, {@code  false} otherwise.
      */
     public boolean isSatelliteSupported() {
@@ -2100,8 +2111,8 @@
     @NonNull
     public List<String> getSatellitePlmnList(int subId) {
         synchronized (mSupportedSatelliteServicesLock) {
-            if (mSupportedSatelliteServices.containsKey(subId)) {
-                return new ArrayList<>(mSupportedSatelliteServices.get(subId).keySet());
+            if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
+                return new ArrayList<>(mSatelliteServicesSupportedByCarriers.get(subId).keySet());
             } else {
                 return new ArrayList<>();
             }
@@ -2117,9 +2128,9 @@
     @NonNull
     public List<Integer> getSupportedSatelliteServices(int subId, String plmn) {
         synchronized (mSupportedSatelliteServicesLock) {
-            if (mSupportedSatelliteServices.containsKey(subId)) {
+            if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
                 Map<String, Set<Integer>> supportedServices =
-                        mSupportedSatelliteServices.get(subId);
+                        mSatelliteServicesSupportedByCarriers.get(subId);
                 if (supportedServices != null && supportedServices.containsKey(plmn)) {
                     return new ArrayList<>(supportedServices.get(plmn));
                 } else {
@@ -2127,8 +2138,8 @@
                             + "does not contain key plmn=" + plmn);
                 }
             } else {
-                loge("getSupportedSatelliteServices: mSupportedSatelliteServices does contain key"
-                        + " subId=" + subId);
+                loge("getSupportedSatelliteServices: mSatelliteServicesSupportedByCarriers does "
+                        + "not contain key subId=" + subId);
             }
             return new ArrayList<>();
         }
@@ -2590,11 +2601,22 @@
     }
 
     private void configureSatellitePlmnForCarrier(int subId) {
-        logd("configureSatellitePlmnForCarrier()");
-        List<String> satellitePlmnList = getSatellitePlmnList(subId);
-        if (!satellitePlmnList.isEmpty()) {
+        logd("configureSatellitePlmnForCarrier");
+        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+            return;
+        }
+        synchronized (mSupportedSatelliteServicesLock) {
+            List<String> carrierPlmnList;
+            if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
+                carrierPlmnList =
+                        mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList();
+            } else {
+                carrierPlmnList = new ArrayList<>();
+            }
             int slotId = SubscriptionManager.getSlotIndex(subId);
-            mSatelliteModemInterface.setSatellitePlmn(slotId, satellitePlmnList,
+            mSatelliteModemInterface.setSatellitePlmn(slotId, carrierPlmnList,
+                    SatelliteServiceUtils.mergeStrLists(
+                            carrierPlmnList, mSatellitePlmnListFromOverlayConfig),
                     obtainMessage(EVENT_SET_SATELLITE_PLMN_INFO_DONE));
         }
     }
@@ -2605,8 +2627,12 @@
     }
 
     private void updateSupportedSatelliteServicesForActiveSubscriptions() {
+        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+            return;
+        }
+
         synchronized (mSupportedSatelliteServicesLock) {
-            mSupportedSatelliteServices.clear();
+            mSatelliteServicesSupportedByCarriers.clear();
             int[] activeSubIds = mSubscriptionManagerService.getActiveSubIdList(true);
             if (activeSubIds != null) {
                 for (int subId : activeSubIds) {
@@ -2620,21 +2646,21 @@
     }
 
     private void updateSupportedSatelliteServices(int subId) {
-        Map<String, Set<Integer>> carrierSupportedSatelliteServicesPerPlmn =
-                readSupportedSatelliteServicesFromCarrierConfig(subId);
         synchronized (mSupportedSatelliteServicesLock) {
-            mSupportedSatelliteServices.put(subId,
-                    SatelliteServiceUtils.mergeSupportedSatelliteServices(
-                            mSatelliteServicesSupportedByProviders,
-                            carrierSupportedSatelliteServicesPerPlmn));
+            mSatelliteServicesSupportedByCarriers.put(
+                    subId, readSupportedSatelliteServicesFromCarrierConfig(subId));
         }
     }
 
     @NonNull
-    private Map<String, Set<Integer>> readSupportedSatelliteServicesFromOverlayConfig() {
-        String[] supportedServices = readStringArrayFromOverlayConfig(
-                R.array.config_satellite_services_supported_by_providers);
-        return SatelliteServiceUtils.parseSupportedSatelliteServices(supportedServices);
+    private List<String> readSatellitePlmnsFromOverlayConfig() {
+        if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+            return new ArrayList<>();
+        }
+
+        String[] devicePlmns = readStringArrayFromOverlayConfig(
+                R.array.config_satellite_providers);
+        return Arrays.stream(devicePlmns).toList();
     }
 
     @NonNull
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index d03587f..6ecb642 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -1039,15 +1039,19 @@
      *
      * @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 plmnList The list of roaming PLMN used for connecting to satellite networks.
+     * @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 message The result receiver that returns whether the modem has
-     *               successfully set the satellite PLMN
+     *                successfully set the satellite PLMN
      */
-    public void setSatellitePlmn(@NonNull int simSlot, @NonNull List<String> plmnList,
-            @NonNull Message message) {
+    public void setSatellitePlmn(@NonNull int simSlot, @NonNull List<String> carrierPlmnList,
+            @NonNull List<String> allSatellitePlmnList, @NonNull Message message) {
         if (mSatelliteService != null) {
             try {
-                mSatelliteService.setSatellitePlmn(simSlot, plmnList,
+                mSatelliteService.setSatellitePlmn(simSlot, carrierPlmnList, allSatellitePlmnList,
                         new IIntegerConsumer.Stub() {
                             @Override
                             public void accept(int result) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index ba68f8d..cad9bfb 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
@@ -48,6 +48,7 @@
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -278,61 +279,6 @@
     }
 
     /**
-     * Expected format of each input string in the array: "PLMN_1:service_1,service_2,..."
-     *
-     * @return The map of supported services with key: PLMN, value: set of services supported by
-     * the PLMN.
-     */
-    @NonNull
-    @NetworkRegistrationInfo.ServiceType
-    public static Map<String, Set<Integer>> parseSupportedSatelliteServices(
-            String[] supportedSatelliteServicesStrArray) {
-        Map<String, Set<Integer>> supportedServicesMap = new HashMap<>();
-        if (supportedSatelliteServicesStrArray == null
-                || supportedSatelliteServicesStrArray.length == 0) {
-            return supportedServicesMap;
-        }
-
-        for (String supportedServicesPerPlmnStr : supportedSatelliteServicesStrArray) {
-            String[] pairOfPlmnAndsupportedServicesStr =
-                    supportedServicesPerPlmnStr.split(":");
-            if (pairOfPlmnAndsupportedServicesStr != null
-                    && (pairOfPlmnAndsupportedServicesStr.length == 1
-                    || pairOfPlmnAndsupportedServicesStr.length == 2)) {
-                String plmn = pairOfPlmnAndsupportedServicesStr[0];
-                Set<Integer> supportedServicesSet = new HashSet<>();
-                if (pairOfPlmnAndsupportedServicesStr.length == 2) {
-                    String[] supportedServicesStrArray =
-                            pairOfPlmnAndsupportedServicesStr[1].split(",");
-                    for (String service : supportedServicesStrArray) {
-                        try {
-                            int serviceType = Integer.parseInt(service);
-                            if (isServiceTypeValid(serviceType)) {
-                                supportedServicesSet.add(serviceType);
-                            } else {
-                                loge("parseSupportedSatelliteServices: invalid serviceType="
-                                        + serviceType);
-                            }
-                        } catch (NumberFormatException e) {
-                            loge("parseSupportedSatelliteServices: supportedServicesPerPlmnStr="
-                                    + supportedServicesPerPlmnStr + ", service=" + service
-                                    + ", e=" + e);
-                        }
-                    }
-                }
-                logd("parseSupportedSatelliteServices: plmn=" + plmn + ", supportedServicesSet="
-                        + supportedServicesSet.stream().map(String::valueOf).collect(
-                                joining(",")));
-                supportedServicesMap.put(plmn, supportedServicesSet);
-            } else {
-                loge("parseSupportedSatelliteServices: invalid format input, "
-                        + "supportedServicesPerPlmnStr=" + supportedServicesPerPlmnStr);
-            }
-        }
-        return supportedServicesMap;
-    }
-
-    /**
      * Expected format of the input dictionary bundle is:
      * <ul>
      *     <li>Key: PLMN string.</li>
@@ -369,36 +315,14 @@
     }
 
     /**
-     * For the PLMN that exists in {@code carrierSupportedServices}, the carrier supported services
-     * will be used. For the PLMN that is present in {@code providerSupportedServices} but not in
-     * {@code carrierSupportedServices}, the provider supported services will be used.
-     *
-     * @param providerSupportedServices Satellite provider supported satellite services.
-     * @param carrierSupportedServices Carrier supported satellite services.
-     * @return The supported satellite services by the device for the corresponding carrier and the
-     * satellite provider.
+     * Merge two string lists into one such that the result list does not have any duplicate items.
      */
     @NonNull
-    @NetworkRegistrationInfo.ServiceType
-    public static Map<String, Set<Integer>> mergeSupportedSatelliteServices(
-            @NonNull @NetworkRegistrationInfo.ServiceType Map<String, Set<Integer>>
-                    providerSupportedServices,
-            @NonNull @NetworkRegistrationInfo.ServiceType Map<String, Set<Integer>>
-                    carrierSupportedServices) {
-        Map<String, Set<Integer>> supportedServicesMap = new HashMap<>();
-        for (Map.Entry<String, Set<Integer>> entry : providerSupportedServices.entrySet()) {
-            if (!entry.getValue().isEmpty()) {
-                supportedServicesMap.put(entry.getKey(), entry.getValue());
-            }
-        }
-        for (Map.Entry<String, Set<Integer>> entry : carrierSupportedServices.entrySet()) {
-            if (entry.getValue().isEmpty()) {
-                supportedServicesMap.remove(entry.getKey());
-            } else {
-                supportedServicesMap.put(entry.getKey(), entry.getValue());
-            }
-        }
-        return supportedServicesMap;
+    public static List<String> mergeStrLists(List<String> strList1, List<String> strList2) {
+        Set<String> mergedStrSet = new HashSet<>();
+        mergedStrSet.addAll(strList1);
+        mergedStrSet.addAll(strList2);
+        return mergedStrSet.stream().toList();
     }
 
     private static boolean isServiceTypeValid(int serviceType) {
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index 3fcbdb8..2e2b147 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -48,6 +48,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.util.function.TriConsumer;
 import com.android.telephony.Rlog;
@@ -277,8 +278,10 @@
                     SubscriptionInfoInternal::getSatelliteEnabled),
             new AbstractMap.SimpleImmutableEntry<>(
                     SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
-                    SubscriptionInfoInternal::getSatelliteAttachEnabledForCarrier)
-
+                    SubscriptionInfoInternal::getSatelliteAttachEnabledForCarrier),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_IS_NTN,
+                    SubscriptionInfoInternal::getNtn)
     );
 
     /**
@@ -406,7 +409,10 @@
                     SubscriptionDatabaseManager::setSatelliteEnabled),
             new AbstractMap.SimpleImmutableEntry<>(
                     SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
-                    SubscriptionDatabaseManager::setSatelliteAttachEnabledForCarrier)
+                    SubscriptionDatabaseManager::setSatelliteAttachEnabledForCarrier),
+            new AbstractMap.SimpleImmutableEntry<>(
+                    SimInfo.COLUMN_IS_NTN,
+                    SubscriptionDatabaseManager::setNtn)
     );
 
     /**
@@ -538,6 +544,10 @@
     @NonNull
     private final Context mContext;
 
+    /** The feature flags */
+    @NonNull
+    private final FeatureFlags mFeatureFlags;
+
     /** The callback used for passing events back to {@link SubscriptionManagerService}. */
     @NonNull
     private final SubscriptionDatabaseManagerCallback mCallback;
@@ -628,9 +638,11 @@
      *
      * @param context The context.
      * @param looper Looper for the handler.
+     * @param featureFlags The feature flags.
      * @param callback Subscription database callback.
      */
     public SubscriptionDatabaseManager(@NonNull Context context, @NonNull Looper looper,
+            @NonNull FeatureFlags featureFlags,
             @NonNull SubscriptionDatabaseManagerCallback callback) {
         super(looper);
         log("Created SubscriptionDatabaseManager.");
@@ -639,6 +651,7 @@
         mUiccController = UiccController.getInstance();
         mAsyncMode = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_subscription_database_async_update);
+        mFeatureFlags = featureFlags;
         initializeDatabase();
     }
 
@@ -2014,6 +2027,23 @@
     }
 
     /**
+     * Set whether the subscription is exclusively used for non-terrestrial networks or not.
+     *
+     * @param subId Subscription ID.
+     * @param isNtn {@code 1} if it is a non-terrestrial network subscription.
+     * {@code 0} otherwise.
+     *
+     * @throws IllegalArgumentException if the subscription does not exist.
+     */
+    public void setNtn(int subId, int isNtn) {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            return;
+        }
+        writeDatabaseAndCacheHelper(subId, SimInfo.COLUMN_IS_NTN, isNtn,
+                SubscriptionInfoInternal.Builder::setNtn);
+    }
+
+    /**
      * Set whether group of the subscription is disabled. This is only useful if it's a grouped
      * opportunistic subscription. In this case, if all primary (non-opportunistic)
      * subscriptions in the group are deactivated (unplugged pSIM or deactivated eSIM profile),
@@ -2272,7 +2302,11 @@
                         SimInfo.COLUMN_SATELLITE_ENABLED)))
                 .setSatelliteAttachEnabledForCarrier(cursor.getInt(
                         cursor.getColumnIndexOrThrow(
-                        SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER)));
+                                SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER)));
+        if (mFeatureFlags.oemEnabledSatelliteFlag()) {
+            builder.setNtn(cursor.getInt(cursor.getColumnIndexOrThrow(
+                    SimInfo.COLUMN_IS_NTN)));
+        }
         return builder.build();
     }
 
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index 4eda949..942e9ce 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -448,6 +448,12 @@
      */
     private final int mIsSatelliteAttachEnabledForCarrier;
 
+    /**
+     * Whether this subscription is used for communicating with non-terrestrial networks.
+     * By default, its disabled. It is intended to use integer to fit the database format.
+     */
+    private final int mIsNtn;
+
     // Below are the fields that do not exist in the SimInfo table.
     /**
      * The card ID of the SIM card. This maps uniquely to {@link #mCardString}.
@@ -532,6 +538,7 @@
         this.mIsSatelliteEnabled = builder.mIsSatelliteEnabled;
         this.mIsSatelliteAttachEnabledForCarrier =
                 builder.mIsSatelliteAttachEnabledForCarrier;
+        this.mIsNtn = builder.mIsNtn;
 
         // Below are the fields that do not exist in the SimInfo table.
         this.mCardId = builder.mCardId;
@@ -1143,6 +1150,15 @@
         return mIsSatelliteAttachEnabledForCarrier;
     }
 
+    /**
+     * An NTN subscription connects to non-terrestrial networks.
+     *
+     * @return {@code 1} if the subscription is for non-terrestrial networks. {@code 0} otherwise.
+     */
+    public int getNtn() {
+        return mIsNtn;
+    }
+
     // Below are the fields that do not exist in SimInfo table.
     /**
      * @return The card ID of the SIM card which contains the subscription.
@@ -1212,6 +1228,7 @@
                 .setUiccApplicationsEnabled(mAreUiccApplicationsEnabled != 0)
                 .setPortIndex(mPortIndex)
                 .setUsageSetting(mUsageSetting)
+                .setNtn(mIsNtn == 1)
                 .build();
     }
 
@@ -1269,6 +1286,7 @@
                 + " userId=" + mUserId
                 + " isSatelliteEnabled=" + mIsSatelliteEnabled
                 + " satellite_attach_enabled_for_carrier=" + mIsSatelliteAttachEnabledForCarrier
+                + " getNtn=" + mIsNtn
                 + " isGroupDisabled=" + mIsGroupDisabled
                 + "]";
     }
@@ -1325,7 +1343,8 @@
                 that.mAllowedNetworkTypesForReasons) && mDeviceToDeviceStatusSharingContacts.equals(
                 that.mDeviceToDeviceStatusSharingContacts) && mNumberFromCarrier.equals(
                 that.mNumberFromCarrier) && mNumberFromIms.equals(that.mNumberFromIms)
-                && mIsSatelliteAttachEnabledForCarrier == that.mIsSatelliteAttachEnabledForCarrier;
+                && mIsSatelliteAttachEnabledForCarrier == that.mIsSatelliteAttachEnabledForCarrier
+                && mIsNtn == that.mIsNtn;
     }
 
     @Override
@@ -1347,7 +1366,7 @@
                 mNumberFromCarrier,
                 mNumberFromIms, mPortIndex, mUsageSetting, mLastUsedTPMessageReference, mUserId,
                 mIsSatelliteEnabled, mCardId, mIsGroupDisabled,
-                mIsSatelliteAttachEnabledForCarrier);
+                mIsSatelliteAttachEnabledForCarrier, mIsNtn);
         result = 31 * result + Arrays.hashCode(mNativeAccessRules);
         result = 31 * result + Arrays.hashCode(mCarrierConfigAccessRules);
         result = 31 * result + Arrays.hashCode(mRcsConfig);
@@ -1708,12 +1727,17 @@
         /**
          * Whether satellite is enabled or not.
          */
-        private int mIsSatelliteEnabled = -1;
+        private int mIsSatelliteEnabled = 0;
 
         /**
          * Whether satellite attach for carrier is enabled by user.
          */
-        private int mIsSatelliteAttachEnabledForCarrier = -1;
+        private int mIsSatelliteAttachEnabledForCarrier = 0;
+
+        /**
+         * Whether this subscription is used for communicating with non-terrestrial network or not.
+         */
+        private int mIsNtn = 0;
 
         // The following fields do not exist in the SimInfo table.
         /**
@@ -1803,6 +1827,7 @@
             mUserId = info.mUserId;
             mIsSatelliteEnabled = info.mIsSatelliteEnabled;
             mIsSatelliteAttachEnabledForCarrier = info.mIsSatelliteAttachEnabledForCarrier;
+            mIsNtn = info.mIsNtn;
             // Below are the fields that do not exist in the SimInfo table.
             mCardId = info.mCardId;
             mIsGroupDisabled = info.mIsGroupDisabled;
@@ -2686,6 +2711,18 @@
             return this;
         }
 
+        /**
+         * Set whether the subscription is for NTN or not.
+         *
+         * @param isNtn {@code 1} if the subscription is for NTN, {@code 0} otherwise.
+         * @return The builder.
+         */
+        @NonNull
+        public Builder setNtn(int isNtn) {
+            mIsNtn = isNtn;
+            return this;
+        }
+
         // Below are the fields that do not exist in the SimInfo table.
         /**
          * Set the card ID of the SIM card which contains the subscription.
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index 3b03a62..aeb1702 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -175,7 +175,8 @@
             SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS,
             SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED,
             SimInfo.COLUMN_SATELLITE_ENABLED,
-            SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER
+            SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER,
+            SimInfo.COLUMN_IS_NTN
     );
 
     /**
@@ -488,7 +489,8 @@
         HandlerThread handlerThread = new HandlerThread(LOG_TAG);
         handlerThread.start();
         mSubscriptionDatabaseManager = new SubscriptionDatabaseManager(context,
-                handlerThread.getLooper(), new SubscriptionDatabaseManagerCallback(mHandler::post) {
+                handlerThread.getLooper(), mFeatureFlags,
+                new SubscriptionDatabaseManagerCallback(mHandler::post) {
                     /**
                      * Called when database has been loaded into the cache.
                      */
@@ -826,6 +828,26 @@
     }
 
     /**
+     * Set whether the subscription ID supports oem satellite or not.
+     *
+     * @param subId The subscription ID.
+     * @param isNtn {@code true} Requested subscription ID supports oem satellite service,
+     * {@code false} otherwise.
+     */
+    public void setNtn(int subId, boolean isNtn) {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            return;
+        }
+
+        // This can throw IllegalArgumentException if the subscription does not exist.
+        try {
+            mSubscriptionDatabaseManager.setNtn(subId, (isNtn ? 1 : 0));
+        } catch (IllegalArgumentException e) {
+            loge("setNtn: invalid subId=" + subId);
+        }
+    }
+
+    /**
      * Set ISO country code by subscription id.
      *
      * @param iso ISO country code associated with the subscription.
@@ -1120,6 +1142,9 @@
                         String mnc = cid.getMnc();
                         builder.setMcc(mcc);
                         builder.setMnc(mnc);
+                        if (mFeatureFlags.oemEnabledSatelliteFlag()) {
+                            builder.setNtn(isSatellitePlmn(mcc + mnc) ? 1 : 0);
+                        }
                     }
                     // If cardId = unsupported or un-initialized, we have no reason to update DB.
                     // Additionally, if the device does not support cardId for default eUICC, the
@@ -1391,6 +1416,7 @@
                             MccTable.updateMccMncConfiguration(mContext, mccMnc);
                         }
                         setMccMnc(subId, mccMnc);
+                        setNtn(subId, isSatellitePlmn(mccMnc));
                     } else {
                         loge("updateSubscription: mcc/mnc is empty");
                     }
@@ -3620,7 +3646,7 @@
      * else {@code false} if subscription is not associated with user.
      *
      * @throws SecurityException if the caller doesn't have permissions required.
-     *
+     * @throws IllegalArgumentException if the subscription has no records on device.
      */
     @Override
     public boolean isSubscriptionAssociatedWithUser(int subscriptionId,
@@ -3630,18 +3656,11 @@
 
         long token = Binder.clearCallingIdentity();
         try {
-            // Return true if there are no subscriptions on the device.
-            List<SubscriptionInfo> subInfoList = getAllSubInfoList(
-                    mContext.getOpPackageName(), mContext.getAttributionTag());
-            if (subInfoList == null || subInfoList.isEmpty()) {
-                return true;
-            }
-
-            List<Integer> subIdList = subInfoList.stream().map(SubscriptionInfo::getSubscriptionId)
-                    .collect(Collectors.toList());
-            if (!subIdList.contains(subscriptionId)) {
-                // Return true as this subscription is not available on the device.
-                return true;
+            // Throw IAE if no record of the sub's association state.
+            if (mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subscriptionId) == null) {
+                throw new IllegalArgumentException(
+                        "[isSubscriptionAssociatedWithUser]: Subscription doesn't exist: "
+                                + subscriptionId);
             }
 
             // Get list of subscriptions associated with this user.
@@ -3683,23 +3702,21 @@
 
         long token = Binder.clearCallingIdentity();
         try {
-            List<SubscriptionInfo> subInfoList =  getAllSubInfoList(
-                    mContext.getOpPackageName(), mContext.getAttributionTag());
-            if (subInfoList == null || subInfoList.isEmpty()) {
+            List<SubscriptionInfoInternal> subInfoList =  mSubscriptionDatabaseManager
+                    .getAllSubscriptions();
+            if (subInfoList.isEmpty()) {
                 return new ArrayList<>();
             }
 
             List<SubscriptionInfo> subscriptionsAssociatedWithUser = new ArrayList<>();
             List<SubscriptionInfo> subscriptionsWithNoAssociation = new ArrayList<>();
-            for (SubscriptionInfo subInfo : subInfoList) {
-                int subId = subInfo.getSubscriptionId();
-                UserHandle subIdUserHandle = getSubscriptionUserHandle(subId);
-                if (userHandle.equals(subIdUserHandle)) {
+            for (SubscriptionInfoInternal subInfo : subInfoList) {
+                if (subInfo.getUserId() == userHandle.getIdentifier()) {
                     // Store subscriptions whose user handle matches with required user handle.
-                    subscriptionsAssociatedWithUser.add(subInfo);
-                } else if (subIdUserHandle == null) {
+                    subscriptionsAssociatedWithUser.add(subInfo.toSubscriptionInfo());
+                } else if (subInfo.getUserId() == UserHandle.USER_NULL) {
                     // Store subscriptions whose user handle is set to null.
-                    subscriptionsWithNoAssociation.add(subInfo);
+                    subscriptionsWithNoAssociation.add(subInfo.toSubscriptionInfo());
                 }
             }
 
@@ -3959,6 +3976,30 @@
     }
 
     /**
+     * @param mccMnc MccMnc value to check whether it supports non-terrestrial network or not.
+     * @return {@code true} if MCC/MNC is matched with in the device overlay key
+     * "config_satellite_esim_identifier", {@code false} otherwise.
+     */
+    private boolean isSatellitePlmn(@NonNull String mccMnc) {
+        if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+            return false;
+        }
+
+        final int id = R.string.config_satellite_sim_identifier;
+        String overlayMccMnc = null;
+        try {
+            overlayMccMnc = mContext.getResources().getString(id);
+        } catch (Resources.NotFoundException ex) {
+            loge("isSatellitePlmn: id= " + id + ", ex=" + ex);
+        }
+        if (overlayMccMnc == null) {
+            return false;
+        } else {
+            return mccMnc.equals(overlayMccMnc);
+        }
+    }
+
+    /**
      * Log debug messages.
      *
      * @param s debug messages
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
index e39c908..2302128 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierServiceStateTrackerTest.java
@@ -36,6 +36,7 @@
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
@@ -82,6 +83,7 @@
         mBundle = mContextFixture.getCarrierConfigBundle();
         when(mPhone.getSubId()).thenReturn(SUB_ID);
         when(mCarrierConfigManager.getConfigForSubId(anyInt(), any())).thenReturn(mBundle);
+        doReturn(false).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_WATCH);
 
         // Capture listener to emulate the carrier config change notification used later
         ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
@@ -303,6 +305,18 @@
                 eq(SUB_ID), isA(Notification.class));
     }
 
+
+    /** Verifies notification map is empty when device is watch. */
+    @Test
+    @SmallTest
+    public void testNotificationMapWhenDeviceIsWatch() {
+        doReturn(true).when(mPackageManager).hasSystemFeature(PackageManager.FEATURE_WATCH);
+
+        CarrierServiceStateTracker tracker = new CarrierServiceStateTracker(mPhone, mSST);
+
+        assertTrue(tracker.getNotificationTypeMap().isEmpty());
+    }
+
     private void sendMessageOnHandler(int messageWhat) {
         Message notificationMsg = mSpyCarrierSST.obtainMessage(messageWhat, null);
         doReturn(true).when(mSpyCarrierSST).evaluateSendingMessage(any());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
index 47e315d..2692057 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/FakeTelephonyProvider.java
@@ -128,9 +128,10 @@
                     + "  INTEGER DEFAULT -1,"
                     + Telephony.SimInfo.COLUMN_USER_HANDLE + " INTEGER DEFAULT "
                     + UserHandle.USER_NULL + ","
-                    + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + " INTEGER DEFAULT -1,"
+                    + Telephony.SimInfo.COLUMN_SATELLITE_ENABLED + " INTEGER DEFAULT 0,"
                     + Telephony.SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER
-                    + " INTEGER DEFAULT -1"
+                    + " INTEGER DEFAULT 0, "
+                    + Telephony.SimInfo.COLUMN_IS_NTN + " INTEGER DEFAULT 0"
                     + ");";
         }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 0a15c47..4bc2ab8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -32,6 +32,7 @@
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.never;
@@ -511,18 +512,22 @@
     }
 
     private void testSetRadioPowerForReason(int reason) {
+        clearInvocations(mSatelliteController);
         // Radio does not turn on if off for other reason and not emergency call.
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
         assertTrue(sst.getRadioPowerOffReasons().isEmpty());
         sst.setRadioPowerForReason(false, false, false, false, reason);
         assertTrue(sst.getRadioPowerOffReasons().contains(reason));
         assertTrue(sst.getRadioPowerOffReasons().size() == 1);
+        verify(mSatelliteController).onCellularRadioPowerOffRequested();
+        clearInvocations(mSatelliteController);
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
         sst.setRadioPowerForReason(true, false, false, false,
                 TelephonyManager.RADIO_POWER_REASON_USER);
         assertTrue(sst.getRadioPowerOffReasons().contains(reason));
         assertTrue(sst.getRadioPowerOffReasons().size() == 1);
+        verify(mSatelliteController, never()).onCellularRadioPowerOffRequested();
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_OFF);
 
@@ -530,6 +535,7 @@
         // had been turned off for.
         sst.setRadioPowerForReason(true, false, false, false, reason);
         assertTrue(sst.getRadioPowerOffReasons().isEmpty());
+        verify(mSatelliteController, never()).onCellularRadioPowerOffRequested();
         waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
         assertTrue(mSimulatedCommands.getRadioState() == TelephonyManager.RADIO_POWER_ON);
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
index 3bafe4d..20ad1a2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoTest.java
@@ -21,6 +21,8 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 
+import com.android.internal.telephony.flags.Flags;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -52,6 +54,7 @@
                 .setEhplmns(EHPLMNS)
                 .setHplmns(HPLMNS)
                 .setCountryIso("us")
+                .setNtn(true)
                 .build();
     }
 
@@ -71,6 +74,9 @@
         assertThat(mSubscriptionInfoUT.getSubscriptionId()).isEqualTo(1);
         assertThat(mSubscriptionInfoUT.getSimSlotIndex()).isEqualTo(0);
         assertThat(mSubscriptionInfoUT.getIccId()).isEqualTo("890126042XXXXXXXXXXX");
+        if (Flags.oemEnabledSatelliteFlag()) {
+            assertThat(mSubscriptionInfoUT.isNtn()).isTrue();
+        }
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index a053c56..ad66b55 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -48,6 +48,7 @@
 import android.test.mock.MockContentResolver;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.pm.permission.LegacyPermissionManagerService;
 
@@ -57,7 +58,6 @@
 
 import java.lang.reflect.Field;
 import java.util.Map;
-
 @SmallTest
 public class TelephonyPermissionsTest {
 
@@ -71,6 +71,7 @@
 
     // Mocked classes
     private Context mMockContext;
+    private FeatureFlags mMockFeatureFlag;
     private AppOpsManager mMockAppOps;
     private SubscriptionManager mMockSubscriptionManager;
     private ITelephony mMockTelephony;
@@ -84,10 +85,12 @@
 
     private MockContentResolver mMockContentResolver;
     private FakeSettingsConfigProvider mFakeSettingsConfigProvider;
+    private FeatureFlags mRealFeatureFlagToBeRestored;
 
     @Before
     public void setUp() throws Exception {
         mMockContext = mock(Context.class);
+        mMockFeatureFlag = mock(FeatureFlags.class);
         mMockAppOps = mock(AppOpsManager.class);
         mMockSubscriptionManager = mock(SubscriptionManager.class);
         mMockTelephony = mock(ITelephony.class);
@@ -129,13 +132,17 @@
                 .thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
         when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
                 PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED);
+
+        replaceFeatureFlag(mMockFeatureFlag);
         setTelephonyMockAsService();
     }
 
     @After
-    public void tearDown() {
+    public void tearDown() throws Exception {
+        replaceFeatureFlag(mRealFeatureFlagToBeRestored);
         mMockContentResolver = null;
         mFakeSettingsConfigProvider = null;
+        mRealFeatureFlagToBeRestored = null;
     }
 
     @Test
@@ -540,6 +547,30 @@
                 UserHandle.SYSTEM, "911"));
     }
 
+    @Test
+    public void testCheckSubscriptionAssociatedWithUser_badSub_flag_enabled() {
+        doReturn(true).when(mMockFeatureFlag).rejectBadSubIdInteraction();
+
+        doThrow(new IllegalArgumentException("has no records on device"))
+                .when(mMockSubscriptionManager).isSubscriptionAssociatedWithUser(SUB_ID,
+                        UserHandle.SYSTEM);
+        assertFalse(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext, SUB_ID,
+                UserHandle.SYSTEM));
+    }
+
+    @Test
+    public void testCheckSubscriptionAssociatedWithUser_badSub_flag_disabled() {
+        doReturn(false).when(mMockFeatureFlag).rejectBadSubIdInteraction();
+
+        doThrow(new IllegalArgumentException("No records found for sub"))
+                .when(mMockSubscriptionManager).isSubscriptionAssociatedWithUser(SUB_ID,
+                        UserHandle.SYSTEM);
+        assertTrue(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext, SUB_ID,
+                UserHandle.SYSTEM));
+        assertTrue(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext,
+                SubscriptionManager.INVALID_SUBSCRIPTION_ID, UserHandle.SYSTEM));
+    }
+
     // Put mMockTelephony into service cache so that TELEPHONY_SUPPLIER will get it.
     private void setTelephonyMockAsService() throws Exception {
         when(mMockTelephonyBinder.queryLocalInterface(anyString())).thenReturn(mMockTelephony);
@@ -630,4 +661,12 @@
         field.set(providerHolder, iContentProvider);
     }
 
+    private synchronized void replaceFeatureFlag(final FeatureFlags newValue)
+            throws Exception {
+        Field field = TelephonyPermissions.class.getDeclaredField("sFeatureFlag");
+        field.setAccessible(true);
+
+        mRealFeatureFlagToBeRestored = (FeatureFlags) field.get(null);
+        field.set(null, newValue);
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java
index 63f3e4f..6d4c0c1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataEvaluationTest.java
@@ -16,10 +16,10 @@
 
 package com.android.internal.telephony.data;
 
-import com.android.internal.telephony.TelephonyTest;
-
 import static com.google.common.truth.Truth.assertThat;
 
+import com.android.internal.telephony.TelephonyTest;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -59,4 +59,32 @@
                 DataEvaluation.DataDisallowedReason.DATA_DISABLED);
         assertThat(mDataEvaluationUT.getDataDisallowedReasons().size()).isEqualTo(1);
     }
+
+
+    @Test
+    public void testIsSubsetOf() {
+        mDataEvaluationUT = new DataEvaluation(DataEvaluation.DataEvaluationReason.DATA_RETRY);
+        assertThat(mDataEvaluationUT.isSubsetOf(
+                DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isTrue();
+        mDataEvaluationUT.addDataDisallowedReason(
+                DataEvaluation.DataDisallowedReason.DATA_DISABLED);
+        assertThat(mDataEvaluationUT.isSubsetOf(
+                DataEvaluation.DataDisallowedReason.DATA_DISABLED)).isTrue();
+        assertThat(mDataEvaluationUT.isSubsetOf(
+                DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isFalse();
+    }
+
+    @Test
+    public void testContainsOnly() {
+        mDataEvaluationUT = new DataEvaluation(DataEvaluation.DataEvaluationReason.DATA_RETRY);
+        assertThat(mDataEvaluationUT.containsOnly(
+                DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isFalse();
+        mDataEvaluationUT.addDataDisallowedReason(
+                DataEvaluation.DataDisallowedReason.DATA_DISABLED);
+        assertThat(mDataEvaluationUT.containsOnly(
+                DataEvaluation.DataDisallowedReason.DATA_DISABLED)).isTrue();
+        assertThat(mDataEvaluationUT.containsOnly(
+                DataEvaluation.DataDisallowedReason.ROAMING_DISABLED)).isFalse();
+    }
+
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index 6d8449a..5e7213b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -2460,6 +2460,7 @@
                         "source=IWLAN, target=EUTRAN, type=disallowed, capabilities=MMS"});
         // Force data config manager to reload the carrier config.
         carrierConfigChanged();
+        processAllMessages();
 
         testSetupImsDataNetwork();
 
@@ -2500,6 +2501,7 @@
 
     @Test
     public void testHandoverDataNetworkNotAllowedByPolicyDelayDueToVoiceCall() throws Exception {
+        doReturn(true).when(mFeatureFlags).relaxHoTeardown();
         // Config delay IMS tear down enabled
         mCarrierConfig.putBoolean(CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL,
                 true);
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 d9cf43c..2d810b3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -42,6 +42,7 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_RESOURCES;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
@@ -69,6 +70,7 @@
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
@@ -137,7 +139,8 @@
     private static final int MAX_BYTES_PER_OUT_GOING_DATAGRAM = 339;
     private static final String TEST_SATELLITE_TOKEN = "TEST_SATELLITE_TOKEN";
     private static final String TEST_NEXT_SATELLITE_TOKEN = "TEST_NEXT_SATELLITE_TOKEN";
-    private static final String[] EMPTY_SATELLITE_SERVICES_SUPPORTED_BY_PROVIDERS_STRING_ARRAY = {};
+    private static final String[] EMPTY_STRING_ARRAY = {};
+    private static final List<String> EMPTY_STRING_LIST = new ArrayList<>();
     private static final int[] ACTIVE_SUB_IDS = {SUB_ID};
     private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>>
             mCarrierConfigChangedListenerList = new ArrayList<>();
@@ -396,8 +399,8 @@
                 mMockSubscriptionManagerService);
 
         mContextFixture.putStringArrayResource(
-                R.array.config_satellite_services_supported_by_providers,
-                EMPTY_SATELLITE_SERVICES_SUPPORTED_BY_PROVIDERS_STRING_ARRAY);
+                R.array.config_satellite_providers,
+                EMPTY_STRING_ARRAY);
         doReturn(ACTIVE_SUB_IDS).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
 
         mCarrierConfigBundle = mContextFixture.getCarrierConfigBundle();
@@ -668,6 +671,7 @@
         mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
         setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
         setRadioPower(false);
+        mSatelliteControllerUT.onCellularRadioPowerOffRequested();
         processAllMessages();
         sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_OFF, null);
         processAllMessages();
@@ -844,6 +848,14 @@
         assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
         assertEquals(SATELLITE_RESULT_NO_RESOURCES, (long) mIIntegerConsumerResults.get(1));
         mSatelliteControllerUT.allRadiosDisabled = true;
+
+        resetSatelliteControllerUTToOnAndProvisionedState();
+        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
+        mSatelliteControllerUT.onCellularRadioPowerOffRequested();
+        processAllMessages();
+        // Satellite should not be powered off since the feature flag oemEnabledSatelliteFlag is
+        // disabled
+        verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
     }
 
     @Test
@@ -1515,54 +1527,37 @@
 
     @Test
     public void testSupportedSatelliteServices() {
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
         List<String> satellitePlmnList = mSatelliteControllerUT.getSatellitePlmnList(SUB_ID);
-        assertEquals(EMPTY_SATELLITE_SERVICES_SUPPORTED_BY_PROVIDERS_STRING_ARRAY.length,
-                satellitePlmnList.size());
+        assertEquals(EMPTY_STRING_ARRAY.length, satellitePlmnList.size());
         List<Integer> supportedSatelliteServices =
                 mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00101");
         assertTrue(supportedSatelliteServices.isEmpty());
 
-        String[] satellitePlmnArray = {"00101", "00102"};
-        String[] satelliteServicesSupportedByProviderStrArray = {"00101:1,2", "00102:2,3"};
-        int[] expectedSupportedServices1 = {1, 2};
-        int[] expectedSupportedServices2 = {2, 3};
-
+        String[] satelliteProviderStrArray = {"00101", "00102"};
         mContextFixture.putStringArrayResource(
-                R.array.config_satellite_services_supported_by_providers,
-                satelliteServicesSupportedByProviderStrArray);
+                R.array.config_satellite_providers, satelliteProviderStrArray);
+        int[] expectedSupportedServices2 = {2};
+        int[] expectedSupportedServices3 = {1, 3};
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00102", expectedSupportedServices2);
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00103", expectedSupportedServices3);
+        String[] expectedSupportedSatellitePlmns = {"00102", "00103"};
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
         TestSatelliteController testSatelliteController =
                 new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
 
         satellitePlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
-        assertTrue(Arrays.equals(satellitePlmnArray, satellitePlmnList.stream().toArray()));
-
+        assertTrue(satellitePlmnList.isEmpty());
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
-        assertNotNull(supportedSatelliteServices);
-        assertTrue(Arrays.equals(expectedSupportedServices1,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+        assertTrue(supportedSatelliteServices.isEmpty());
 
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
-        assertNotNull(supportedSatelliteServices);
-        assertTrue(Arrays.equals(expectedSupportedServices2,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
-
-        // Carrier config changed
-        int[] expectedSupportedServices3 = {2};
-        int[] expectedSupportedServices4 = {1, 3};
-        PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
-        carrierSupportedSatelliteServicesPerProvider.putIntArray(
-                "00102", expectedSupportedServices3);
-        carrierSupportedSatelliteServicesPerProvider.putIntArray(
-                "00103", expectedSupportedServices4);
-        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
-                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
-                carrierSupportedSatelliteServicesPerProvider);
+        // Carrier config changed with carrierEnabledSatelliteFlag disabled
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
                 : mCarrierConfigChangedListenerList) {
             pair.first.execute(() -> pair.second.onCarrierConfigChanged(
@@ -1572,24 +1567,34 @@
         processAllMessages();
 
         supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
-        assertNotNull(supportedSatelliteServices);
-        assertTrue(Arrays.equals(expectedSupportedServices1,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
-
-        supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
-        assertNotNull(supportedSatelliteServices);
-        assertTrue(Arrays.equals(expectedSupportedServices3,
+        assertTrue(supportedSatelliteServices.isEmpty());
+        supportedSatelliteServices =
+                testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
+        assertTrue(supportedSatelliteServices.isEmpty());
+
+        // Trigger carrier config changed with carrierEnabledSatelliteFlag enabled
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        processAllMessages();
+
+        satellitePlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+        assertTrue(Arrays.equals(
+                expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray()));
+        supportedSatelliteServices =
+                mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+        assertTrue(Arrays.equals(expectedSupportedServices2,
                 supportedSatelliteServices.stream()
                         .mapToInt(Integer::intValue)
                         .toArray()));
-
         supportedSatelliteServices =
                 mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00103");
-        assertTrue(Arrays.equals(expectedSupportedServices4,
+        assertTrue(Arrays.equals(expectedSupportedServices3,
                 supportedSatelliteServices.stream()
                         .mapToInt(Integer::intValue)
                         .toArray()));
@@ -1605,9 +1610,8 @@
         }
         processAllMessages();
 
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
-        assertTrue(supportedSatelliteServices.isEmpty());
+        satellitePlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+        assertTrue(satellitePlmnList.isEmpty());
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
         assertTrue(supportedSatelliteServices.isEmpty());
@@ -1615,25 +1619,18 @@
                 testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
         assertTrue(supportedSatelliteServices.isEmpty());
 
-        supportedSatelliteServices =
-                testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00101");
-        assertNotNull(supportedSatelliteServices);
-        assertTrue(Arrays.equals(expectedSupportedServices1,
-                supportedSatelliteServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
 
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00102");
         assertNotNull(supportedSatelliteServices);
-        assertTrue(Arrays.equals(expectedSupportedServices3,
+        assertTrue(Arrays.equals(expectedSupportedServices2,
                 supportedSatelliteServices.stream()
                         .mapToInt(Integer::intValue)
                         .toArray()));
 
         supportedSatelliteServices =
                 testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00103");
-        assertTrue(Arrays.equals(expectedSupportedServices4,
+        assertTrue(Arrays.equals(expectedSupportedServices3,
                 supportedSatelliteServices.stream()
                         .mapToInt(Integer::intValue)
                         .toArray()));
@@ -1643,26 +1640,41 @@
     public void testConfigureSatellitePlmnOnCarrierConfigChanged() {
         logd("testConfigureSatellitePlmnOnCarrierConfigChanged");
 
-        String[] satelliteServicesSupportedByProviderStrArray =
-                {"00101:1,2", "00102:2,3", "00103:1,2", "00104:3,4", "00105:1"};
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
+        String[] satelliteProviderStrArray =
+                {"00101", "00102", "00103", "00104", "00105"};
+        List<String> satellitePlmnListFromOverlayConfig =
+                Arrays.stream(satelliteProviderStrArray).toList();
         mContextFixture.putStringArrayResource(
-                R.array.config_satellite_services_supported_by_providers,
-                satelliteServicesSupportedByProviderStrArray);
+                R.array.config_satellite_providers, satelliteProviderStrArray);
 
         /* Initially, the radio state is ON. In the constructor, satelliteController registers for
          the radio state changed events and immediately gets the radio state changed event as ON. */
         doReturn(false).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+        mCarrierConfigChangedListenerList.clear();
         TestSatelliteController testSatelliteController =
                 new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
         processAllMessages();
-        List<String> satellitePlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
-        verify(mMockSatelliteModemInterface, never())
-                .setSatellitePlmn(anyInt(), eq(satellitePlmnList), any(Message.class));
+        List<String> carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+        verify(mMockSatelliteModemInterface, never()).setSatellitePlmn(
+                anyInt(), anyList(), anyList(), any(Message.class));
+        assertTrue(carrierPlmnList.isEmpty());
         reset(mMockSatelliteModemInterface);
 
         // Test setSatellitePlmn() when Carrier Config change event triggered.
         mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
                 true);
+        int[] supportedServices2 = {2};
+        int[] supportedServices3 = {1, 3};
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00102", supportedServices2);
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                "00103", supportedServices3);
+        List<String> expectedCarrierPlmnList = Arrays.asList("00102", "00103");
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
                 : mCarrierConfigChangedListenerList) {
             pair.first.execute(() -> pair.second.onCarrierConfigChanged(
@@ -1670,14 +1682,64 @@
             );
         }
         processAllMessages();
-        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(), anyList(), any(
-                Message.class));
+        carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+        verify(mMockSatelliteModemInterface, never()).setSatellitePlmn(
+                anyInt(), anyList(), anyList(), any(Message.class));
+        assertTrue(carrierPlmnList.isEmpty());
+        reset(mMockSatelliteModemInterface);
+
+        // Reset TestSatelliteController so that device satellite PLMNs is loaded when
+        // carrierEnabledSatelliteFlag is enabled.
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+        mCarrierConfigChangedListenerList.clear();
+        testSatelliteController =
+                new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+
+        // Trigger carrier config changed with carrierEnabledSatelliteFlag enabled and empty
+        // carrier supported satellite services.
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                new PersistableBundle());
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        processAllMessages();
+
+        carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+        assertTrue(carrierPlmnList.isEmpty());
+        List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+                carrierPlmnList, satellitePlmnListFromOverlayConfig);
+        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+                eq(EMPTY_STRING_LIST), eq(allSatellitePlmnList), any(Message.class));
+        reset(mMockSatelliteModemInterface);
+
+        // Trigger carrier config changed with carrierEnabledSatelliteFlag enabled and non-empty
+        // carrier supported satellite services.
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        processAllMessages();
+        carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+        allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+                carrierPlmnList, satellitePlmnListFromOverlayConfig);
+        assertEquals(expectedCarrierPlmnList, carrierPlmnList);
+        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+                eq(carrierPlmnList), eq(allSatellitePlmnList), any(Message.class));
         reset(mMockSatelliteModemInterface);
 
         /* setSatellitePlmn() is called regardless whether satellite attach for carrier is
            supported. */
         mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
-                true);
+                false);
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
                 : mCarrierConfigChangedListenerList) {
             pair.first.execute(() -> pair.second.onCarrierConfigChanged(
@@ -1685,13 +1747,36 @@
             );
         }
         processAllMessages();
-        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(), anyList(), any(
-                Message.class));
+        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+                eq(carrierPlmnList), eq(allSatellitePlmnList), any(Message.class));
+        reset(mMockSatelliteModemInterface);
+
+        // Test empty config_satellite_providers and empty carrier PLMN list
+        mCarrierConfigChangedListenerList.clear();
+        mContextFixture.putStringArrayResource(
+                R.array.config_satellite_providers, EMPTY_STRING_ARRAY);
+        testSatelliteController =
+                new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                new PersistableBundle());
+        for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+                : mCarrierConfigChangedListenerList) {
+            pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+                    /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+            );
+        }
+        processAllMessages();
+        carrierPlmnList = testSatelliteController.getSatellitePlmnList(SUB_ID);
+        assertTrue(carrierPlmnList.isEmpty());
+        verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
+                eq(EMPTY_STRING_LIST), eq(EMPTY_STRING_LIST), any(Message.class));
         reset(mMockSatelliteModemInterface);
     }
 
     @Test
     public void testSatelliteCommunicationRestriction() {
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
         mCarrierConfigBundle.putBoolean(
                 CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
         for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
@@ -1821,6 +1906,30 @@
         verify(mMockSatelliteModemInterface, times(1))
                 .requestSetSatelliteEnabledForCarrier(anyInt(), eq(true), any(Message.class));
         reset(mMockSatelliteModemInterface);
+
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
+
+        mIIntegerConsumerResults.clear();
+        mSatelliteControllerUT.removeSatelliteAttachRestrictionForCarrier(SUB_ID,
+                SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
+        processAllMessages();
+        assertTrue(waitForIIntegerConsumerResult(1));
+        assertEquals(
+                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, (long) mIIntegerConsumerResults.get(0));
+        verifyZeroInteractions(mMockSatelliteModemInterface);
+
+        mIIntegerConsumerResults.clear();
+        mSatelliteControllerUT.addSatelliteAttachRestrictionForCarrier(SUB_ID,
+                SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER, mIIntegerConsumer);
+        processAllMessages();
+        assertTrue(waitForIIntegerConsumerResult(1));
+        assertEquals(
+                SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, (long) mIIntegerConsumerResults.get(0));
+        verifyZeroInteractions(mMockSatelliteModemInterface);
+
+        Set<Integer> satelliteRestrictionReasons =
+                mSatelliteControllerUT.getSatelliteAttachRestrictionReasonsForCarrier(SUB_ID);
+        assertTrue(satelliteRestrictionReasons.isEmpty());
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
index 78d7627..28874df 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
@@ -17,7 +17,6 @@
 package com.android.internal.telephony.satellite;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
 import android.os.PersistableBundle;
@@ -33,8 +32,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -57,58 +55,6 @@
     }
 
     @Test
-    public void testParseSupportedSatelliteServicesFromStringArray() {
-        // Parse correct format input string
-        int[] expectedServices1 = {2, 3};
-        int[] expectedServices2 = {3};
-        String[] supportedServicesStrArr1 = {"10011:2,3", "10112:3"};
-        Map<String, Set<Integer>> supportedServiceMap =
-                SatelliteServiceUtils.parseSupportedSatelliteServices(supportedServicesStrArr1);
-
-        assertTrue(supportedServiceMap.containsKey("10011"));
-        Set<Integer> supportedServices = supportedServiceMap.get("10011");
-        assertTrue(Arrays.equals(expectedServices1,
-                supportedServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
-
-        assertTrue(supportedServiceMap.containsKey("10112"));
-        supportedServices = supportedServiceMap.get("10112");
-        assertTrue(Arrays.equals(expectedServices2,
-                supportedServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
-
-        // Parse correct mixed with incorrect format input string
-        String[] supportedServicesStrArr2 = {"10011:2,3,1xy", "10112:3,70", "10012:"};
-        supportedServiceMap = SatelliteServiceUtils.parseSupportedSatelliteServices(
-                supportedServicesStrArr2);
-
-        assertTrue(supportedServiceMap.containsKey("10011"));
-        supportedServices = supportedServiceMap.get("10011");
-        assertTrue(Arrays.equals(expectedServices1,
-                supportedServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
-
-        assertTrue(supportedServiceMap.containsKey("10112"));
-        supportedServices = supportedServiceMap.get("10112");
-        assertTrue(Arrays.equals(expectedServices2,
-                supportedServices.stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
-
-        assertTrue(supportedServiceMap.containsKey("10012"));
-        assertTrue(supportedServiceMap.get("10012").isEmpty());
-
-        // Parse an empty input string
-        String[] supportedServicesStrArr3 = {};
-        supportedServiceMap = SatelliteServiceUtils.parseSupportedSatelliteServices(
-                supportedServicesStrArr3);
-        assertTrue(supportedServiceMap.isEmpty());
-    }
-
-    @Test
     public void testParseSupportedSatelliteServicesFromPersistableBundle() {
         PersistableBundle supportedServicesBundle = new PersistableBundle();
         String plmn1 = "10101";
@@ -153,49 +99,11 @@
     }
 
     @Test
-    public void testMergeSupportedSatelliteServices() {
-        String plmn1 = "00101";
-        String plmn2 = "00102";
-        String plmn3 = "00103";
-        String plmn4 = "00104";
-
-        Integer[] providerSupportedServicesForPlmn1 = {1, 2, 3};
-        Integer[] providerSupportedServicesForPlmn2 = {3, 4};
-        Map<String, Set<Integer>> providerSupportedServicesMap = new HashMap<>();
-        providerSupportedServicesMap.put(
-                plmn1, new HashSet<>(Arrays.asList(providerSupportedServicesForPlmn1)));
-        providerSupportedServicesMap.put(
-                plmn2, new HashSet<>(Arrays.asList(providerSupportedServicesForPlmn2)));
-        providerSupportedServicesMap.put(plmn4, new HashSet<>());
-
-        Integer[] carrierSupportedServicesForPlmn2 = {};
-        Integer[] carrierSupportedServicesForPlmn3 = {1, 3, 4};
-        Map<String, Set<Integer>> carrierSupportedServicesMap = new HashMap<>();
-        carrierSupportedServicesMap.put(
-                plmn2, new HashSet<>(Arrays.asList(carrierSupportedServicesForPlmn2)));
-        carrierSupportedServicesMap.put(
-                plmn3, new HashSet<>(Arrays.asList(carrierSupportedServicesForPlmn3)));
-
-        // Come from device config.
-        int[] expectedSupportedServicesForPlmn1 = {1, 2, 3};
-        // Come from carrier config.
-        int[] expectedSupportedServicesForPlmn3 = {1, 3, 4};
-        Map<String, Set<Integer>> supportedServicesMap =
-                SatelliteServiceUtils.mergeSupportedSatelliteServices(
-                        providerSupportedServicesMap, carrierSupportedServicesMap);
-
-        assertEquals(2, supportedServicesMap.size());
-        assertTrue(supportedServicesMap.containsKey(plmn1));
-        assertTrue(supportedServicesMap.containsKey(plmn3));
-        assertFalse(supportedServicesMap.containsKey(plmn2));
-        assertFalse(supportedServicesMap.containsKey(plmn4));
-        assertTrue(Arrays.equals(expectedSupportedServicesForPlmn1,
-                supportedServicesMap.get(plmn1).stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
-        assertTrue(Arrays.equals(expectedSupportedServicesForPlmn3,
-                supportedServicesMap.get(plmn3).stream()
-                        .mapToInt(Integer::intValue)
-                        .toArray()));
+    public void testMergeStrLists() {
+        List<String> l1 = Arrays.asList("1", "2", "2");
+        List<String> l2 = Arrays.asList("1", "3", "3");
+        List<String> expectedMergedList = Arrays.asList("1", "2", "3");
+        List<String> mergedList = SatelliteServiceUtils.mergeStrLists(l1, l2);
+        assertEquals(expectedMergedList, mergedList);
     }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
index 59dfec6..ce77f14 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
@@ -26,8 +26,10 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -49,6 +51,7 @@
 import android.testing.TestableLooper;
 
 import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.subscription.SubscriptionDatabaseManager.SubscriptionDatabaseManagerCallback;
 
 import org.junit.After;
@@ -119,10 +122,14 @@
     static final int FAKE_USER_ID2 = 11;
     static final int FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED = 1;
     static final int FAKE_SATELLITE_ATTACH_FOR_CARRIER_DISABLED = 0;
+    static final int FAKE_SATELLITE_IS_NTN_ENABLED = 1;
+    static final int FAKE_SATELLITE_IS_NTN_DISABLED = 0;
 
     static final String FAKE_MAC_ADDRESS1 = "DC:E5:5B:38:7D:40";
     static final String FAKE_MAC_ADDRESS2 = "DC:B5:4F:47:F3:4C";
 
+    private FeatureFlags mFeatureFlags;
+
     static final SubscriptionInfoInternal FAKE_SUBSCRIPTION_INFO1 =
             new SubscriptionInfoInternal.Builder()
                     .setId(1)
@@ -190,6 +197,7 @@
                     .setSatelliteEnabled(0)
                     .setSatelliteAttachEnabledForCarrier(
                             FAKE_SATELLITE_ATTACH_FOR_CARRIER_DISABLED)
+                    .setNtn(FAKE_SATELLITE_IS_NTN_DISABLED)
                     .setGroupDisabled(false)
                     .build();
 
@@ -260,6 +268,7 @@
                     .setSatelliteEnabled(1)
                     .setSatelliteAttachEnabledForCarrier(
                             FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED)
+                    .setNtn(FAKE_SATELLITE_IS_NTN_ENABLED)
                     .setGroupDisabled(false)
                     .build();
 
@@ -412,14 +421,16 @@
             ((Runnable) invocation.getArguments()[0]).run();
             return null;
         }).when(mSubscriptionDatabaseManagerCallback).invokeFromExecutor(any(Runnable.class));
+        mFeatureFlags = Mockito.mock(FeatureFlags.class);
 
         ((MockContentResolver) mContext.getContentResolver()).addProvider(
                 Telephony.Carriers.CONTENT_URI.getAuthority(), mSubscriptionProvider);
 
         doReturn(1).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID1));
         doReturn(2).when(mUiccController).convertToPublicCardId(eq(FAKE_ICCID2));
+        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
         mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(),
-                mSubscriptionDatabaseManagerCallback);
+                mFeatureFlags, mSubscriptionDatabaseManagerCallback);
         logd("SubscriptionDatabaseManagerTest -Setup!");
     }
 
@@ -524,7 +535,7 @@
         mContextFixture.putBooleanResource(com.android.internal.R.bool
                 .config_subscription_database_async_update, false);
         mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(),
-                mSubscriptionDatabaseManagerCallback);
+                mFeatureFlags, mSubscriptionDatabaseManagerCallback);
 
         assertThat(insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1).getSubscriptionId())
                 .isEqualTo(1);
@@ -1971,6 +1982,80 @@
     }
 
     @Test
+    public void testUpdateSatelliteNtn() throws Exception {
+        // exception is expected if there is nothing in the database.
+        assertThrows(IllegalArgumentException.class,
+                () -> mDatabaseManagerUT.setNtn(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                        FAKE_SATELLITE_IS_NTN_ENABLED));
+
+        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+        mDatabaseManagerUT.setNtn(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                FAKE_SATELLITE_IS_NTN_ENABLED);
+        processAllMessages();
+
+        subInfo = new SubscriptionInfoInternal.Builder(subInfo)
+                .setNtn(FAKE_SATELLITE_IS_NTN_ENABLED)
+                .build();
+        verifySubscription(subInfo);
+        verify(mSubscriptionDatabaseManagerCallback, times(2)).onSubscriptionChanged(eq(1));
+
+        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_IS_NTN)).isEqualTo(FAKE_SATELLITE_IS_NTN_ENABLED);
+
+        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_IS_NTN, FAKE_SATELLITE_IS_NTN_DISABLED);
+        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).getNtn())
+                .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED);
+    }
+
+    @Test
+    public void testUpdateSatelliteNtnWithFeatureDisabled() throws Exception {
+        assertThrows(IllegalArgumentException.class,
+                () -> mDatabaseManagerUT.setSatelliteAttachEnabledForCarrier(
+                        FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                        FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED));
+
+        SubscriptionInfoInternal subInfo = insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
+        mDatabaseManagerUT.setSatelliteAttachEnabledForCarrier(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                FAKE_SATELLITE_IS_NTN_DISABLED);
+        processAllMessages();
+
+        when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
+        reset(mSubscriptionDatabaseManagerCallback);
+        subInfo = new SubscriptionInfoInternal.Builder(subInfo)
+                .setNtn(FAKE_SATELLITE_IS_NTN_ENABLED)
+                .build();
+
+        int subId = subInfo.getSubscriptionId();
+        // Verify the cache value is not same as the inserted one.
+        assertWithMessage("Subscription info cache value is not different.")
+                .that(mDatabaseManagerUT.getSubscriptionInfoInternal(subId)).isNotEqualTo(subInfo);
+
+        // Load subscription info from the database.
+        mDatabaseManagerUT.reloadDatabaseSync();
+        processAllMessages();
+
+        // Verify the database value is not same as the inserted one.
+        assertWithMessage("Subscription info database value is not different.")
+                .that(mDatabaseManagerUT.getSubscriptionInfoInternal(subId)).isNotEqualTo(subInfo);
+
+        verify(mSubscriptionDatabaseManagerCallback, never()).onSubscriptionChanged(eq(1));
+
+        assertThat(mDatabaseManagerUT.getSubscriptionProperty(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_IS_NTN)).isNotEqualTo(FAKE_SATELLITE_IS_NTN_ENABLED);
+
+        mDatabaseManagerUT.setSubscriptionProperty(FAKE_SUBSCRIPTION_INFO1.getSubscriptionId(),
+                SimInfo.COLUMN_IS_NTN, FAKE_SATELLITE_IS_NTN_ENABLED);
+        assertThat(mDatabaseManagerUT.getSubscriptionInfoInternal(
+                FAKE_SUBSCRIPTION_INFO1.getSubscriptionId()).getNtn())
+                .isNotEqualTo(FAKE_SATELLITE_IS_NTN_ENABLED);
+    }
+
+    @Test
     public void testUpdateSubscriptionsInGroup() throws Exception {
         insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO1);
         insertSubscriptionAndVerify(FAKE_SUBSCRIPTION_INFO2);
@@ -2074,7 +2159,8 @@
                     }
                 };
         assertThat(callback.getExecutor()).isEqualTo(executor);
-        mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(), callback);
+        mDatabaseManagerUT = new SubscriptionDatabaseManager(mContext, Looper.myLooper(),
+                mFeatureFlags, callback);
         processAllMessages();
 
         assertThat(latch.getCount()).isEqualTo(1);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
index d1e3bb5..94bcca7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -104,7 +104,9 @@
                     .setSatelliteAttachEnabledForCarrier(
                             SubscriptionDatabaseManagerTest
                                     .FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED)
+                    .setNtn(SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_ENABLED)
                     .setGroupDisabled(false)
+                    .setNtn(1)
                     .build();
 
     private final SubscriptionInfoInternal mSubInfoNull =
@@ -217,7 +219,10 @@
         assertThat(mSubInfo.getSatelliteAttachEnabledForCarrier())
                 .isEqualTo(SubscriptionDatabaseManagerTest
                         .FAKE_SATELLITE_ATTACH_FOR_CARRIER_ENABLED);
+        assertThat(mSubInfo.getNtn()).isEqualTo(
+                SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_ENABLED);
         assertThat(mSubInfo.isGroupDisabled()).isFalse();
+        assertThat(mSubInfo.getNtn()).isEqualTo(1);
     }
 
     @Test
@@ -280,6 +285,7 @@
         assertThat(subInfo.getPortIndex()).isEqualTo(
                 SubscriptionManager.USAGE_SETTING_DEFAULT);
         assertThat(subInfo.isGroupDisabled()).isFalse();
+        assertThat(subInfo.isNtn()).isTrue();
     }
 
     @Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index ab531a6..05489dc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -1113,8 +1113,6 @@
 
     @Test
     public void testIsSubscriptionAssociatedWithUser() {
-        insertSubscription(FAKE_SUBSCRIPTION_INFO1);
-
         // Should fail without MANAGE_SUBSCRIPTION_USER_ASSOCIATION
         assertThrows(SecurityException.class, () -> mSubscriptionManagerServiceUT
                 .isSubscriptionAssociatedWithUser(1, FAKE_USER_HANDLE));
@@ -1125,6 +1123,12 @@
                 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
         mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
 
+        // Should fail for non-existent sub Id
+        assertThrows(IllegalArgumentException.class, () -> mSubscriptionManagerServiceUT
+                .isSubscriptionAssociatedWithUser(1, FAKE_USER_HANDLE));
+
+        insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+
         mSubscriptionManagerServiceUT.setSubscriptionUserHandle(FAKE_USER_HANDLE, 1);
         processAllMessages();
         verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1));