Merge "Update HAL APIs interface to support sim type switching on 2pSIM+1eSIM configured devices" into main
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index edb4ce2..8561dac 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -118,3 +118,11 @@
     description: "This flag controls to get a group id level2."
     bug:"381171540"
 }
+
+# OWNER=jinjeong TARGET=25Q2
+flag {
+    name: "action_sim_preference_settings"
+    namespace: "telephony"
+    description: "This flag controls to launch sim preference page in Setting"
+    bug:"381319469"
+}
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index ee7447c..1b19c99 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -2952,4 +2952,39 @@
      * @param h Handler to be removed from the registrant list.
      */
     default void unregisterForSecurityAlgorithmUpdates(Handler h) {}
+
+    /**
+     * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
+     *                        supported by user subscription.
+     * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
+     *                             PLMNs that are not supported by the carrier and make sure not to
+     *                             attach to them.
+     * @param result Callback message to receive the result.
+     */
+    default void setSatellitePlmn(int simSlot,
+            @NonNull List<String> carrierPlmnList, @NonNull List<String> allSatellitePlmnList,
+            Message result) {}
+
+    /**
+     * Enable or disable satellite in the cellular modem associated with a carrier.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+     * @param result Callback message to receive the result.
+     */
+    default void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+            Message result) {}
+
+    /**
+     * Check whether satellite is enabled in the cellular modem associated with a carrier.
+     *
+     * @param simSlot Indicates the SIM slot to which this API will be applied.
+     * @param result Callback message to receive the result.
+     */
+    default void isSatelliteEnabledForCarrier(int simSlot, Message result) {}
 }
diff --git a/src/java/com/android/internal/telephony/DisplayInfoController.java b/src/java/com/android/internal/telephony/DisplayInfoController.java
index d3f0264..bb19a31 100644
--- a/src/java/com/android/internal/telephony/DisplayInfoController.java
+++ b/src/java/com/android/internal/telephony/DisplayInfoController.java
@@ -110,7 +110,7 @@
         mTelephonyDisplayInfo = new TelephonyDisplayInfo(
                 TelephonyManager.NETWORK_TYPE_UNKNOWN,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
-                false);
+                false, false, false);
         mNetworkTypeController = new NetworkTypeController(phone, this, featureFlags);
         // EVENT_UPDATE will transition from DefaultState to the current state
         // and update the TelephonyDisplayInfo based on the current state.
@@ -132,7 +132,9 @@
         TelephonyDisplayInfo newDisplayInfo = new TelephonyDisplayInfo(
                 mNetworkTypeController.getDataNetworkType(),
                 mNetworkTypeController.getOverrideNetworkType(),
-                isRoaming());
+                isRoaming(),
+                mPhone.getServiceStateTracker().getServiceState().isUsingNonTerrestrialNetwork(),
+                mNetworkTypeController.getSatelliteConstrainedData());
         if (!newDisplayInfo.equals(mTelephonyDisplayInfo)) {
             logl("TelephonyDisplayInfo changed from " + mTelephonyDisplayInfo + " to "
                     + newDisplayInfo);
diff --git a/src/java/com/android/internal/telephony/NetworkResponse.java b/src/java/com/android/internal/telephony/NetworkResponse.java
index b4a37b3..ccf066f 100644
--- a/src/java/com/android/internal/telephony/NetworkResponse.java
+++ b/src/java/com/android/internal/telephony/NetworkResponse.java
@@ -551,6 +551,36 @@
         }
     }
 
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error
+     */
+    public void setSatellitePlmnResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_NETWORK, mRil, responseInfo);
+    }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error
+     */
+    public void setSatelliteEnabledForCarrierResponse(RadioResponseInfo responseInfo) {
+        RadioResponse.responseVoid(HAL_SERVICE_NETWORK, mRil, responseInfo);
+    }
+
+    /**
+     * @param responseInfo Response info struct containing response type, serial no. and error.
+     * @param isEnabled Indicates whether satellite is enabled for carrier or not.
+     */
+    public void isSatelliteEnabledForCarrierResponse(RadioResponseInfo responseInfo,
+            boolean isEnabled) {
+        RILRequest rr = mRil.processResponse(HAL_SERVICE_NETWORK, responseInfo);
+
+        if (rr != null) {
+            if (responseInfo.error == RadioError.NONE) {
+                RadioResponse.sendMessageResponse(rr.mResult, isEnabled);
+            }
+            mRil.processResponseDone(rr, responseInfo, isEnabled);
+        }
+    }
+
     @Override
     public String getInterfaceHash() {
         return IRadioNetworkResponse.HASH;
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index 081a5c8..b12a3df 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -22,7 +22,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
 import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Message;
 import android.os.PersistableBundle;
 import android.os.PowerManager;
@@ -233,6 +239,72 @@
     private boolean mDoesPccListIndicateIdle = false;
 
     private boolean mInVoiceCall = false;
+    private boolean mIsSatelliteConstrainedData = false;
+    private boolean mIsSatelliteNetworkCallbackRegistered = false;
+    private ConnectivityManager mConnectivityManager;
+
+    private final ConnectivityManager.NetworkCallback mNetworkCallback =
+            new ConnectivityManager.NetworkCallback() {
+                @Override
+                public void onAvailable(Network network) {
+                    log("On Available: " + network);
+                    if (network != null) {
+                        if (mConnectivityManager != null) {
+                            NetworkCapabilities capabilities =
+                                    mConnectivityManager.getNetworkCapabilities(network);
+                            updateBandwidthConstrainedStatus(capabilities);
+                        } else {
+                            log("network is null");
+                        }
+                    }
+                }
+
+                @Override
+                public void onCapabilitiesChanged(Network network,
+                        NetworkCapabilities networkCapabilities) {
+                    log("onCapabilitiesChanged: " + network);
+                    if (network != null) {
+                        updateBandwidthConstrainedStatus(networkCapabilities);
+                    } else {
+                        log("network is null");
+                    }
+                }
+
+                @Override
+                public void onLost(Network network) {
+                    log("Network Lost");
+                    if (mIsSatelliteConstrainedData) {
+                        mIsSatelliteConstrainedData = false;
+                        mDisplayInfoController.updateTelephonyDisplayInfo();
+                    }
+                }
+            };
+
+    private boolean isBandwidthConstrainedCapabilitySupported(NetworkCapabilities
+            capabilities) {
+        // TODO (b/382002908: Remove try catch exception for
+        //  NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED & replace datautils with
+        //  NetworkCapabilities on api availability at mainline module)
+        try {
+            return capabilities.hasTransport(
+                    NetworkCapabilities.TRANSPORT_SATELLITE) &&
+                    !capabilities.hasCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+        } catch (Exception ignored) {
+            log("NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED not supported ");
+            return false;
+        }
+    }
+
+    private void updateBandwidthConstrainedStatus(NetworkCapabilities capabilities) {
+        if (capabilities != null) {
+            mIsSatelliteConstrainedData
+                    = isBandwidthConstrainedCapabilitySupported(capabilities);
+            log("satellite constrained data status : " + mIsSatelliteConstrainedData);
+            mDisplayInfoController.updateTelephonyDisplayInfo();
+        } else {
+            log("capabilities is null");
+        }
+    }
 
     /**
      * NetworkTypeController constructor.
@@ -266,9 +338,42 @@
         mServiceState = mPhone.getServiceStateTracker().getServiceState();
         mPhysicalChannelConfigs = mPhone.getServiceStateTracker().getPhysicalChannelConfigList();
 
+        if(mFeatureFlags.carrierEnabledSatelliteFlag()) {
+            registerForSatelliteNetwork();
+        }
+
         sendMessage(EVENT_INITIALIZE);
     }
 
+    public synchronized void registerForSatelliteNetwork() {
+        if (!mIsSatelliteNetworkCallbackRegistered) {
+            mIsSatelliteNetworkCallbackRegistered = true;
+            HandlerThread handlerThread = new HandlerThread("SatelliteDataUsageThread");
+            handlerThread.start();
+            Handler handler = new Handler(handlerThread.getLooper());
+
+            NetworkRequest.Builder builder = new NetworkRequest.Builder();
+            builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+            // TODO (b/382002908: Remove try catch exception for
+            //  NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED & replace datautils with
+            //  NetworkCapabilities on api availability at mainline module)
+            try {
+                builder.removeCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+            } catch (Exception ignored) {
+                log("NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED not supported ");
+            }
+            mConnectivityManager =
+                    (ConnectivityManager) mPhone.getContext()
+                            .getSystemService(Context.CONNECTIVITY_SERVICE);
+            if (mConnectivityManager != null) {
+                mConnectivityManager.registerBestMatchingNetworkCallback(
+                        builder.build(), mNetworkCallback, handler);
+            } else {
+                loge("network callback not registered");
+            }
+        }
+    }
+
     /**
      * @return The current override network type, used to create TelephonyDisplayInfo in
      * DisplayInfoController.
@@ -289,6 +394,15 @@
     }
 
     /**
+     * @return satellite bandwidth constrained connection status, used to create
+     * TelephonyDisplayInfo in DisplayInfoController.
+     *
+     */
+    public boolean getSatelliteConstrainedData() {
+       return mIsSatelliteConstrainedData;
+    }
+
+    /**
      * @return {@code true} if either the primary or secondary 5G icon timers are active,
      * and {@code false} if neither are.
      */
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 34ac832..1bb9984 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -181,6 +181,9 @@
     /** @hide */
     public static final HalVersion RADIO_HAL_VERSION_2_3 = new HalVersion(2, 3);
 
+    /** @hide */
+    public static final HalVersion RADIO_HAL_VERSION_2_4 = new HalVersion(2, 4);
+
     // Hal version
     private final Map<Integer, HalVersion> mHalVersion = new HashMap<>();
 
@@ -5352,6 +5355,102 @@
             });
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSatellitePlmn(int simSlot, @NonNull List<String> carrierPlmnList,
+            @NonNull List<String> allSatellitePlmnList, Message result) {
+        RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+        if (!canMakeRequest(
+                "setSatellitePlmn",
+                networkProxy,
+                result,
+                RADIO_HAL_VERSION_2_4)) {
+            return;
+        }
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_PLMN, result,
+                mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+                    + " simSlot=" + simSlot + " carrierPlmnList=" + carrierPlmnList
+                    + " allSatellitePlmnList=" + allSatellitePlmnList);
+        }
+
+        radioServiceInvokeHelper(
+                HAL_SERVICE_NETWORK,
+                rr,
+                "setSatellitePlmn",
+                () -> {
+                    networkProxy.setSatellitePlmn(rr.mSerial, simSlot, carrierPlmnList,
+                            allSatellitePlmnList);
+                });
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setSatelliteEnabledForCarrier(int simSlot, boolean satelliteEnabled,
+            Message result) {
+        RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+        if (!canMakeRequest(
+                "setSatelliteEnabledForCarrier",
+                networkProxy,
+                result,
+                RADIO_HAL_VERSION_2_4)) {
+            return;
+        }
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER, result,
+                mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+                    + " simSlot=" + simSlot + " satelliteEnabled=" + satelliteEnabled);
+        }
+
+        radioServiceInvokeHelper(
+                HAL_SERVICE_NETWORK,
+                rr,
+                "setSatelliteEnabledForCarrier",
+                () -> {
+                    networkProxy.setSatelliteEnabledForCarrier(rr.mSerial, simSlot,
+                            satelliteEnabled);
+                });
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void isSatelliteEnabledForCarrier(int simSlot, Message result) {
+        RadioNetworkProxy networkProxy = getRadioServiceProxy(RadioNetworkProxy.class);
+        if (!canMakeRequest(
+                "isSatelliteEnabledForCarrier",
+                networkProxy,
+                result,
+                RADIO_HAL_VERSION_2_4)) {
+            return;
+        }
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER, result,
+                mRILDefaultWorkSource);
+
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+                    + " simSlot=" + simSlot);
+        }
+
+        radioServiceInvokeHelper(
+                HAL_SERVICE_NETWORK, rr, "isSatelliteEnabledForCarrier", () -> {
+                    networkProxy.isSatelliteEnabledForCarrier(rr.mSerial, simSlot);
+                });
+    }
+
+
     //***** Private Methods
     /**
      * This is a helper function to be called when an indication callback is called for any radio
@@ -6216,6 +6315,7 @@
             case 2: return RADIO_HAL_VERSION_2_1;
             case 3: return RADIO_HAL_VERSION_2_2;
             case 4: return RADIO_HAL_VERSION_2_3;
+            case 5: return RADIO_HAL_VERSION_2_4;
             default: return RADIO_HAL_VERSION_UNKNOWN;
         }
     }
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index ccfaa35..8f0060b 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -121,6 +121,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_N1_MODE_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_NULL_CIPHER_AND_INTEGRITY_ENABLED;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_SECURITY_ALGORITHMS_UPDATED_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_IS_VONR_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_LAST_CALL_FAIL_CAUSE;
@@ -180,6 +181,8 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_DATA_MODEM;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_RADIO_CAPABILITY;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER;
+import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SATELLITE_PLMN;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_SIM_CARD_POWER;
@@ -5289,6 +5292,12 @@
                 return "IS_SECURITY_ALGORITHMS_UPDATED_ENABLED";
             case RIL_REQUEST_GET_SIMULTANEOUS_CALLING_SUPPORT:
                 return "GET_SIMULTANEOUS_CALLING_SUPPORT";
+            case RIL_REQUEST_SET_SATELLITE_PLMN:
+                return "SET_SATELLITE_PLMN";
+            case RIL_REQUEST_SET_SATELLITE_ENABLED_FOR_CARRIER:
+                return "SET_SATELLITE_ENABLED_FOR_CARRIER";
+            case RIL_REQUEST_IS_SATELLITE_ENABLED_FOR_CARRIER:
+                return "IS_SATELLITE_ENABLED_FOR_CARRIER";
             default:
                 return "<unknown request " + request + ">";
         }
diff --git a/src/java/com/android/internal/telephony/RadioNetworkProxy.java b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
index 4acc71a..12e6c90 100644
--- a/src/java/com/android/internal/telephony/RadioNetworkProxy.java
+++ b/src/java/com/android/internal/telephony/RadioNetworkProxy.java
@@ -979,4 +979,60 @@
         }
         // Only supported on AIDL.
     }
+
+   /**
+     * Set the non-terrestrial PLMN with lower priority than terrestrial networks.
+     *
+     * @param serial Serial number of request.
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param carrierPlmnList The list of roaming PLMN used for connecting to satellite networks
+     *                        supported by user subscription.
+     * @param allSatellitePlmnList Modem should use the allSatellitePlmnList to identify satellite
+     *                             PLMNs that are not supported by the carrier and make sure not to
+     *                             attach to them.
+     */
+    public void setSatellitePlmn(int serial, int simSlot, List<String> carrierPlmnList,
+            List<String> allSatellitePlmnList) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            String[] carrierPlmnArray = carrierPlmnList.toArray(new String[0]);
+            String[] allSatellitePlmnArray = allSatellitePlmnList.toArray(new String[0]);
+            mNetworkProxy.setSatellitePlmn(serial, simSlot, carrierPlmnArray,
+                    allSatellitePlmnArray);
+        }
+        // Only supported on AIDL.
+    }
+
+    /**
+     * Enable or disable satellite in the cellular modem associated with a carrier.
+     *
+     * @param serial Serial number of request.
+     * @param simSlot Indicates the SIM slot to which this API will be applied. The modem will use
+     *                this information to determine the relevant carrier.
+     * @param satelliteEnabled {@code true} to enable satellite, {@code false} to disable satellite.
+     */
+    public void setSatelliteEnabledForCarrier(int serial, int simSlot,
+            boolean satelliteEnabled) throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mNetworkProxy.setSatelliteEnabledForCarrier(serial, simSlot, satelliteEnabled);
+        }
+        // Only supported on AIDL.
+    }
+
+    /**
+     * Check whether satellite is enabled in the cellular modem associated with a carrier.
+     *
+     * @param serial Serial number of request.
+     * @param simSlot Indicates the SIM slot to which this API will be applied.
+     */
+    public void isSatelliteEnabledForCarrier(int serial, int simSlot)
+            throws RemoteException {
+        if (isEmpty()) return;
+        if (isAidl()) {
+            mNetworkProxy.isSatelliteEnabledForCarrier(serial, simSlot);
+        }
+        // Only supported on AIDL.
+    }
 }
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index 9f74890..fdd0c0a 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -177,7 +177,6 @@
 
     /** Maximum number of Satellite relevant stats to store between pulls. */
     private final int mMaxNumSatelliteStats;
-    private final int mMaxNumSatelliteControllerStats = 1;
     private final int mMaxNumCarrierRoamingSatelliteSessionStats = 1;
 
     /** Maximum number of data network validation to store during pulls. */
@@ -710,76 +709,75 @@
 
     /** Adds a new {@link SatelliteController} to the storage. */
     public synchronized void addSatelliteControllerStats(SatelliteController stats) {
-        // SatelliteController is a single data point
-        SatelliteController[] atomArray = mAtoms.satelliteController;
-        if (atomArray == null || atomArray.length == 0) {
-            atomArray = new SatelliteController[] {new SatelliteController()};
+        // find existing satellite controller atom with same carrier ID.
+        SatelliteController existingStats = find(stats);
+        if (existingStats != null) {
+            existingStats.countOfSatelliteServiceEnablementsSuccess
+                    += stats.countOfSatelliteServiceEnablementsSuccess;
+            existingStats.countOfSatelliteServiceEnablementsFail
+                    += stats.countOfSatelliteServiceEnablementsFail;
+            existingStats.countOfOutgoingDatagramSuccess
+                    += stats.countOfOutgoingDatagramSuccess;
+            existingStats.countOfOutgoingDatagramFail
+                    += stats.countOfOutgoingDatagramFail;
+            existingStats.countOfIncomingDatagramSuccess
+                    += stats.countOfIncomingDatagramSuccess;
+            existingStats.countOfIncomingDatagramFail
+                    += stats.countOfIncomingDatagramFail;
+            existingStats.countOfDatagramTypeSosSmsSuccess
+                    += stats.countOfDatagramTypeSosSmsSuccess;
+            existingStats.countOfDatagramTypeSosSmsFail
+                    += stats.countOfDatagramTypeSosSmsFail;
+            existingStats.countOfDatagramTypeLocationSharingSuccess
+                    += stats.countOfDatagramTypeLocationSharingSuccess;
+            existingStats.countOfDatagramTypeLocationSharingFail
+                    += stats.countOfDatagramTypeLocationSharingFail;
+            existingStats.countOfProvisionSuccess
+                    += stats.countOfProvisionSuccess;
+            existingStats.countOfProvisionFail
+                    += stats.countOfProvisionFail;
+            existingStats.countOfDeprovisionSuccess
+                    += stats.countOfDeprovisionSuccess;
+            existingStats.countOfDeprovisionFail
+                    += stats.countOfDeprovisionFail;
+            existingStats.totalServiceUptimeSec
+                    += stats.totalServiceUptimeSec;
+            existingStats.totalBatteryConsumptionPercent
+                    += stats.totalBatteryConsumptionPercent;
+            existingStats.totalBatteryChargedTimeSec
+                    += stats.totalBatteryChargedTimeSec;
+            existingStats.countOfDemoModeSatelliteServiceEnablementsSuccess
+                    += stats.countOfDemoModeSatelliteServiceEnablementsSuccess;
+            existingStats.countOfDemoModeSatelliteServiceEnablementsFail
+                    += stats.countOfDemoModeSatelliteServiceEnablementsFail;
+            existingStats.countOfDemoModeOutgoingDatagramSuccess
+                    += stats.countOfDemoModeOutgoingDatagramSuccess;
+            existingStats.countOfDemoModeOutgoingDatagramFail
+                    += stats.countOfDemoModeOutgoingDatagramFail;
+            existingStats.countOfDemoModeIncomingDatagramSuccess
+                    += stats.countOfDemoModeIncomingDatagramSuccess;
+            existingStats.countOfDemoModeIncomingDatagramFail
+                    += stats.countOfDemoModeIncomingDatagramFail;
+            existingStats.countOfDatagramTypeKeepAliveSuccess
+                    += stats.countOfDatagramTypeKeepAliveSuccess;
+            existingStats.countOfDatagramTypeKeepAliveFail
+                    += stats.countOfDatagramTypeKeepAliveFail;
+            existingStats.countOfAllowedSatelliteAccess += stats.countOfAllowedSatelliteAccess;
+            existingStats.countOfDisallowedSatelliteAccess
+                    += stats.countOfDisallowedSatelliteAccess;
+            existingStats.countOfSatelliteAccessCheckFail += stats.countOfSatelliteAccessCheckFail;
+
+            existingStats.isProvisioned = stats.isProvisioned;
+
+            existingStats.countOfSatelliteAllowedStateChangedEvents
+                    += stats.countOfSatelliteAllowedStateChangedEvents;
+            existingStats.countOfSuccessfulLocationQueries +=
+                    stats.countOfSuccessfulLocationQueries;
+            existingStats.countOfFailedLocationQueries += stats.countOfFailedLocationQueries;
+        } else {
+            mAtoms.satelliteController = insertAtRandomPlace(mAtoms.satelliteController, stats,
+                    mMaxNumSatelliteStats);
         }
-
-        SatelliteController atom = atomArray[0];
-        atom.countOfSatelliteServiceEnablementsSuccess
-                += stats.countOfSatelliteServiceEnablementsSuccess;
-        atom.countOfSatelliteServiceEnablementsFail
-                += stats.countOfSatelliteServiceEnablementsFail;
-        atom.countOfOutgoingDatagramSuccess
-                += stats.countOfOutgoingDatagramSuccess;
-        atom.countOfOutgoingDatagramFail
-                += stats.countOfOutgoingDatagramFail;
-        atom.countOfIncomingDatagramSuccess
-                += stats.countOfIncomingDatagramSuccess;
-        atom.countOfIncomingDatagramFail
-                += stats.countOfIncomingDatagramFail;
-        atom.countOfDatagramTypeSosSmsSuccess
-                += stats.countOfDatagramTypeSosSmsSuccess;
-        atom.countOfDatagramTypeSosSmsFail
-                += stats.countOfDatagramTypeSosSmsFail;
-        atom.countOfDatagramTypeLocationSharingSuccess
-                += stats.countOfDatagramTypeLocationSharingSuccess;
-        atom.countOfDatagramTypeLocationSharingFail
-                += stats.countOfDatagramTypeLocationSharingFail;
-        atom.countOfProvisionSuccess
-                += stats.countOfProvisionSuccess;
-        atom.countOfProvisionFail
-                += stats.countOfProvisionFail;
-        atom.countOfDeprovisionSuccess
-                += stats.countOfDeprovisionSuccess;
-        atom.countOfDeprovisionFail
-                += stats.countOfDeprovisionFail;
-        atom.totalServiceUptimeSec
-                += stats.totalServiceUptimeSec;
-        atom.totalBatteryConsumptionPercent
-                += stats.totalBatteryConsumptionPercent;
-        atom.totalBatteryChargedTimeSec
-                += stats.totalBatteryChargedTimeSec;
-        atom.countOfDemoModeSatelliteServiceEnablementsSuccess
-                += stats.countOfDemoModeSatelliteServiceEnablementsSuccess;
-        atom.countOfDemoModeSatelliteServiceEnablementsFail
-                += stats.countOfDemoModeSatelliteServiceEnablementsFail;
-        atom.countOfDemoModeOutgoingDatagramSuccess
-                += stats.countOfDemoModeOutgoingDatagramSuccess;
-        atom.countOfDemoModeOutgoingDatagramFail
-                += stats.countOfDemoModeOutgoingDatagramFail;
-        atom.countOfDemoModeIncomingDatagramSuccess
-                += stats.countOfDemoModeIncomingDatagramSuccess;
-        atom.countOfDemoModeIncomingDatagramFail
-                += stats.countOfDemoModeIncomingDatagramFail;
-        atom.countOfDatagramTypeKeepAliveSuccess
-                += stats.countOfDatagramTypeKeepAliveSuccess;
-        atom.countOfDatagramTypeKeepAliveFail
-                += stats.countOfDatagramTypeKeepAliveFail;
-        atom.countOfAllowedSatelliteAccess += stats.countOfAllowedSatelliteAccess;
-        atom.countOfDisallowedSatelliteAccess += stats.countOfDisallowedSatelliteAccess;
-        atom.countOfSatelliteAccessCheckFail += stats.countOfSatelliteAccessCheckFail;
-
-        atom.isProvisioned = stats.isProvisioned;
-        atom.carrierId = stats.carrierId;
-
-        atom.countOfSatelliteAllowedStateChangedEvents
-                += stats.countOfSatelliteAllowedStateChangedEvents;
-        atom.countOfSuccessfulLocationQueries += stats.countOfSuccessfulLocationQueries;
-        atom.countOfFailedLocationQueries += stats.countOfFailedLocationQueries;
-
-        mAtoms.satelliteController = atomArray;
         saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
     }
 
@@ -1825,7 +1823,7 @@
             atoms.outgoingShortCodeSms = sanitizeAtoms(atoms.outgoingShortCodeSms,
                     OutgoingShortCodeSms.class, mMaxOutgoingShortCodeSms);
             atoms.satelliteController = sanitizeAtoms(atoms.satelliteController,
-                            SatelliteController.class, mMaxNumSatelliteControllerStats);
+                            SatelliteController.class, mMaxNumSatelliteStats);
             atoms.satelliteSession = sanitizeAtoms(atoms.satelliteSession,
                     SatelliteSession.class, mMaxNumSatelliteStats);
             atoms.satelliteIncomingDatagram = sanitizeAtoms(atoms.satelliteIncomingDatagram,
@@ -1848,7 +1846,7 @@
                     mMaxNumSatelliteStats);
             atoms.carrierRoamingSatelliteControllerStats = sanitizeAtoms(
                     atoms.carrierRoamingSatelliteControllerStats,
-                    CarrierRoamingSatelliteControllerStats.class, mMaxNumSatelliteControllerStats);
+                    CarrierRoamingSatelliteControllerStats.class, mMaxNumSatelliteStats);
             atoms.satelliteEntitlement = sanitizeAtoms(atoms.satelliteEntitlement,
                     SatelliteEntitlement.class, mMaxNumSatelliteStats);
             atoms.satelliteConfigUpdater = sanitizeAtoms(atoms.satelliteConfigUpdater,
@@ -2390,6 +2388,19 @@
     }
 
     /**
+     * Returns SatelliteController atom that has same carrier_id value or
+     * {@code null} if does not exist.
+     */
+    private @Nullable SatelliteController find(SatelliteController key) {
+        for (SatelliteController stats : mAtoms.satelliteController) {
+            if (stats.carrierId == key.carrierId) {
+                return stats;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Returns CarrierRoamingSatelliteControllerStats atom that has same carrier_id value or
      * {@code null} if does not exist.
      */
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index a921b89..75771d0 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -376,6 +376,10 @@
                         });
                     }
 
+                    // Send the captured data about incoming datagram to metric
+                    sInstance.reportMetrics(satelliteDatagram,
+                            SatelliteManager.SATELLITE_RESULT_SUCCESS);
+
                     if (pendingCount <= 0) {
                         sInstance.mDatagramController.updateReceiveStatus(mSubId,
                                 SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
@@ -393,10 +397,6 @@
                                 internalCallback::accept);
                         sInstance.pollPendingSatelliteDatagramsInternal(mSubId, callback);
                     }
-
-                    // Send the captured data about incoming datagram to metric
-                    sInstance.reportMetrics(satelliteDatagram,
-                            SatelliteManager.SATELLITE_RESULT_SUCCESS);
                     break;
                 }
 
@@ -748,8 +748,8 @@
                         (int) (Math.round((double) sizeBytes / ROUNDING_UNIT) * ROUNDING_UNIT);
             }
             datagramTransferTime = (System.currentTimeMillis() - mDatagramTransferStartTime);
-            mDatagramTransferStartTime = 0;
         }
+        mDatagramTransferStartTime = 0;
 
         SatelliteStats.getInstance().onSatelliteIncomingDatagramMetrics(
                 new SatelliteStats.SatelliteIncomingDatagramParams.Builder()
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index c6383a6..c1f03bb 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -33,6 +33,8 @@
 import static android.telephony.CarrierConfigManager.KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_DISPLAY_NAME_STRING;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
@@ -41,7 +43,7 @@
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
-import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE;
+import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY;
 import static android.telephony.SubscriptionManager.SATELLITE_ATTACH_ENABLED_FOR_CARRIER;
 import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
@@ -580,6 +582,18 @@
     /** Key Subscription ID, value : map to plmn info with related data plan. */
     @GuardedBy("mSupportedSatelliteServicesLock")
     SparseArray<Map<String, Integer>> mEntitlementDataPlanMapPerCarrier = new SparseArray<>();
+    /** Key Subscription ID, value : map to plmn info with related service type. */
+    @GuardedBy("mSupportedSatelliteServicesLock")
+    SparseArray<Map<String, List<Integer>>> mEntitlementServiceTypeMapPerCarrier =
+            new SparseArray<>();
+    /** Key Subscription ID, value : map to plmn info with related service policy for data service */
+    @GuardedBy("mSupportedSatelliteServicesLock")
+    SparseArray<Map<String, Integer>> mEntitlementDataServicePolicyMapPerCarrier =
+            new SparseArray<>();
+    /** Key Subscription ID, value : map to plmn info with related service policy for voice service */
+    @GuardedBy("mSupportedSatelliteServicesLock")
+    SparseArray<Map<String, Integer>> mEntitlementVoiceServicePolicyMapPerCarrier =
+            new SparseArray<>();
     private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0);
     // key : subscriberId, value : provisioned or not.
     @GuardedBy("mSatelliteTokenProvisionedLock")
@@ -3821,6 +3835,14 @@
             return new ArrayList<>();
         }
         synchronized (mSupportedSatelliteServicesLock) {
+            Map<String, List<Integer>> allowedServicesList
+                    = mEntitlementServiceTypeMapPerCarrier.get(subId);
+            if (allowedServicesList != null && allowedServicesList.containsKey(plmn)) {
+                List<Integer> allowedServiceValues = allowedServicesList.get(plmn);
+                if (allowedServiceValues != null && !allowedServiceValues.isEmpty()) {
+                    return allowedServiceValues;
+                }
+            }
             if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
                 Map<String, Set<Integer>> supportedServices =
                         mSatelliteServicesSupportedByCarriers.get(subId);
@@ -4205,11 +4227,18 @@
      * @param entitlementEnabled {@code true} Satellite service enabled
      * @param allowedPlmnList    plmn allowed list to use the satellite service
      * @param barredPlmnList    plmn barred list to pass the modem
+     * @param plmnDataPlanMap   data plan map for the plmn
+     * @param plmnServiceTypeMap available services map for the plmn
+     * @param plmnDataServicePolicyMap data service policy map for the plmn
+     * @param plmnVoiceServicePolicyMap voice service policy map for the plmn
      * @param callback           callback for accept
      */
     public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled,
             @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList,
             @Nullable Map<String,Integer> plmnDataPlanMap,
+            @Nullable Map<String,List<Integer>> plmnServiceTypeMap,
+            @Nullable Map<String,Integer> plmnDataServicePolicyMap,
+            @Nullable Map<String,Integer> plmnVoiceServicePolicyMap,
             @Nullable IIntegerConsumer callback) {
         if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
             logd("onSatelliteEntitlementStatusUpdated: carrierEnabledSatelliteFlag is not enabled");
@@ -4233,10 +4262,23 @@
         if (plmnDataPlanMap == null) {
             plmnDataPlanMap = new HashMap<>();
         }
+        if (plmnServiceTypeMap == null) {
+            plmnServiceTypeMap = new HashMap<>();
+        }
+        if (plmnDataServicePolicyMap == null) {
+            plmnDataServicePolicyMap = new HashMap<>();
+        }
+        if (plmnVoiceServicePolicyMap == null) {
+            plmnVoiceServicePolicyMap = new HashMap<>();
+        }
         logd("onSatelliteEntitlementStatusUpdated subId=" + subId + ", entitlementEnabled="
                 + entitlementEnabled + ", allowedPlmnList=["
                 + String.join(",", allowedPlmnList) + "]" + ", barredPlmnList=["
-                + String.join(",", barredPlmnList) + "]");
+                + String.join(",", barredPlmnList) + "]"
+                + ", plmnDataPlanMap =" + plmnDataPlanMap.toString()
+                + ", plmnServiceTypeMap =" + plmnServiceTypeMap.toString()
+                + ", plmnDataServicePolicyMap=" + plmnDataServicePolicyMap.toString()
+                + ", plmnVoiceServicePolicyMap=" + plmnVoiceServicePolicyMap.toString());
 
         synchronized (mSupportedSatelliteServicesLock) {
             if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) {
@@ -4262,6 +4304,9 @@
                 mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList);
                 mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList);
                 mEntitlementDataPlanMapPerCarrier.put(subId, plmnDataPlanMap);
+                mEntitlementServiceTypeMapPerCarrier.put(subId, plmnServiceTypeMap);
+                mEntitlementDataServicePolicyMapPerCarrier.put(subId, plmnDataServicePolicyMap);
+                mEntitlementVoiceServicePolicyMapPerCarrier.put(subId, plmnVoiceServicePolicyMap);
                 updatePlmnListPerCarrier(subId);
                 configureSatellitePlmnForCarrier(subId);
                 mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList);
@@ -5364,6 +5409,7 @@
                 config = mCarrierConfigManager.getConfigForSubId(subId,
                         KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
                         KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                        KEY_SATELLITE_DISPLAY_NAME_STRING,
                         KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL,
                         KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
                         KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
@@ -5379,9 +5425,10 @@
                         KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT,
                         KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT,
                         KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT,
-                        KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE,
+                        KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT,
                         KEY_SATELLITE_SUPPORTED_MSG_APPS_STRING_ARRAY,
-                        KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE
+                        KEY_REGIONAL_SATELLITE_EARFCN_BUNDLE,
+                        KEY_SATELLITE_DATA_SUPPORT_MODE_INT
                 );
             } catch (Exception e) {
                 logw("getConfigForSubId: " + e);
@@ -5587,6 +5634,11 @@
                 KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT);
     }
 
+    @CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE
+    private int getCarrierSatelliteDataSupportedMode(int subId) {
+        return getConfigForSubId(subId).getInt(KEY_SATELLITE_DATA_SUPPORT_MODE_INT);
+    }
+
     /**
      * Check if satellite attach is enabled by user for the carrier associated with the
      * {@code subId}.
@@ -7177,6 +7229,29 @@
     }
 
     /**
+     * Request to get the name to display for Satellite.
+     *
+     * @param result The result receiver that returns the name to display for the satellite
+     *               or an error code if the request failed.
+     */
+    public void requestSatelliteDisplayName(@NonNull ResultReceiver result) {
+        if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+            plogd("requestSatelliteDisplayName: carrierRoamingNbIotNtn flag is disabled");
+            result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
+            return;
+        }
+
+        int subId = getSelectedSatelliteSubId();
+        String displayName = getConfigForSubId(subId).getString(
+                KEY_SATELLITE_DISPLAY_NAME_STRING, "Satellite");
+
+        plogd("requestSatelliteDisplayName: " + displayName);
+        Bundle bundle = new Bundle();
+        bundle.putString(SatelliteManager.KEY_SATELLITE_DISPLAY_NAME, displayName);
+        result.send(SATELLITE_RESULT_SUCCESS, bundle);
+    }
+
+    /**
      * Request to get list of prioritized satellite tokens to be used for provision.
      *
      * @param result The result receiver, which returns the list of prioritized satellite tokens
@@ -7923,8 +7998,8 @@
     private void overrideSatelliteCapabilitiesIfApplicable() {
         int subId = getSelectedSatelliteSubId();
         PersistableBundle config = getPersistableBundle(subId);
-        if (config.containsKey(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE)) {
-            int datagramSize = config.getInt(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE);
+        if (config.containsKey(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT)) {
+            int datagramSize = config.getInt(KEY_SATELLITE_SOS_MAX_DATAGRAM_SIZE_BYTES_INT);
             SubscriptionInfo subInfo = mSubscriptionManagerService.getSubscriptionInfo(subId);
             if (!(subInfo == null || subInfo.isOnlyNonTerrestrialNetwork())) {
                 synchronized (mSatelliteCapabilitiesLock) {
@@ -8314,4 +8389,56 @@
         // TODO (Override with carrier config value when configuration defined)
         return SATELLITE_DATA_PLAN_METERED;
     }
+
+    /**
+     * Method to return the current satellite data service policy supported mode for the registered
+     * plmn based on entitlement provisioning information. Note: If no information at
+     * provisioning is supported this is overridden with operator carrier config information.
+     *
+     * @param subId current subscription id
+     * @param plmn current registered plmn information
+     *
+     * @return Supported modes {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}
+     */
+    public int getSatelliteDataServicePolicyForPlmn(int subId, String plmn) {
+        if (plmn != null) {
+            synchronized (mSupportedSatelliteServicesLock) {
+                Map<String, Integer> dataServicePolicy =
+                        mEntitlementDataServicePolicyMapPerCarrier.get(
+                        subId);
+                logd("data policy available for sub id:" + dataServicePolicy);
+                if (dataServicePolicy != null && dataServicePolicy.containsKey(plmn)) {
+                    return dataServicePolicy.get(plmn);
+                }
+            }
+        }
+        return getCarrierSatelliteDataSupportedMode(subId);
+    }
+
+    /**
+     * Method to return the current satellite voice service policy supported mode for the registered
+     * plmn based on entitlement provisioning information. Note: If no information at
+     * provisioning is supported this is overridden with operator carrier config information.
+     *
+     * @param subId current subscription id
+     * @param plmn current registered plmn information
+     *
+     * @return Supported modes {@link CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE}
+     */
+    public int getSatelliteVoiceServicePolicyForPlmn(int subId, String plmn) {
+        if (plmn != null) {
+            synchronized (mSupportedSatelliteServicesLock) {
+                Map<String, Integer> voiceServicePolicy =
+                        mEntitlementVoiceServicePolicyMapPerCarrier.get(
+                                subId);
+                logd("voice policy available for sub id:" + voiceServicePolicy);
+                if (voiceServicePolicy != null && voiceServicePolicy.containsKey(plmn)) {
+                    return voiceServicePolicy.get(plmn);
+                }
+            }
+        }
+        // TODO (Replace below code with related enum value, when voice service policy support mode
+        // is added)
+        return 0; // Restricted
+    }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
index 7db9195..f101f18 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteNetworkInfo.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.telephony.satellite;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Data class of the satellite configuration received from the entitlement server.
  */
@@ -28,9 +31,21 @@
      * 2. "metered"
      * 3. empty string. */
     public String mDataPlanType;
+    /** Stored the Allowed Services Info. with key as service type and value as service
+     *  policy for the plmn
+     *  Possible Service Type values: "data" and "voice".
+     *  Possible Service Policy values: "constrained" and "unconstrained".
+     */
+    public Map<String,String> mAllowedServicesInfo;
 
-    public SatelliteNetworkInfo(String plmn, String dataPlanType) {
+    public SatelliteNetworkInfo(String plmn, String dataPlanType,
+            Map<String,String> allowedServicesInfo) {
         mPlmn = plmn;
         mDataPlanType = dataPlanType;
+        if (allowedServicesInfo != null) {
+            mAllowedServicesInfo = new HashMap<>(allowedServicesInfo);
+        } else {
+            mAllowedServicesInfo = new HashMap<>();
+        }
     }
 }
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index 64bd2b7..e924878 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -76,6 +76,7 @@
 import com.android.internal.telephony.flags.Flags;
 import com.android.internal.telephony.metrics.SatelliteStats;
 
+import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -274,12 +275,13 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     protected boolean isSatelliteAllowedByReasons() {
         SatelliteManager satelliteManager = mContext.getSystemService(SatelliteManager.class);
-        List<Integer> disallowedReasons = satelliteManager.getSatelliteDisallowedReasons();
-        if (disallowedReasons.stream().anyMatch(r ->
+        int[] disallowedReasons = satelliteManager.getSatelliteDisallowedReasons();
+        if (Arrays.stream(disallowedReasons).anyMatch(r ->
                 (r == SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP
                         || r == SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED
                         || r == SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED))) {
-            plogd("isAllowedForDefaultMessageApp:false, disallowedReasons=" + disallowedReasons);
+            plogd("isAllowedForDefaultMessageApp:false, disallowedReasons="
+                    + Arrays.toString(disallowedReasons));
             return false;
         }
         return true;
@@ -671,7 +673,7 @@
 
     @NonNull private Bundle createExtraBundleForEventDisplayEmergencyMessage(
             boolean isTestEmergencyNumber) {
-        int handoverType = EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
+        int handoverType = getEmergencyCallToSatelliteHandoverType();
         Pair<String, String> oemSatelliteMessagingApp =
                 getOemEnabledSatelliteHandoverAppFromOverlayConfig(mContext);
         String packageName = oemSatelliteMessagingApp.first;
@@ -679,10 +681,8 @@
         String action = getSatelliteEmergencyHandoverIntentActionFromOverlayConfig(mContext,
                 isTestEmergencyNumber);
 
-        if (isSatelliteConnectedViaCarrierWithinHysteresisTime()
-                || isEmergencyCallToSatelliteHandoverTypeT911Enforced()) {
+        if (handoverType == EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911) {
             ComponentName defaultSmsAppComponent = getDefaultSmsApp();
-            handoverType = EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
             packageName = defaultSmsAppComponent.getPackageName();
             className = defaultSmsAppComponent.getClassName();
         }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index f92643a..a7923cf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1044,7 +1044,8 @@
             doReturn(new TelephonyDisplayInfo(
                     mNetworkTypeController.getDataNetworkType(),
                     mNetworkTypeController.getOverrideNetworkType(),
-                    false)).when(mDisplayInfoController).getTelephonyDisplayInfo();
+                    false, false, false))
+                    .when(mDisplayInfoController).getTelephonyDisplayInfo();
             return null;
         }).when(mDisplayInfoController).updateTelephonyDisplayInfo();
         mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index f934371..0449f8a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -1344,7 +1344,7 @@
         TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
                 TelephonyManager.NETWORK_TYPE_LTE,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
-                false);
+                false, false, false);
 
         // Notify with invalid subId on default phone. Should NOT trigger callback.
         mTelephonyRegistry.notifyDisplayInfoChanged(0, INVALID_SUBSCRIPTION_ID, displayInfo);
@@ -1371,11 +1371,11 @@
         TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
                 TelephonyManager.NETWORK_TYPE_LTE,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
-                false);
+                false, false, false);
         TelephonyDisplayInfo expectDisplayInfo = new TelephonyDisplayInfo(
                 TelephonyManager.NETWORK_TYPE_LTE,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
-                false);
+                false, false, false);
 
         // Notify with invalid subId on default phone. Should NOT trigger callback.
         mTelephonyRegistry.notifyDisplayInfoChanged(0, INVALID_SUBSCRIPTION_ID, displayInfo);
@@ -1398,11 +1398,11 @@
         TelephonyDisplayInfo displayInfo = new TelephonyDisplayInfo(
                 TelephonyManager.NETWORK_TYPE_LTE,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED,
-                false);
+                false, false, false);
         TelephonyDisplayInfo expectDisplayInfo = new TelephonyDisplayInfo(
                 TelephonyManager.NETWORK_TYPE_LTE,
                 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE,
-                false);
+                false, false, false);
         TelephonyCallback telephonyCallback2 = new TelephonyCallbackWrapper() {
             @Override
             public void onDisplayInfoChanged(TelephonyDisplayInfo displayInfoNotify) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 88eea32..0db881c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -811,7 +811,7 @@
         doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_LTE).when(mServiceState)
                 .getRilDataRadioTechnology();
         doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE,
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
                 .when(mDisplayInfoController).getTelephonyDisplayInfo();
         doReturn(mPhone).when(mCT).getPhone();
         doReturn(mImsEcbm).when(mImsManager).getEcbmInterface();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
index 0e2676e..d3f3050 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
@@ -101,9 +101,11 @@
     public void setUp() throws Exception {
         super.setUp(getClass().getSimpleName());
         mGoodTelephonyDisplayInfo = new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false /*roaming*/);
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false /*roaming*/,
+                false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/);
         mBadTelephonyDisplayInfo = new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UMTS,
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false /*roaming*/);
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false /*roaming*/,
+                false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/);
         mMockedPhoneSwitcherCallback =
                 mock(AutoDataSwitchController.AutoDataSwitchControllerCallback.class);
         mMockedAlarmManager = mock(AlarmManager.class);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
index 95cefd8..88dce51 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataConfigManagerTest.java
@@ -126,20 +126,23 @@
         doReturn(SignalStrength.SIGNAL_STRENGTH_POOR).when(signalStrength).getLevel();
         assertThat(mDataConfigManagerUT.getAutoDataSwitchScore(new TelephonyDisplayInfo(
                         TelephonyManager.NETWORK_TYPE_LTE,
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false/*isRoaming*/),
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED, false/*isRoaming*/,
+                        false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/),
                 signalStrength)).isEqualTo(10227);
         // Verify if entry contains any invalid negative scores, should yield 0.
         doReturn(SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN).when(signalStrength).getLevel();
         assertThat(mDataConfigManagerUT.getAutoDataSwitchScore(new TelephonyDisplayInfo(
                         TelephonyManager.NETWORK_TYPE_LTE,
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/),
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/,
+                        false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/),
                 signalStrength))
                 .isEqualTo(0/*OUT_OF_SERVICE_AUTO_DATA_SWITCH_SCORE*/);
         // Verify non-existent entry should yield -1
         doReturn(SignalStrength.SIGNAL_STRENGTH_POOR).when(signalStrength).getLevel();
         assertThat(mDataConfigManagerUT.getAutoDataSwitchScore(new TelephonyDisplayInfo(
                         TelephonyManager.NETWORK_TYPE_EDGE,
-                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/),
+                        TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false/*isRoaming*/,
+                        false/*isNtn*/, false/*isSatelliteConstrainedDataStatus*/),
                 signalStrength))
                 .isEqualTo(0/*OUT_OF_SERVICE_AUTO_DATA_SWITCH_SCORE*/);
     }
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 4cc10d9..3f2d6f2 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -2478,7 +2478,7 @@
 
         // Change data network type to NR
         doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
                 .when(mDisplayInfoController).getTelephonyDisplayInfo();
         dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
         processAllMessages();
@@ -2521,7 +2521,7 @@
 
         // Change data network type to NR
         doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
                 .when(mDisplayInfoController).getTelephonyDisplayInfo();
         dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
         processAllMessages();
@@ -2577,7 +2577,7 @@
 
         // Change data network type to NR
         doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_NR,
-                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false))
+                TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false))
                 .when(mDisplayInfoController).getTelephonyDisplayInfo();
         dataNetwork.sendMessage(13/*EVENT_DISPLAY_INFO_CHANGED*/);
         processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
index f7990b9..6e41448 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -146,7 +146,7 @@
     private AutoDataSwitchController.AutoDataSwitchControllerCallback mAutoDataSwitchCallback;
     private TelephonyDisplayInfo mTelephonyDisplayInfo = new TelephonyDisplayInfo(
             TelephonyManager.NETWORK_TYPE_NR,
-            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false);
+            TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, false, false, false);
     private SubscriptionManagerServiceCallback mSubscriptionManagerServiceCallback;
 
     @Before
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
index 110dade..e6e4c30 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -4370,94 +4370,95 @@
     public void addSatelliteControllerStats_withExistingEntries() throws Exception {
         createEmptyTestFile();
         mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
-        mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController1);
-        mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController2);
+        mPersistAtomsStorage.addSatelliteControllerStats(copyOf(mSatelliteController1));
+        mPersistAtomsStorage.addSatelliteControllerStats(copyOf(mSatelliteController1));
         mPersistAtomsStorage.incTimeMillis(100L);
 
         SatelliteController expected = new SatelliteController();
         expected.countOfSatelliteServiceEnablementsSuccess =
-                mSatelliteController1.countOfSatelliteServiceEnablementsSuccess
-                        + mSatelliteController2.countOfSatelliteServiceEnablementsSuccess;
+                mSatelliteController1.countOfSatelliteServiceEnablementsSuccess * 2;
         expected.countOfSatelliteServiceEnablementsFail =
-                mSatelliteController1.countOfSatelliteServiceEnablementsFail
-                        + mSatelliteController2.countOfSatelliteServiceEnablementsFail;
+                mSatelliteController1.countOfSatelliteServiceEnablementsFail * 2;
         expected.countOfOutgoingDatagramSuccess =
-                mSatelliteController1.countOfOutgoingDatagramSuccess
-                        + mSatelliteController2.countOfOutgoingDatagramSuccess;
+                mSatelliteController1.countOfOutgoingDatagramSuccess * 2;
         expected.countOfOutgoingDatagramFail =
-                mSatelliteController1.countOfOutgoingDatagramFail
-                        + mSatelliteController2.countOfOutgoingDatagramFail;
+                mSatelliteController1.countOfOutgoingDatagramFail * 2;
         expected.countOfIncomingDatagramSuccess =
-                mSatelliteController1.countOfIncomingDatagramSuccess
-                        + mSatelliteController2.countOfIncomingDatagramSuccess;
+                mSatelliteController1.countOfIncomingDatagramSuccess * 2;
         expected.countOfIncomingDatagramFail =
-                mSatelliteController1.countOfIncomingDatagramFail
-                        + mSatelliteController2.countOfIncomingDatagramFail;
+                mSatelliteController1.countOfIncomingDatagramFail * 2;
         expected.countOfDatagramTypeSosSmsSuccess =
-                mSatelliteController1.countOfDatagramTypeSosSmsSuccess
-                        + mSatelliteController2.countOfDatagramTypeSosSmsSuccess;
+                mSatelliteController1.countOfDatagramTypeSosSmsSuccess * 2;
         expected.countOfDatagramTypeSosSmsFail =
-                mSatelliteController1.countOfDatagramTypeSosSmsFail
-                        + mSatelliteController2.countOfDatagramTypeSosSmsFail;
+                mSatelliteController1.countOfDatagramTypeSosSmsFail * 2;
         expected.countOfDatagramTypeLocationSharingSuccess =
-                mSatelliteController1.countOfDatagramTypeLocationSharingSuccess
-                        + mSatelliteController2.countOfDatagramTypeLocationSharingSuccess;
+                mSatelliteController1.countOfDatagramTypeLocationSharingSuccess * 2;
         expected.countOfDatagramTypeLocationSharingFail =
-                mSatelliteController1.countOfDatagramTypeLocationSharingFail
-                        + mSatelliteController2.countOfDatagramTypeLocationSharingFail;
+                mSatelliteController1.countOfDatagramTypeLocationSharingFail * 2;
         expected.countOfProvisionSuccess =
-                mSatelliteController1.countOfProvisionSuccess
-                        + mSatelliteController2.countOfProvisionSuccess;
+                mSatelliteController1.countOfProvisionSuccess * 2;
         expected.countOfProvisionFail =
-                mSatelliteController1.countOfProvisionFail
-                        + mSatelliteController2.countOfProvisionFail;
+                mSatelliteController1.countOfProvisionFail * 2;
         expected.countOfDeprovisionSuccess =
-                mSatelliteController1.countOfDeprovisionSuccess
-                        + mSatelliteController2.countOfDeprovisionSuccess;
+                mSatelliteController1.countOfDeprovisionSuccess * 2;
         expected.countOfDeprovisionFail =
-                mSatelliteController1.countOfDeprovisionFail
-                        + mSatelliteController2.countOfDeprovisionFail;
+                mSatelliteController1.countOfDeprovisionFail * 2;
         expected.totalServiceUptimeSec =
-                mSatelliteController1.totalServiceUptimeSec
-                        + mSatelliteController2.totalServiceUptimeSec;
+                mSatelliteController1.totalServiceUptimeSec * 2;
         expected.totalBatteryConsumptionPercent =
-                mSatelliteController1.totalBatteryConsumptionPercent
-                        + mSatelliteController2.totalBatteryConsumptionPercent;
+                mSatelliteController1.totalBatteryConsumptionPercent * 2;
         expected.totalBatteryChargedTimeSec =
-                mSatelliteController1.totalBatteryChargedTimeSec
-                        + mSatelliteController2.totalBatteryChargedTimeSec;
+                mSatelliteController1.totalBatteryChargedTimeSec * 2;
         expected.countOfDemoModeSatelliteServiceEnablementsSuccess =
-                mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsSuccess
-                        + mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsSuccess;
+                mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsSuccess * 2;
         expected.countOfDemoModeSatelliteServiceEnablementsFail =
-                mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsFail
-                        + mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsFail;
+                mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsFail * 2;
         expected.countOfDemoModeOutgoingDatagramSuccess =
-                mSatelliteController1.countOfDemoModeOutgoingDatagramSuccess
-                        + mSatelliteController2.countOfDemoModeOutgoingDatagramSuccess;
+                mSatelliteController1.countOfDemoModeOutgoingDatagramSuccess * 2;
         expected.countOfDemoModeOutgoingDatagramFail =
-                mSatelliteController1.countOfDemoModeOutgoingDatagramFail
-                        + mSatelliteController2.countOfDemoModeOutgoingDatagramFail;
+                mSatelliteController1.countOfDemoModeOutgoingDatagramFail * 2;
         expected.countOfDemoModeIncomingDatagramSuccess =
-                mSatelliteController1.countOfDemoModeIncomingDatagramSuccess
-                        + mSatelliteController2.countOfDemoModeIncomingDatagramSuccess;
+                mSatelliteController1.countOfDemoModeIncomingDatagramSuccess * 2;
         expected.countOfDemoModeIncomingDatagramFail =
-                mSatelliteController1.countOfDemoModeIncomingDatagramFail
-                        + mSatelliteController2.countOfDemoModeIncomingDatagramFail;
+                mSatelliteController1.countOfDemoModeIncomingDatagramFail * 2;
         expected.countOfDatagramTypeKeepAliveSuccess =
-                mSatelliteController1.countOfDatagramTypeKeepAliveSuccess
-                        + mSatelliteController2.countOfDatagramTypeKeepAliveSuccess;
+                mSatelliteController1.countOfDatagramTypeKeepAliveSuccess * 2;
         expected.countOfDatagramTypeKeepAliveFail =
-                mSatelliteController1.countOfDatagramTypeKeepAliveFail
-                        + mSatelliteController2.countOfDatagramTypeKeepAliveFail;
-        expected.isProvisioned = mSatelliteController2.isProvisioned;
-        expected.carrierId = mSatelliteController2.carrierId;
+                mSatelliteController1.countOfDatagramTypeKeepAliveFail * 2;
+        expected.isProvisioned = mSatelliteController1.isProvisioned;
+        expected.carrierId = mSatelliteController1.carrierId;
+        expected.countOfSatelliteAllowedStateChangedEvents =
+                mSatelliteController1.countOfSatelliteAllowedStateChangedEvents * 2;
+        expected.countOfSuccessfulLocationQueries =
+                mSatelliteController1.countOfSuccessfulLocationQueries * 2;
+        expected.countOfFailedLocationQueries =
+                mSatelliteController1.countOfFailedLocationQueries * 2;
 
         // Service state and service switch should be added successfully
         verifyCurrentStateSavedToFileOnce();
         SatelliteController[] output =
                 mPersistAtomsStorage.getSatelliteControllerStats(0L);
-        assertHasStats(output, expected);
+        assertHasStats(output, expected, 1);
+    }
+
+    @Test
+    public void addSatelliteControllerStats_addNewCarrierId() throws Exception {
+        createEmptyTestFile();
+        mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+        mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController1);
+        mPersistAtomsStorage.addSatelliteControllerStats(mSatelliteController2);
+        mPersistAtomsStorage.incTimeMillis(100L);
+
+        SatelliteController expected1 = mSatelliteController1;
+        SatelliteController expected2 = mSatelliteController2;
+
+        // Service state and service switch should be added successfully
+        verifyCurrentStateSavedToFileOnce();
+        SatelliteController[] output =
+                mPersistAtomsStorage.getSatelliteControllerStats(0L);
+
+        assertHasStats(output, expected1, 1);
+        assertHasStats(output, expected2, 1);
     }
 
     @Test
@@ -5829,60 +5830,71 @@
         assertEquals(expectedCount, actualCount);
     }
 
-    private static void assertHasStats(
-            SatelliteController[] tested,
-            @Nullable SatelliteController expectedStats) {
+    private static void assertHasStats(SatelliteController[] tested,
+            @Nullable SatelliteController expectedStats, int expectedCount) {
         assertNotNull(tested);
-        assertEquals(tested[0].countOfSatelliteServiceEnablementsSuccess,
-                expectedStats.countOfSatelliteServiceEnablementsSuccess);
-        assertEquals(tested[0].countOfSatelliteServiceEnablementsFail,
-                expectedStats.countOfSatelliteServiceEnablementsFail);
-        assertEquals(tested[0].countOfOutgoingDatagramSuccess,
-                expectedStats.countOfOutgoingDatagramSuccess);
-        assertEquals(tested[0].countOfOutgoingDatagramFail,
-                expectedStats.countOfOutgoingDatagramFail);
-        assertEquals(tested[0].countOfIncomingDatagramSuccess,
-                expectedStats.countOfIncomingDatagramSuccess);
-        assertEquals(tested[0].countOfIncomingDatagramFail,
-                expectedStats.countOfIncomingDatagramFail);
-        assertEquals(tested[0].countOfDatagramTypeSosSmsSuccess,
-                expectedStats.countOfDatagramTypeSosSmsSuccess);
-        assertEquals(tested[0].countOfDatagramTypeSosSmsFail,
-                expectedStats.countOfDatagramTypeSosSmsFail);
-        assertEquals(tested[0].countOfDatagramTypeLocationSharingSuccess,
-                expectedStats.countOfDatagramTypeLocationSharingSuccess);
-        assertEquals(tested[0].countOfDatagramTypeLocationSharingFail,
-                expectedStats.countOfDatagramTypeLocationSharingFail);
-        assertEquals(tested[0].totalServiceUptimeSec,
-                expectedStats.totalServiceUptimeSec);
-        assertEquals(tested[0].totalBatteryConsumptionPercent,
-                expectedStats.totalBatteryConsumptionPercent);
-        assertEquals(tested[0].totalBatteryChargedTimeSec,
-                expectedStats.totalBatteryChargedTimeSec);
-        assertEquals(tested[0].countOfDemoModeSatelliteServiceEnablementsSuccess,
-                expectedStats.countOfDemoModeSatelliteServiceEnablementsSuccess);
-        assertEquals(tested[0].countOfDemoModeSatelliteServiceEnablementsFail,
-                expectedStats.countOfDemoModeSatelliteServiceEnablementsFail);
-        assertEquals(tested[0].countOfDemoModeOutgoingDatagramSuccess,
-                expectedStats.countOfDemoModeOutgoingDatagramSuccess);
-        assertEquals(tested[0].countOfDemoModeOutgoingDatagramFail,
-                expectedStats.countOfDemoModeOutgoingDatagramFail);
-        assertEquals(tested[0].countOfDemoModeIncomingDatagramSuccess,
-                expectedStats.countOfDemoModeIncomingDatagramSuccess);
-        assertEquals(tested[0].countOfDemoModeIncomingDatagramFail,
-                expectedStats.countOfDemoModeIncomingDatagramFail);
-        assertEquals(tested[0].countOfDatagramTypeKeepAliveSuccess,
-                expectedStats.countOfDatagramTypeKeepAliveSuccess);
-        assertEquals(tested[0].countOfDatagramTypeKeepAliveFail,
-                expectedStats.countOfDatagramTypeKeepAliveFail);
-        assertEquals(tested[0].countOfAllowedSatelliteAccess,
-                expectedStats.countOfAllowedSatelliteAccess);
-        assertEquals(tested[0].countOfDisallowedSatelliteAccess,
-                expectedStats.countOfDisallowedSatelliteAccess);
-        assertEquals(tested[0].countOfSatelliteAccessCheckFail,
-                expectedStats.countOfSatelliteAccessCheckFail);
-        assertEquals(tested[0].isProvisioned, expectedStats.isProvisioned);
-        assertEquals(tested[0].carrierId, expectedStats.carrierId);
+        int actualCount = 0;
+        int i = 0;
+        for (SatelliteController stats : tested) {
+            if (expectedStats.carrierId == stats.carrierId) {
+                assertEquals(expectedStats.countOfSatelliteServiceEnablementsSuccess,
+                        stats.countOfSatelliteServiceEnablementsSuccess);
+                assertEquals(expectedStats.countOfSatelliteServiceEnablementsFail,
+                        stats.countOfSatelliteServiceEnablementsFail);
+                assertEquals(expectedStats.countOfOutgoingDatagramSuccess,
+                        stats.countOfOutgoingDatagramSuccess);
+                assertEquals(expectedStats.countOfOutgoingDatagramFail,
+                        stats.countOfOutgoingDatagramFail);
+                assertEquals(expectedStats.countOfIncomingDatagramSuccess,
+                        stats.countOfIncomingDatagramSuccess);
+                assertEquals(expectedStats.countOfIncomingDatagramFail,
+                        stats.countOfIncomingDatagramFail);
+                assertEquals(expectedStats.countOfDatagramTypeSosSmsSuccess,
+                        stats.countOfDatagramTypeSosSmsSuccess);
+                assertEquals(expectedStats.countOfDatagramTypeSosSmsFail,
+                        stats.countOfDatagramTypeSosSmsFail);
+                assertEquals(expectedStats.countOfDatagramTypeLocationSharingSuccess,
+                        stats.countOfDatagramTypeLocationSharingSuccess);
+                assertEquals(expectedStats.countOfDatagramTypeLocationSharingFail,
+                        stats.countOfDatagramTypeLocationSharingFail);
+                assertEquals(expectedStats.totalServiceUptimeSec, stats.totalServiceUptimeSec);
+                assertEquals(expectedStats.totalBatteryConsumptionPercent,
+                        stats.totalBatteryConsumptionPercent);
+                assertEquals(expectedStats.totalBatteryChargedTimeSec,
+                        stats.totalBatteryChargedTimeSec);
+                assertEquals(expectedStats.countOfDemoModeSatelliteServiceEnablementsSuccess,
+                        stats.countOfDemoModeSatelliteServiceEnablementsSuccess);
+                assertEquals(expectedStats.countOfDemoModeSatelliteServiceEnablementsFail,
+                        stats.countOfDemoModeSatelliteServiceEnablementsFail);
+                assertEquals(expectedStats.countOfDemoModeOutgoingDatagramSuccess,
+                        stats.countOfDemoModeOutgoingDatagramSuccess);
+                assertEquals(expectedStats.countOfDemoModeOutgoingDatagramFail,
+                        stats.countOfDemoModeOutgoingDatagramFail);
+                assertEquals(expectedStats.countOfDemoModeIncomingDatagramSuccess,
+                        stats.countOfDemoModeIncomingDatagramSuccess);
+                assertEquals(expectedStats.countOfDemoModeIncomingDatagramFail,
+                        stats.countOfDemoModeIncomingDatagramFail);
+                assertEquals(expectedStats.countOfDatagramTypeKeepAliveSuccess,
+                        stats.countOfDatagramTypeKeepAliveSuccess);
+                assertEquals(expectedStats.countOfDatagramTypeKeepAliveFail,
+                        stats.countOfDatagramTypeKeepAliveFail);
+                assertEquals(expectedStats.countOfAllowedSatelliteAccess,
+                        stats.countOfAllowedSatelliteAccess);
+                assertEquals(expectedStats.countOfDisallowedSatelliteAccess,
+                        stats.countOfDisallowedSatelliteAccess);
+                assertEquals(expectedStats.countOfSatelliteAccessCheckFail,
+                        stats.countOfSatelliteAccessCheckFail);
+                assertEquals(expectedStats.isProvisioned, stats.isProvisioned);
+                assertEquals(expectedStats.countOfSatelliteAllowedStateChangedEvents,
+                        stats.countOfSatelliteAllowedStateChangedEvents);
+                assertEquals(expectedStats.countOfSuccessfulLocationQueries,
+                        stats.countOfSuccessfulLocationQueries);
+                assertEquals(expectedStats.countOfFailedLocationQueries,
+                        stats.countOfFailedLocationQueries);
+                actualCount++;
+            }
+        }
+        assertEquals(expectedCount, actualCount);
     }
 
     private static void assertHasStatsAndCount(
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 3ccd17e..6f716b5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -33,7 +33,12 @@
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_NIDD_APN_NAME_STRING;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL;
 import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ROAMING_TURN_OFF_SESSION_FOR_EMERGENCY_CALL_BOOL;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED;
 import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_VOICE;
 import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
 import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD;
 import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GREAT;
@@ -3168,7 +3173,8 @@
         // Verify call the requestSetSatelliteEnabledForCarrier to enable the satellite when
         // satellite service is enabled by entitlement server.
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
-                new ArrayList<>(), new HashMap<>(), mIIntegerConsumer);
+                new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), mIIntegerConsumer);
         processAllMessages();
 
         assertTrue(waitForIIntegerConsumerResult(1));
@@ -3188,7 +3194,8 @@
                 .when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
         setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
-                new ArrayList<>(), new HashMap<>(), mIIntegerConsumer);
+                new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), mIIntegerConsumer);
         processAllMessages();
 
         assertTrue(waitForIIntegerConsumerResult(1));
@@ -3219,7 +3226,8 @@
         List<String> entitlementPlmnList = new ArrayList<>();
         List<String> barredPlmnList = new ArrayList<>();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, new HashMap<>(), mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
         verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
                 any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
 
@@ -3277,7 +3285,8 @@
         reset(mMockSatelliteModemInterface);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", ""}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, new HashMap<>(), mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
         verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
                 any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
 
@@ -3285,7 +3294,8 @@
         reset(mMockSatelliteModemInterface);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "123456789"}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, new HashMap<>(), mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
         verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
                 any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
 
@@ -3293,7 +3303,8 @@
         reset(mMockSatelliteModemInterface);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "12"}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, new HashMap<>(), mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
         verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
                 any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
 
@@ -3301,7 +3312,8 @@
         reset(mMockSatelliteModemInterface);
         entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "1234"}).toList();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, new HashMap<>(), mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
         verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(
                 any(SatelliteModemEnableRequestAttributes.class), any(Message.class));
     }
@@ -3310,7 +3322,8 @@
             List<String> mergedPlmnList, List<String> overlayConfigPlmnList,
             List<String> barredPlmnList) {
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, new HashMap<>(), mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
 
         List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
                 SUB_ID);
@@ -3532,21 +3545,24 @@
 
         // Change SUB_ID's EntitlementStatus to true
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
-                new ArrayList<>(), new HashMap<>(), mIIntegerConsumer);
+                new ArrayList<>(), new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
 
         assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
         assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID1));
 
         // Change SUB_ID1's EntitlementStatus to true
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID1, true, new ArrayList<>(),
-                new ArrayList<>(), new HashMap<>(), mIIntegerConsumer);
+                new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), mIIntegerConsumer);
 
         assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
         assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
 
         // Change SUB_ID's EntitlementStatus to false
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
-                new ArrayList<>(), new HashMap<>(), mIIntegerConsumer);
+                new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+                new HashMap<>(), mIIntegerConsumer);
 
         assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID));
         assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
@@ -6373,7 +6389,8 @@
                 "00101", SATELLITE_DATA_PLAN_METERED,
                 "00103", SATELLITE_DATA_PLAN_UNMETERED);
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, dataPlanListMap, mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, dataPlanListMap, new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
 
         int dataPlanForPlmn;
         dataPlanForPlmn = mSatelliteControllerUT.getSatelliteDataPlanForPlmn(SUB_ID, "00101");
@@ -6404,9 +6421,170 @@
         List<String> barredPlmnList = new ArrayList<>();
         Map<String, Integer> dataPlanListMap = new HashMap<>();
         mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
-                entitlementPlmnList, barredPlmnList, dataPlanListMap, mIIntegerConsumer);
+                entitlementPlmnList, barredPlmnList, dataPlanListMap, new HashMap<>(),
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
 
         int dataPlanForPlmn = mSatelliteControllerUT.getSatelliteDataPlanForPlmn(SUB_ID, "00101");
         assertEquals(SATELLITE_DATA_PLAN_METERED, dataPlanForPlmn);
     }
+
+    @Test
+    public void TestGetSupportedSatelliteServicesForPlmn_WithEntitlement() throws Exception {
+        logd("TestGetSupportedSatelliteServicesForPlmn_WithEntitlement");
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+        replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+                mSatelliteControllerUT, new SparseArray<>());
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+
+        List<String> entitlementPlmnList =
+                Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+                        .toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, List<Integer>> serviceTypeListMap = Map.of(
+                "00101", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS),
+                "00102", List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+                "00103", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS));
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), serviceTypeListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+        List<Integer> allowedServiceForPlmn;
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00101");
+        assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_SMS), allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00102");
+        assertEquals(List.of(SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS), allowedServiceForPlmn);
+
+        allowedServiceForPlmn = mSatelliteControllerUT
+                .getSupportedSatelliteServicesForPlmn(SUB_ID, "00103");
+        assertEquals(List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE, SERVICE_TYPE_SMS),
+                allowedServiceForPlmn);
+    }
+
+    @Test
+    public void TestGetSupportedSatelliteServicesForPlmn_WithoutEntitlement() throws Exception {
+        logd("TestGetSupportedSatelliteServicesForPlmn_WithoutAllowedServices");
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+        replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+                mSatelliteControllerUT, new SparseArray<>());
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+
+        List<String> entitlementPlmnList =
+                Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+                        .toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, Integer> dataPlanListMap =  new HashMap<>();
+        Map<String, List<Integer>> allowedServiceListMap = new HashMap<>();
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, dataPlanListMap, allowedServiceListMap,
+                new HashMap<>(), new HashMap<>(), mIIntegerConsumer);
+
+        // Verify whether the carrier config plmn list is returned with conditions below
+        // the config data plmn list : empty
+        // the carrier config plmn list : exist with services {{2}}
+        setConfigData(new ArrayList<>());
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+        PersistableBundle carrierSupportedSatelliteServicesPerProvider =
+                new PersistableBundle();
+        List<String> carrierConfigPlmnList = List.of("00101");
+        carrierSupportedSatelliteServicesPerProvider.putIntArray(
+                carrierConfigPlmnList.get(0), new int[]{2});
+        mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
+                        .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+                carrierSupportedSatelliteServicesPerProvider);
+        invokeCarrierConfigChanged();
+
+        List<Integer> servicesPerPlmn;
+        servicesPerPlmn = mSatelliteControllerUT.getSupportedSatelliteServicesForPlmn(
+                SUB_ID, "00101");
+        assertEquals(Arrays.asList(2).stream().sorted().toList(),
+                servicesPerPlmn.stream().sorted().toList());
+    }
+
+    @Test
+    public void testGetSupportedSatelliteDataModeForPlmn_WithEntitlement() throws Exception {
+        logd("testGetSupportedSatelliteDataModeForPlmn_WithEntitlement");
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+        replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+                mSatelliteControllerUT, new SparseArray<>());
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+
+        List<String> entitlementPlmnList =
+                Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+                        .toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, Integer> dataServicePolicyMap = Map.of(
+                "00101", SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED,
+                "00102", SATELLITE_DATA_SUPPORT_ALL
+        );
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                dataServicePolicyMap, new HashMap<>(), mIIntegerConsumer);
+
+        int dataSupportModeForPlmn;
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101");
+        assertEquals(SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED, dataSupportModeForPlmn);
+
+        dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00102");
+        assertEquals(SATELLITE_DATA_SUPPORT_ALL, dataSupportModeForPlmn);
+
+    }
+
+    @Test
+    public void testGetSupportedSatelliteDataModeForPlmn_WithoutEntitlement() throws Exception {
+        logd("testGetSupportedSatelliteDataModeForPlmn_WithoutEntitlement");
+        when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
+        replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
+                mSatelliteControllerUT, new SparseArray<>());
+        List<String> overlayConfigPlmnList = new ArrayList<>();
+        replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
+                mSatelliteControllerUT, overlayConfigPlmnList);
+        mCarrierConfigBundle.putBoolean(
+                CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+        mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+                true);
+
+        List<String> entitlementPlmnList =
+                Arrays.stream(new String[]{"00101", "00102", "00103", "00104"})
+                        .toList();
+        List<String> barredPlmnList = new ArrayList<>();
+        Map<String, Integer> dataServicePolicyMap = new HashMap<>();
+        mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+                entitlementPlmnList, barredPlmnList, new HashMap<>(), new HashMap<>(),
+                dataServicePolicyMap, new HashMap<>(), mIIntegerConsumer);
+
+        mCarrierConfigBundle.putInt(
+                CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+                SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED);
+        int dataSupportModeForPlmn = mSatelliteControllerUT
+                .getSatelliteDataServicePolicyForPlmn(SUB_ID, "00101");
+        assertEquals(SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED, dataSupportModeForPlmn);
+    }
 }