Merge "Add requestSatelliteDisplayNameForSubscription in SatelliteManager" into main
diff --git a/assets/google_us_san_mtv_sat_s2.dat b/assets/google_us_san_mtv_sat_s2.dat
new file mode 100644
index 0000000..26516010
--- /dev/null
+++ b/assets/google_us_san_mtv_sat_s2.dat
Binary files differ
diff --git a/assets/satellite_access_config.json b/assets/satellite_access_config.json
new file mode 100644
index 0000000..4f9f853
--- /dev/null
+++ b/assets/satellite_access_config.json
@@ -0,0 +1,140 @@
+{
+    "access_control_configs": [
+        {
+            "config_id": 0,
+            "satellite_infos": [
+                {
+                    "satellite_id": "0db0312f-d73f-444d-b99b-a893dfb42edf",
+                    "satellite_position": {
+                        "longitude": -150.3,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        259,
+                        260
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3000,
+                            "end_earfcn": 4300
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                6,
+                7,
+                8
+            ]
+        },
+        {
+            "config_id": 1,
+            "satellite_infos": [
+                {
+                    "satellite_id": "1dec24f8-9223-4196-ad7a-a03002db7af7",
+                    "satellite_position": {
+                        "longitude": 15.5,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        257,
+                        258
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3200,
+                            "end_earfcn": 3200
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                9,
+                10,
+                11
+            ]
+        },
+        {
+            "config_id": 2,
+            "satellite_infos": [
+                {
+                    "satellite_id": "f60cb479-d85b-4f4e-b050-cc428f5eb4a4",
+                    "satellite_position": {
+                        "longitude": -150,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        259,
+                        260
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3300,
+                            "end_earfcn": 3400
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                12,
+                13,
+                14
+            ]
+        },
+        {
+            "config_id": 3,
+            "satellite_infos": [
+                {
+                    "satellite_id": "c5837d96-9585-46aa-8dd0-a974583737fb",
+                    "satellite_position": {
+                        "longitude": -155,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        261,
+                        262
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3500,
+                            "end_earfcn": 3600
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                15,
+                16,
+                17
+            ]
+        }
+        ,
+        {
+            "config_id": 4,
+            "satellite_infos": [
+                {
+                    "satellite_id": "6ef2a128-0477-4271-895f-dc4a221d2b23",
+                    "satellite_position": {
+                        "longitude": -66,
+                        "altitude": 35786000
+                    },
+                    "bands": [
+                        263,
+                        264
+                    ],
+                    "earfcn_ranges": [
+                        {
+                            "start_earfcn": 3700,
+                            "end_earfcn": 3800
+                        }
+                    ]
+                }
+            ],
+            "tag_ids": [
+                18,
+                19,
+                20
+            ]
+        }
+    ]
+}
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index a7054f9..60bbe0a 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -86,8 +86,8 @@
     <string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"Билдирмелер"</string>
     <string name="cell_broadcast_settings" msgid="8135324242541809924">"Өзгөчө кырдаал тууралуу кулактандыруу"</string>
     <string name="call_settings" msgid="3677282690157603818">"Чалуу параметрлери"</string>
-    <string name="additional_gsm_call_settings" msgid="1561980168685658846">"Кошумча жөндөөлөр"</string>
-    <string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Кошумча жөндөөлөр (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+    <string name="additional_gsm_call_settings" msgid="1561980168685658846">"Кошумча параметрлер"</string>
+    <string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Кошумча параметрлер (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
     <string name="sum_gsm_call_settings" msgid="7964692601608878138">"GSM менен гана чалуунун кошумча параметрлери"</string>
     <string name="additional_cdma_call_settings" msgid="2178016561980611304">"Кошумча CDMA чалуунун параметрлери"</string>
     <string name="sum_cdma_call_settings" msgid="3185825305136993636">"CDMA менен гана чалуунун кошумча параметрлери"</string>
diff --git a/src/com/android/phone/EventLogTags.logtags b/src/com/android/phone/EventLogTags.logtags
index 474a01c..f7654af 100644
--- a/src/com/android/phone/EventLogTags.logtags
+++ b/src/com/android/phone/EventLogTags.logtags
@@ -1,4 +1,4 @@
-# See system/core/logcat/event.logtags for a description of the format of this file.
+# See system/logging/logcat/event.logtags for a description of the format of this file.
 
 option java_package com.android.phone;
 
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 9ba9dec..1a645da 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -26,6 +26,9 @@
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ACCESS_BARRED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP;
 
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
@@ -163,6 +166,7 @@
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
 import android.telephony.satellite.ISatelliteSupportedStateCallback;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
+import android.telephony.satellite.ISelectedNbIotSatelliteSubscriptionCallback;
 import android.telephony.satellite.NtnSignalStrength;
 import android.telephony.satellite.NtnSignalStrengthCallback;
 import android.telephony.satellite.SatelliteCapabilities;
@@ -8595,9 +8599,10 @@
                 setNetworkSelectionModeAutomatic(subId);
                 Phone phone = getPhone(subId);
                 cleanUpAllowedNetworkTypes(phone, subId);
+
                 setDataRoamingEnabled(subId, phone == null ? false
                         : phone.getDataSettingsManager().isDefaultDataRoamingEnabled());
-                getPhone(subId).resetCarrierKeysForImsiEncryption();
+                getPhone(subId).resetCarrierKeysForImsiEncryption(true);
             }
             // There has been issues when Sms raw table somehow stores orphan
             // fragments. They lead to garbled message when new fragments come
@@ -13226,6 +13231,15 @@
                             result.accept(resultCode);
                             return;
                         }
+                        List<Integer> disallowedReasons =
+                                mSatelliteAccessController.getSatelliteDisallowedReasons();
+                        if (disallowedReasons.stream().anyMatch(r ->
+                                (r == SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP
+                                        || r == SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED
+                                        || r == SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED))) {
+                            result.accept(SATELLITE_RESULT_ACCESS_BARRED);
+                            return;
+                        }
                         if (isAllowed) {
                             ResultReceiver resultReceiver = new ResultReceiver(mMainThreadHandler) {
                                 @Override
@@ -13319,12 +13333,9 @@
      *
      * @param result The result receiver that returns whether the satellite service is supported on
      *               the device if the request is successful or an error code if the request failed.
-     *
-     * @throws SecurityException if the caller doesn't have the required permission.
      */
     @Override
     public void requestIsSatelliteSupported(@NonNull ResultReceiver result) {
-        enforceSatelliteCommunicationPermission("requestIsSatelliteSupported");
         final long identity = Binder.clearCallingIdentity();
         try {
             mSatelliteController.requestIsSatelliteSupported(result);
@@ -13809,6 +13820,54 @@
     }
 
     /**
+     * Registers for selected satellite subscription changed event from the satellite service.
+     *
+     * @param callback The callback to handle the satellite subscription changed event.
+     *
+     * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     */
+    @Override
+    @SatelliteManager.SatelliteResult
+    public int registerForSelectedNbIotSatelliteSubscriptionChanged(
+            @NonNull ISelectedNbIotSatelliteSubscriptionCallback callback) {
+        enforceSatelliteCommunicationPermission(
+                "registerForSelectedNbIotSatelliteSubscriptionChanged");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return mSatelliteController.registerForSelectedNbIotSatelliteSubscriptionChanged(
+                    callback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Unregisters for selected satellite subscription changed event from the satellite service.
+     * If callback was not registered before, the request will be ignored.
+     *
+     * @param callback The callback that was passed to {@link
+     *     #registerForSelectedNbIotSatelliteSubscriptionChanged(
+     *     ISelectedNbIotSatelliteSubscriptionCallback)}.
+     *
+     * @throws SecurityException if the caller doesn't have required permission.
+     */
+    @Override
+    public void unregisterForSelectedNbIotSatelliteSubscriptionChanged(
+            @NonNull ISelectedNbIotSatelliteSubscriptionCallback callback) {
+        enforceSatelliteCommunicationPermission(
+                "unregisterForSelectedNbIotSatelliteSubscriptionChanged");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mSatelliteController.unregisterForSelectedNbIotSatelliteSubscriptionChanged(
+                    callback);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Inform whether the device is aligned with the satellite in both real and demo mode.
      *
      * @param isAligned {@code true} Device is aligned with the satellite.
@@ -14333,12 +14392,13 @@
      */
     public boolean setSatelliteAccessControlOverlayConfigs(boolean reset, boolean isAllowed,
             String s2CellFile, long locationFreshDurationNanos,
-            List<String> satelliteCountryCodes) {
+            List<String> satelliteCountryCodes, String satelliteAccessConfigurationFile) {
         Log.d(LOG_TAG, "setSatelliteAccessControlOverlayConfigs: reset=" + reset
                 + ", isAllowed" + isAllowed + ", s2CellFile=" + s2CellFile
                 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
                 + ", satelliteCountryCodes=" + ((satelliteCountryCodes != null)
-                ? String.join(", ", satelliteCountryCodes) : null));
+                ? String.join(", ", satelliteCountryCodes) : null)
+                + ", satelliteAccessConfigurationFile=" + satelliteAccessConfigurationFile);
         TelephonyPermissions.enforceShellOnly(
                 Binder.getCallingUid(), "setSatelliteAccessControlOverlayConfigs");
         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
@@ -14347,7 +14407,8 @@
         final long identity = Binder.clearCallingIdentity();
         try {
             return mSatelliteAccessController.setSatelliteAccessControlOverlayConfigs(reset,
-                    isAllowed, s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
+                    isAllowed, s2CellFile, locationFreshDurationNanos, satelliteCountryCodes,
+                    satelliteAccessConfigurationFile);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -14807,7 +14868,13 @@
     public void setNtnSmsSupported(boolean ntnSmsSupported) {
         enforceSatelliteCommunicationPermission("setNtnSmsSupported");
         enforceSendSmsPermission();
-        mSatelliteController.setNtnSmsSupportedByMessagesApp(ntnSmsSupported);
+
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mSatelliteController.setNtnSmsSupportedByMessagesApp(ntnSmsSupported);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     /**
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 5ea1304..cd6a369 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -232,6 +232,7 @@
             "set-allowed-network-types-for-users";
     private static final String GET_IMEI = "get-imei";
     private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
+    private static final String COMMAND_DELETE_IMSI_KEY = "delete_imsi_key";
     // Take advantage of existing methods that already contain permissions checks when possible.
     private final ITelephony mInterface;
 
@@ -431,6 +432,8 @@
                 return handleSetSatelliteSubscriberIdListChangedIntentComponent();
             case SET_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT:
                 return handleOverrideCarrierRoamingNtnEligibilityChanged();
+            case COMMAND_DELETE_IMSI_KEY:
+                return handleDeleteTestImsiKey();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -3590,9 +3593,11 @@
         String s2CellFile = null;
         long locationFreshDurationNanos = 0;
         List<String> satelliteCountryCodes = null;
+        String satelliteAccessConfigurationFile = null;
 
         String opt;
         while ((opt = getNextOption()) != null) {
+            Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: opt=" + opt);
             switch (opt) {
                 case "-r": {
                     reset = true;
@@ -3615,16 +3620,22 @@
                     satelliteCountryCodes = Arrays.asList(countryCodeStr.split(","));
                     break;
                 }
+                case "-g": {
+                    satelliteAccessConfigurationFile = getNextArgRequired();
+                    break;
+                }
             }
         }
         Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: reset=" + reset
                 + ", isAllowed=" + isAllowed + ", s2CellFile=" + s2CellFile
                 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
-                + ", satelliteCountryCodes=" + satelliteCountryCodes);
+                + ", satelliteCountryCodes=" + satelliteCountryCodes
+                + ", satelliteAccessConfigurationFile=" + satelliteAccessConfigurationFile);
 
         try {
             boolean result = mInterface.setSatelliteAccessControlOverlayConfigs(reset, isAllowed,
-                    s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
+                    s2CellFile, locationFreshDurationNanos, satelliteCountryCodes,
+                    satelliteAccessConfigurationFile);
             if (VDBG) {
                 Log.v(LOG_TAG, "setSatelliteAccessControlOverlayConfigs result =" + result);
             }
@@ -4132,4 +4143,22 @@
         Log.d(LOG_TAG, "handleSetSatelliteAccessRestrictionCheckingResult(" + state + ")");
         return 0;
     }
+
+    private int handleDeleteTestImsiKey() {
+        if (!(checkShellUid())) {
+                Log.v(LOG_TAG,
+                    "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
+                            + " checkShellUid fails");
+            return -1;
+        }
+
+        Phone phone = PhoneFactory.getDefaultPhone();
+        if (phone == null) {
+            Log.e(LOG_TAG,
+                    "handleCarrierRestrictionStatusCommand" + "No default Phone available");
+            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        }
+        phone.resetCarrierKeysForImsiEncryption(true);
+        return 1;
+    }
 }
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParser.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParser.java
index 0658279..895edfd 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParser.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParser.java
@@ -60,7 +60,6 @@
     public static final String SATELLITE_BANDS = "bands";
     public static final String SATELLITE_TAG_ID_LIST = "tag_ids";
 
-
     /**
      * Parses a JSON file containing satellite access configurations.
      *
@@ -193,15 +192,17 @@
         return satelliteId;
     }
 
-    @Nullable
+    @NonNull
     protected static SatellitePosition parseSatellitePosition(
             @NonNull JSONObject satelliteInfoJson) {
         JSONObject jsonObject = satelliteInfoJson.optJSONObject(SATELLITE_POSITION);
+        SatellitePosition satellitePosition = new SatellitePosition(Double.NaN, Double.NaN);
+
         if (jsonObject == null) {
             loge("parseSatellitePosition: jsonObject is null");
-            return null;
+            return satellitePosition;
         }
-        SatellitePosition satellitePosition;
+
         try {
             double longitude = jsonObject.getDouble(SATELLITE_LONGITUDE);
             double altitude = jsonObject.getDouble(SATELLITE_ALTITUDE);
@@ -209,11 +210,11 @@
                 satellitePosition = new SatellitePosition(longitude, altitude);
             } else {
                 loge("parseSatellitePosition: invalid value: " + longitude + " | " + altitude);
-                return null;
+                return satellitePosition;
             }
         } catch (JSONException e) {
             loge("parseSatellitePosition: json parsing error " + e.getMessage());
-            return null;
+            return satellitePosition;
         }
 
         logd("parseSatellitePosition: " + satellitePosition);
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index a47691e..9618f7a 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -25,6 +25,7 @@
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ACCESS_BARRED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_DISABLED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_NOT_AVAILABLE;
@@ -80,11 +81,13 @@
 import android.telephony.Rlog;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
+import android.telephony.satellite.EarfcnRange;
 import android.telephony.satellite.ISatelliteCommunicationAllowedStateCallback;
 import android.telephony.satellite.ISatelliteDisallowedReasonsCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
 import android.telephony.satellite.ISatelliteSupportedStateCallback;
 import android.telephony.satellite.SatelliteAccessConfiguration;
+import android.telephony.satellite.SatelliteInfo;
 import android.telephony.satellite.SatelliteManager;
 import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
 import android.telephony.satellite.SystemSelectionSpecifier;
@@ -133,6 +136,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /**
  * This module is responsible for making sure that satellite communication can be used by devices
@@ -180,7 +184,8 @@
     private static final String KEY_AVAILABLE_NOTIFICATION_SHOWN = "available_notification_shown";
     private static final String KEY_UNAVAILABLE_NOTIFICATION_SHOWN =
             "unavailable_notification_shown";
-    private static final String NOTIFICATION_TAG = "SatelliteAccessController";
+    private static final String AVAILABLE_NOTIFICATION_TAG = "available_notification_tag";
+    private static final String UNAVAILABLE_NOTIFICATION_TAG = "unavailable_notification_tag";
     private static final int NOTIFICATION_ID = 1;
     private static final String NOTIFICATION_CHANNEL = "satelliteChannel";
     private static final String NOTIFICATION_CHANNEL_ID = "satellite";
@@ -280,6 +285,8 @@
     private boolean mOverriddenIsSatelliteAllowAccessControl;
     @Nullable
     private File mOverriddenSatelliteS2CellFile;
+    @Nullable
+    private String mOverriddenSatelliteConfigurationFileName;
     private long mOverriddenLocationFreshDurationNanos;
 
     @GuardedBy("mLock")
@@ -321,11 +328,17 @@
     /** Key: Config ID; Value: SatelliteAccessConfiguration */
     @GuardedBy("mLock")
     @Nullable
-    private Map<Integer, SatelliteAccessConfiguration> mSatelliteAccessConfigMap;
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    protected Map<Integer, SatelliteAccessConfiguration> mSatelliteAccessConfigMap;
 
     /** These are used for CTS test */
     private Path mCtsSatS2FilePath = null;
+    private Path mCtsSatelliteAccessConfigurationFilePath = null;
     protected static final String GOOGLE_US_SAN_SAT_S2_FILE_NAME = "google_us_san_sat_s2.dat";
+    protected static final String GOOGLE_US_SAN_SAT_MTV_S2_FILE_NAME =
+            "google_us_san_mtv_sat_s2.dat";
+    protected static final String SATELLITE_ACCESS_CONFIG_FILE_NAME =
+            "satellite_access_config.json";
 
     /** These are for config updater config data */
     private static final String SATELLITE_ACCESS_CONTROL_DATA_DIR = "satellite_access_control";
@@ -358,6 +371,7 @@
     protected static final int
             DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION = 3;
     protected static final int DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES = 10;
+    private static final int MAX_EARFCN_ARRAY_LENGTH = 32;
 
     private long mRetryIntervalToEvaluateUserInSatelliteAllowedRegion = 0;
     private int mMaxRetryCountForValidatingPossibleChangeInAllowedRegion = 0;
@@ -458,6 +472,7 @@
         mControllerMetricsStats = ControllerMetricsStats.getInstance();
         mAccessControllerMetricsStats = AccessControllerMetricsStats.getInstance();
         initSharedPreferences(context);
+        checkSharedPreference();
         loadOverlayConfigs(context);
         // loadConfigUpdaterConfigs has to be called after loadOverlayConfigs
         // since config updater config has higher priority and thus can override overlay config
@@ -607,8 +622,8 @@
                         mNewRegionalConfigId = null;
                     }
                 }
-                updateRegionalConfigId();
             }
+            updateRegionalConfigId();
         }
     }
 
@@ -752,7 +767,8 @@
      */
     public boolean setSatelliteAccessControlOverlayConfigs(boolean reset, boolean isAllowed,
             @Nullable String s2CellFile, long locationFreshDurationNanos,
-            @Nullable List<String> satelliteCountryCodes) {
+            @Nullable List<String> satelliteCountryCodes,
+            @Nullable String satelliteConfigurationFile) {
         if (!isMockModemAllowed()) {
             plogd("setSatelliteAccessControllerOverlayConfigs: mock modem is not allowed");
             return false;
@@ -761,7 +777,8 @@
                 + ", isAllowed" + isAllowed + ", s2CellFile=" + s2CellFile
                 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
                 + ", satelliteCountryCodes=" + ((satelliteCountryCodes != null)
-                ? String.join(", ", satelliteCountryCodes) : null));
+                ? String.join(", ", satelliteCountryCodes) : null)
+                + ", satelliteConfigurationFile=" + satelliteConfigurationFile);
         synchronized (mLock) {
             if (reset) {
                 mIsOverlayConfigOverridden = false;
@@ -777,9 +794,25 @@
                                 + " does not exist");
                         mOverriddenSatelliteS2CellFile = null;
                     }
+                    mCachedAccessRestrictionMap.clear();
                 } else {
                     mOverriddenSatelliteS2CellFile = null;
                 }
+                if (!TextUtils.isEmpty(satelliteConfigurationFile)) {
+                    File overriddenSatelliteConfigurationFile = getTestSatelliteConfiguration(
+                            satelliteConfigurationFile);
+                    if (overriddenSatelliteConfigurationFile.exists()) {
+                        mOverriddenSatelliteConfigurationFileName =
+                                overriddenSatelliteConfigurationFile.getAbsolutePath();
+                    } else {
+                        plogd("The overriding file "
+                                + overriddenSatelliteConfigurationFile.getAbsolutePath()
+                                + " does not exist");
+                        mOverriddenSatelliteConfigurationFileName = null;
+                    }
+                } else {
+                    mOverriddenSatelliteConfigurationFileName = null;
+                }
                 mOverriddenLocationFreshDurationNanos = locationFreshDurationNanos;
                 if (satelliteCountryCodes != null) {
                     mOverriddenSatelliteCountryCodes = satelliteCountryCodes;
@@ -808,7 +841,7 @@
             if (mRegionalConfigId == null) {
                 plogd("updateSystemSelectionChannels: Invalid Regional config ID."
                         + " System Selection channels can not be passed down to modem");
-                result.send(SatelliteManager.SATELLITE_RESULT_ACCESS_BARRED, null);
+                result.send(SATELLITE_RESULT_ACCESS_BARRED, null);
                 return;
             }
         }
@@ -817,8 +850,9 @@
 
     protected File getTestSatelliteS2File(String fileName) {
         plogd("getTestSatelliteS2File: fileName=" + fileName);
-        if (TextUtils.equals(fileName, GOOGLE_US_SAN_SAT_S2_FILE_NAME)) {
-            mCtsSatS2FilePath = copyTestSatS2FileToPhoneDirectory(GOOGLE_US_SAN_SAT_S2_FILE_NAME);
+        if (TextUtils.equals(fileName, GOOGLE_US_SAN_SAT_S2_FILE_NAME)
+                || TextUtils.equals(fileName, GOOGLE_US_SAN_SAT_MTV_S2_FILE_NAME)) {
+            mCtsSatS2FilePath = copyTestAssetFileToPhoneDirectory(fileName);
             if (mCtsSatS2FilePath != null) {
                 return mCtsSatS2FilePath.toFile();
             } else {
@@ -828,8 +862,21 @@
         return new File(fileName);
     }
 
+    protected File getTestSatelliteConfiguration(String fileName) {
+        plogd("getTestSatelliteConfiguration: fileName=" + fileName);
+        if (TextUtils.equals(fileName, SATELLITE_ACCESS_CONFIG_FILE_NAME)) {
+            mCtsSatelliteAccessConfigurationFilePath = copyTestAssetFileToPhoneDirectory(fileName);
+            if (mCtsSatelliteAccessConfigurationFilePath != null) {
+                return mCtsSatelliteAccessConfigurationFilePath.toFile();
+            } else {
+                ploge("getTestSatelliteConfiguration: mCtsSatelliteConfigurationFilePath is null");
+            }
+        }
+        return new File(fileName);
+    }
+
     @Nullable
-    private static Path copyTestSatS2FileToPhoneDirectory(String sourceFileName) {
+    private static Path copyTestAssetFileToPhoneDirectory(String sourceFileName) {
         PhoneGlobals phoneGlobals = PhoneGlobals.getInstance();
         File ctsFile = phoneGlobals.getDir("cts", Context.MODE_PRIVATE);
         if (!ctsFile.exists()) {
@@ -837,26 +884,26 @@
         }
 
         Path targetDir = ctsFile.toPath();
-        Path targetSatS2FilePath = targetDir.resolve(sourceFileName);
+        Path targetFilePath = targetDir.resolve(sourceFileName);
         try {
             var assetManager = phoneGlobals.getAssets();
             if (assetManager == null) {
-                loge("copyTestSatS2FileToPhoneDirectory: no assets");
+                loge("copyTestAssetFileToPhoneDirectory: no assets");
                 return null;
             }
             InputStream inputStream = assetManager.open(sourceFileName);
             if (inputStream == null) {
-                loge("copyTestSatS2FileToPhoneDirectory: Resource=" + sourceFileName
+                loge("copyTestAssetFileToPhoneDirectory: Resource=" + sourceFileName
                         + " not found");
                 return null;
             } else {
-                Files.copy(inputStream, targetSatS2FilePath, StandardCopyOption.REPLACE_EXISTING);
+                Files.copy(inputStream, targetFilePath, StandardCopyOption.REPLACE_EXISTING);
             }
         } catch (IOException ex) {
-            loge("copyTestSatS2FileToPhoneDirectory: ex=" + ex);
+            loge("copyTestAssetFileToPhoneDirectory: ex=" + ex);
             return null;
         }
-        return targetSatS2FilePath;
+        return targetFilePath;
     }
 
     @Nullable
@@ -1121,8 +1168,16 @@
     }
 
     protected void loadSatelliteAccessConfigurationFromDeviceConfig() {
-        String satelliteConfigurationFileName =
-                getSatelliteConfigurationFileNameFromOverlayConfig(mContext);
+        logd("loadSatelliteAccessConfigurationFromDeviceConfig:");
+        String satelliteConfigurationFileName;
+        synchronized (mLock) {
+            if (mIsOverlayConfigOverridden && mOverriddenSatelliteConfigurationFileName != null) {
+                satelliteConfigurationFileName = mOverriddenSatelliteConfigurationFileName;
+            } else {
+                satelliteConfigurationFileName = getSatelliteConfigurationFileNameFromOverlayConfig(
+                        mContext);
+            }
+        }
         loadSatelliteAccessConfigurationFromFile(satelliteConfigurationFileName);
     }
 
@@ -1435,7 +1490,11 @@
         logd("mSatelliteDisallowedReasons:"
                 + String.join(", ", mSatelliteDisallowedReasons.toString()));
         notifySatelliteDisallowedReasonsChanged();
-        if (mFeatureFlags.carrierRoamingNbIotNtn() && mNotifySatelliteAvailabilityEnabled) {
+        int subId = mSatelliteController.getSelectedSatelliteSubId();
+        int carrierRoamingNtnConnectType =
+            mSatelliteController.getCarrierRoamingNtnConnectType(subId);
+        if (mSatelliteController.isSatelliteSystemNotificationsEnabled(
+                carrierRoamingNtnConnectType)) {
             showSatelliteSystemNotification();
         }
     }
@@ -1447,44 +1506,59 @@
         }
 
         if (mSatelliteDisallowedReasons.isEmpty()) {
-            if (!hasAlreadyNotified(KEY_AVAILABLE_NOTIFICATION_SHOWN, 0)) {
+            mNotificationManager.cancel(UNAVAILABLE_NOTIFICATION_TAG, NOTIFICATION_ID);
+            if (!hasAlreadyNotified(KEY_AVAILABLE_NOTIFICATION_SHOWN)) {
                 mNotificationManager.notifyAsUser(
-                        NOTIFICATION_TAG,
+                        AVAILABLE_NOTIFICATION_TAG,
                         NOTIFICATION_ID,
                         mSatelliteAvailableNotification,
                         UserHandle.ALL
                 );
-                markAsNotified(KEY_AVAILABLE_NOTIFICATION_SHOWN, 0);
+                markAsNotified(KEY_AVAILABLE_NOTIFICATION_SHOWN, true);
+                markAsNotified(KEY_UNAVAILABLE_NOTIFICATION_SHOWN, false);
             }
         } else {
+            mNotificationManager.cancel(AVAILABLE_NOTIFICATION_TAG, NOTIFICATION_ID);
             for (Integer reason : mSatelliteDisallowedReasons) {
-                if (!hasAlreadyNotified(KEY_UNAVAILABLE_NOTIFICATION_SHOWN, reason)) {
+                if (!hasAlreadyNotified(KEY_UNAVAILABLE_NOTIFICATION_SHOWN)) {
                     mNotificationManager.notifyAsUser(
-                            NOTIFICATION_TAG,
+                            UNAVAILABLE_NOTIFICATION_TAG,
                             NOTIFICATION_ID,
                             mSatelliteUnAvailableNotifications.get(reason),
                             UserHandle.ALL
                     );
-                    markAsNotified(KEY_UNAVAILABLE_NOTIFICATION_SHOWN, reason);
+                    markAsNotified(KEY_UNAVAILABLE_NOTIFICATION_SHOWN, true);
+                    markAsNotified(KEY_AVAILABLE_NOTIFICATION_SHOWN, false);
                     break;
                 }
             }
         }
     }
 
-    private boolean hasAlreadyNotified(String key, int reason) {
-        Set<String> reasons = mSharedPreferences.getStringSet(key, new HashSet<>());
-        return reasons.contains(String.valueOf(reason));
+    private boolean hasAlreadyNotified(String key) {
+        return mSharedPreferences.getBoolean(key, false);
     }
 
-    private void markAsNotified(String key, int reason) {
-        Set<String> reasons = mSharedPreferences.getStringSet(key, new HashSet<>());
-        if (!reasons.contains(String.valueOf(reason))) {
-            reasons.add(String.valueOf(reason));
-            SharedPreferences.Editor editor = mSharedPreferences.edit();
-            editor.putStringSet(key, reasons);
-            editor.apply();
-        }
+    private void markAsNotified(String key, boolean notified) {
+        mSharedPreferences.edit().putBoolean(key, notified).apply();
+    }
+
+    private void checkSharedPreference() {
+        String[] keys = {
+                CONFIG_UPDATER_SATELLITE_IS_ALLOW_ACCESS_CONTROL_KEY,
+                LATEST_SATELLITE_COMMUNICATION_ALLOWED_KEY,
+                KEY_AVAILABLE_NOTIFICATION_SHOWN,
+                KEY_UNAVAILABLE_NOTIFICATION_SHOWN
+        };
+        // An Exception may occur if the initial value is set to HashSet while attempting to obtain
+        // a boolean value. If an exception occurs, the SharedPreferences will be removed with Keys.
+        Arrays.stream(keys).forEach(key -> {
+            try {
+                mSharedPreferences.getBoolean(key, false);
+            } catch (ClassCastException e) {
+                mSharedPreferences.edit().remove(key).apply();
+            }
+        });
     }
 
     /**
@@ -2224,41 +2298,66 @@
                 mccmnc = subInfo.getMccString() + subInfo.getMncString();
             }
 
-            synchronized (mRegionalSatelliteEarfcnsLock) {
-                /* Key: Regional satellite config ID, Value: SatelliteRegionalConfig
-                 * contains satellite config IDs and set of earfcns in the corresponding regions.
-                 */
-                Map<Integer, SatelliteRegionalConfig> satelliteRegionalConfigMap =
-                        mSatelliteRegionalConfigPerSubMap.get(subId);
-                if (satelliteRegionalConfigMap == null || satelliteRegionalConfigMap.isEmpty()) {
-                    plogd("handleCmdUpdateSystemSelectionChannels: config IDs and Earfcns are not"
-                            + " found for subId: "
-                            + subId);
-                    sendUpdateSystemSelectionChannelsResult(
-                            SATELLITE_RESULT_INVALID_TELEPHONY_STATE, null);
-                    return;
-                }
-
-                SatelliteRegionalConfig satelliteRegionalConfig = satelliteRegionalConfigMap.get(
-                        mRegionalConfigId);
-                if (satelliteRegionalConfig == null) {
-                    plogd("handleCmdUpdateSystemSelectionChannels: "
-                            + "Earfcns for satellite config Id: " + mRegionalConfigId
-                            + " not found");
-                    sendUpdateSystemSelectionChannelsResult(
-                            SATELLITE_RESULT_INVALID_TELEPHONY_STATE, null);
-                    return;
-                }
-                IntArray bands = new IntArray();
-                IntArray earfcns = new IntArray();
-                for (Integer value : satelliteRegionalConfig.getEarfcns()) {
-                    earfcns.add(value);
-                }
-
-                mSatelliteController.updateSystemSelectionChannels(
-                        new SystemSelectionSpecifier(mccmnc, bands, earfcns),
-                        mInternalUpdateSystemSelectionChannelsResultReceiver);
+            final Integer[] regionalConfigId = new Integer[1];
+            regionalConfigId[0] = getSelectedRegionalConfigId();
+            if (regionalConfigId[0] != null
+                    && regionalConfigId[0] == UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID) {
+                // The geofence file with old format return UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID
+                // for an S2 cell present in the file.
+                // For backward compatibility, we will use DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+                // for such cases.
+                regionalConfigId[0] = DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
             }
+            if (!SatelliteAccessConfigurationParser.isRegionalConfigIdValid(regionalConfigId[0])) {
+                plogd("handleCmdUpdateSystemSelectionChannels: mRegionalConfigId is not valid, "
+                        + "mRegionalConfig=" + getSelectedRegionalConfigId());
+                sendUpdateSystemSelectionChannelsResult(
+                        SATELLITE_RESULT_ACCESS_BARRED, null);
+                return;
+            }
+
+            SatelliteAccessConfiguration satelliteAccessConfiguration;
+            synchronized (mLock) {
+                satelliteAccessConfiguration = Optional.ofNullable(mSatelliteAccessConfigMap)
+                        .map(map -> map.get(regionalConfigId[0]))
+                        .orElse(null);
+            }
+            if (satelliteAccessConfiguration == null) {
+                plogd("handleCmdUpdateSystemSelectionChannels: satelliteAccessConfiguration "
+                        + "is not valid");
+                sendUpdateSystemSelectionChannelsResult(
+                        SATELLITE_RESULT_ACCESS_BARRED, null);
+                return;
+            }
+
+            List<SatelliteInfo> satelliteInfos =
+                    satelliteAccessConfiguration.getSatelliteInfos();
+            List<Integer> bandList = new ArrayList<>();
+            List<Integer> earfcnList = new ArrayList<>();
+            for (SatelliteInfo satelliteInfo : satelliteInfos) {
+                bandList.addAll(satelliteInfo.getBands());
+                List<EarfcnRange> earfcnRangeList = satelliteInfo.getEarfcnRanges();
+                earfcnRangeList.stream().flatMapToInt(
+                        earfcnRange -> IntStream.of(earfcnRange.getStartEarfcn(),
+                                earfcnRange.getEndEarfcn())).boxed().forEach(earfcnList::add);
+            }
+
+            IntArray bands = new IntArray(bandList.size());
+            bands.addAll(bandList.stream().mapToInt(Integer::intValue).toArray());
+            IntArray earfcns = new IntArray(
+                    Math.min(earfcnList.size(), MAX_EARFCN_ARRAY_LENGTH));
+            for (int i = 0; i < Math.min(earfcnList.size(), MAX_EARFCN_ARRAY_LENGTH); i++) {
+                earfcns.add(earfcnList.get(i));
+            }
+            IntArray tagIds = new IntArray(satelliteAccessConfiguration.getTagIds().size());
+            tagIds.addAll(satelliteAccessConfiguration.getTagIds().stream().mapToInt(
+                    Integer::intValue).toArray());
+
+            List<SystemSelectionSpecifier> selectionSpecifiers = new ArrayList<>();
+            selectionSpecifiers.add(new SystemSelectionSpecifier(mccmnc, bands, earfcns,
+                    satelliteInfos.toArray(new SatelliteInfo[0]), tagIds));
+            mSatelliteController.updateSystemSelectionChannels(selectionSpecifiers,
+                    mInternalUpdateSystemSelectionChannelsResultReceiver);
         }
     }
 
@@ -2909,6 +3008,13 @@
         evaluatePossibleChangeInDefaultSmsApp(context);
     }
 
+    @Nullable
+    private Integer getSelectedRegionalConfigId() {
+        synchronized (mLock) {
+            return mRegionalConfigId;
+        }
+    }
+
     private void plogv(@NonNull String log) {
         Rlog.v(TAG, log);
         if (mPersistentLogger != null) {
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
index 8d9850d..1f46ff6 100644
--- a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
@@ -489,7 +489,11 @@
         logd("queryCompleted: updateSatelliteEntitlementStatus");
         updateSatelliteEntitlementStatus(subId, entitlementResult.getEntitlementStatus() ==
                         SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_ENABLED,
-                entitlementResult.getAllowedPLMNList(), entitlementResult.getBarredPLMNList());
+                entitlementResult.getAllowedPLMNList(), entitlementResult.getBarredPLMNList(),
+                entitlementResult.getDataPlanInfoForPlmnList(),
+                entitlementResult.getAvailableServiceTypeInfoForPlmnList(),
+                entitlementResult.getDataServicePolicyInfoForPlmnList(),
+                entitlementResult.getVoiceServicePolicyInfoForPlmnList());
     }
 
     private boolean shouldStartQueryEntitlement(int subId) {
@@ -546,7 +550,10 @@
                 mSatelliteEntitlementResultPerSub.put(subId, enabledResult);
             }
             updateSatelliteEntitlementStatus(subId, true, enabledResult.getAllowedPLMNList(),
-                    enabledResult.getBarredPLMNList());
+                    enabledResult.getBarredPLMNList(), enabledResult.getDataPlanInfoForPlmnList(),
+                    enabledResult.getAvailableServiceTypeInfoForPlmnList(),
+                    enabledResult.getDataServicePolicyInfoForPlmnList(),
+                    enabledResult.getVoiceServicePolicyInfoForPlmnList());
         }
         resetEntitlementQueryPerSubId(subId);
     }
@@ -655,9 +662,14 @@
      */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public void updateSatelliteEntitlementStatus(int subId, boolean enabled,
-            List<String> plmnAllowedList, List<String> plmnBarredList) {
+            List<String> plmnAllowedList, List<String> plmnBarredList,
+            Map<String,Integer> plmnDataPlanMap,
+            Map<String, List<Integer>>plmnAllowedServicesMap,
+            Map<String,Integer>plmnDataServicePolicyMap,
+            Map<String, Integer>plmnVoiceServicePolicyMap) {
         SatelliteController.getInstance().onSatelliteEntitlementStatusUpdated(subId, enabled,
-                plmnAllowedList, plmnBarredList, null);
+                plmnAllowedList, plmnBarredList, plmnDataPlanMap, plmnAllowedServicesMap,
+                plmnDataServicePolicyMap, plmnVoiceServicePolicyMap, null);
     }
 
     private @SatelliteConstants.SatelliteEntitlementStatus int getEntitlementStatus(
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
index 97cb355..7d6b5ba 100644
--- a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
@@ -30,7 +30,9 @@
 import org.json.JSONObject;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -51,6 +53,14 @@
     private static final String PLMN_KEY = "PLMN";
     /** The data plan is of the metered or un-metered type. This value is optional. */
     private static final String DATA_PLAN_TYPE_KEY = "DataPlanType";
+    /** The allowed services info with array of allowed services */
+    private static final String ALLOWED_SERVICES_INFO_TYPE_KEY = "AllowedServicesInfo";
+    /** The allowed services with service type and service policy for the plmn*/
+    private static final String ALLOWED_SERVICES_KEY = "AllowedServices";
+    /** list of service type supported for the plmn*/
+    private static final String SERVICE_TYPE_KEY = "ServiceType";
+    /** list of service policy supported for the plmn*/
+    private static final String SERVICE_POLICY_KEY = "ServicePolicy";
 
     @SatelliteEntitlementResult.SatelliteEntitlementStatus private int mEntitlementStatus;
 
@@ -90,7 +100,7 @@
      */
     public List<SatelliteNetworkInfo> getPlmnAllowed() {
         return mPlmnAllowedList.stream().map((info) -> new SatelliteNetworkInfo(info.mPlmn,
-                info.mDataPlanType)).collect(Collectors.toList());
+                info.mDataPlanType, info.mAllowedServicesInfo)).collect(Collectors.toList());
     }
 
     /**
@@ -125,10 +135,31 @@
                 for (int i = 0; i < jsonArray.length(); i++) {
                     String dataPlanType = jsonArray.getJSONObject(i).has(DATA_PLAN_TYPE_KEY)
                             ? jsonArray.getJSONObject(i).getString(DATA_PLAN_TYPE_KEY) : "";
+                    Map<String, String> allowedServicesInfo = new HashMap<>();
+                    if (jsonArray.getJSONObject(i).has(ALLOWED_SERVICES_INFO_TYPE_KEY)) {
+                        allowedServicesInfo = new HashMap<>();
+                        JSONArray jsonArray1 = jsonArray.getJSONObject(i)
+                                .getJSONArray(ALLOWED_SERVICES_INFO_TYPE_KEY);
+                        for (int j = 0; j < jsonArray1.length(); j++) {
+                            String serviceType =  jsonArray1.getJSONObject(j)
+                                    .getJSONObject(ALLOWED_SERVICES_KEY)
+                                    .has(SERVICE_TYPE_KEY) ? jsonArray1.getJSONObject(j)
+                                    .getJSONObject(ALLOWED_SERVICES_KEY)
+                                    .getString(SERVICE_TYPE_KEY): "";
+                            String servicePolicy = jsonArray1.getJSONObject(j)
+                                    .getJSONObject(ALLOWED_SERVICES_KEY)
+                                    .has(SERVICE_POLICY_KEY) ? jsonArray1.getJSONObject(j)
+                                    .getJSONObject(ALLOWED_SERVICES_KEY)
+                                    .getString(SERVICE_POLICY_KEY) : "";
+                            allowedServicesInfo.put(serviceType, servicePolicy);
+                        }
+                    }
                     String plmn = jsonArray.getJSONObject(i).getString(PLMN_KEY);
-                    logd("parsingResponse: plmn=" + plmn + " dataplan=" + dataPlanType);
+                    logd("parsingResponse: plmn=" + plmn + " dataplan=" + dataPlanType
+                            + " allowedServices=" + allowedServicesInfo);
                     if (!TextUtils.isEmpty(plmn)) {
-                        mPlmnAllowedList.add(new SatelliteNetworkInfo(plmn, dataPlanType));
+                        mPlmnAllowedList.add(new SatelliteNetworkInfo(
+                                plmn, dataPlanType, allowedServicesInfo));
                     }
                 }
             }
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
index 014e28e..5d531fc 100644
--- a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
@@ -16,12 +16,23 @@
 
 package com.android.phone.satellite.entitlement;
 
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_VOICE;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_SMS;
+
+import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_DATA_PLAN_METERED;
+import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_DATA_PLAN_UNMETERED;
+
 import android.annotation.IntDef;
 
 import com.android.internal.telephony.satellite.SatelliteNetworkInfo;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -112,4 +123,85 @@
         return new SatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_DISABLED,
                 new ArrayList<>(), new ArrayList<>());
     }
+
+    /**
+     * Get the data plan for the plmn List
+     *
+     * @return data plan for the plmn List
+     */
+    public Map<String, Integer> getDataPlanInfoForPlmnList() {
+        Map<String, Integer> dataPlanInfo = new HashMap<>();
+
+        for (SatelliteNetworkInfo plmnInfo :  mAllowedSatelliteNetworkInfoList) {
+            int dataPlan = SATELLITE_DATA_PLAN_METERED; // default metered is available
+            if (plmnInfo.mDataPlanType.equalsIgnoreCase("unmetered")) {
+                dataPlan = SATELLITE_DATA_PLAN_UNMETERED; // overwrite data plan if unmetered
+            }
+            dataPlanInfo.put(plmnInfo.mPlmn, dataPlan);
+        }
+        return dataPlanInfo;
+    }
+
+    /**
+     * Get ServiceType at Allowed Services for the plmn List
+     *
+     * @return The Allowed Services for the plmn List
+     */
+    public Map<String, List<Integer>> getAvailableServiceTypeInfoForPlmnList() {
+        Map<String, List<Integer>> availableServicesInfo = new HashMap<>();
+        for (SatelliteNetworkInfo plmnInfo : mAllowedSatelliteNetworkInfoList) {
+            List<Integer> allowedServicesList = new ArrayList<>();
+            if (plmnInfo.mAllowedServicesInfo != null) {
+                for (String key : plmnInfo.mAllowedServicesInfo.keySet()) {
+                    if (key.equalsIgnoreCase("data")) {
+                        allowedServicesList.add(SERVICE_TYPE_DATA);
+                    } else if (key.equalsIgnoreCase("voice")) {
+                        allowedServicesList.add(SERVICE_TYPE_VOICE);
+                    }
+                }
+                // By default sms is added to the allowed services
+                allowedServicesList.add(SERVICE_TYPE_SMS);
+                availableServicesInfo.put(plmnInfo.mPlmn, allowedServicesList);
+            }
+        }
+        return availableServicesInfo;
+    }
+
+    /**
+     * Get ServicePolicy for data at Allowed Services for the plmn List
+     *
+     * @return The Allowed Services for the plmn List
+     */
+    public Map<String, Integer> getDataServicePolicyInfoForPlmnList() {
+        return getServicePolicyInfoForServiceType("data");
+    }
+
+    /**
+     * Get ServicePolicy for voice at Allowed Services for the plmn List
+     *
+     * @return The Allowed Services for the plmn List
+     */
+    public Map<String, Integer> getVoiceServicePolicyInfoForPlmnList() {
+        return getServicePolicyInfoForServiceType("voice");
+    }
+
+    public Map<String, Integer> getServicePolicyInfoForServiceType(String serviceType) {
+        Map<String, Integer> servicePolicyInfo = new HashMap<>();
+        for (SatelliteNetworkInfo plmnInfo : mAllowedSatelliteNetworkInfoList) {
+            if (plmnInfo.mAllowedServicesInfo != null) {
+                for (String key : plmnInfo.mAllowedServicesInfo.keySet()) {
+                    if (key.equalsIgnoreCase(serviceType)) {
+                        String servicePolicy = plmnInfo.mAllowedServicesInfo.get(key);
+                        if (servicePolicy.equalsIgnoreCase("constrained")) {
+                            servicePolicyInfo.put(plmnInfo.mPlmn,
+                                    SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED);
+                        } else if (servicePolicy.equalsIgnoreCase("unconstrained")) {
+                            servicePolicyInfo.put(plmnInfo.mPlmn, SATELLITE_DATA_SUPPORT_ALL);
+                        }
+                    }
+                }
+            }
+        }
+        return servicePolicyInfo;
+    }
 }
diff --git a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
index d046f03..b4df40a 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
@@ -203,6 +203,12 @@
             android:layout_height="wrap_content"
             android:paddingRight="4dp"
             android:text="@string/setNtnSmsSupportedFalse"/>
+        <Button
+            android:id="@+id/requestSatelliteAccessConfigurationForCurrentLocation"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/requestSatelliteAccessConfigurationForCurrentLocation"/>
 
         <LinearLayout
             android:layout_width="match_parent"
diff --git a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
index 4b5ea5b..5c3a72d 100644
--- a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
+++ b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
@@ -109,4 +109,6 @@
 
     <string name="registerForModemStateChanged">registerForModemStateChanged</string>
     <string name="unregisterForModemStateChanged">unregisterForModemStateChanged</string>
+
+    <string name="requestSatelliteAccessConfigurationForCurrentLocation">requestSatelliteAccessConfigurationForCurrentLocation</string>
 </resources>
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
index 7d5e9af..5092d03 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
@@ -26,6 +26,7 @@
 import android.telephony.satellite.wrapper.CarrierRoamingNtnModeListenerWrapper2;
 import android.telephony.satellite.wrapper.NtnSignalStrengthCallbackWrapper;
 import android.telephony.satellite.wrapper.NtnSignalStrengthWrapper;
+import android.telephony.satellite.wrapper.SatelliteAccessConfigurationWrapper;
 import android.telephony.satellite.wrapper.SatelliteCapabilitiesCallbackWrapper;
 import android.telephony.satellite.wrapper.SatelliteCommunicationAllowedStateCallbackWrapper;
 import android.telephony.satellite.wrapper.SatelliteManagerWrapper;
@@ -131,6 +132,9 @@
                 .setOnClickListener(this::setNtnSmsSupportedTrue);
         findViewById(R.id.setNtnSmsSupportedFalse)
                 .setOnClickListener(this::setNtnSmsSupportedFalse);
+        findViewById(R.id.requestSatelliteAccessConfigurationForCurrentLocation)
+                .setOnClickListener(this::requestSatelliteAccessConfigurationForCurrentLocation);
+
 
 
         findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
@@ -703,6 +707,47 @@
         }
     }
 
+    private void requestSatelliteAccessConfigurationForCurrentLocation(View view) {
+        addLogMessage("requestSatelliteAccessConfigurationForCurrentLocation");
+        logd("requestSatelliteAccessConfigurationForCurrentLocation");
+        OutcomeReceiver<SatelliteAccessConfigurationWrapper,
+                SatelliteManagerWrapper.SatelliteExceptionWrapper> receiver =
+                new OutcomeReceiver<>() {
+                    @Override
+                    public void onResult(SatelliteAccessConfigurationWrapper result) {
+                        if (result != null) {
+                            addLogMessage("requestSatelliteAccessConfigurationForCurrentLocation: "
+                                    + result.getSatelliteInfos());
+                        } else {
+                            addLogMessage("requestSatelliteAccessConfigurationForCurrentLocation: "
+                                    + "null");
+                        }
+                    }
+
+                    @Override
+                    public void onError(
+                            SatelliteManagerWrapper.SatelliteExceptionWrapper exception) {
+                        if (exception != null) {
+                            String onError = "requestSatelliteAccessConfigurationForCurrentLocation"
+                                    + " exception: "
+                                    + translateResultCodeToString(exception.getErrorCode());
+                            logd(onError);
+                            addLogMessage(onError);
+                        }
+                    }
+                };
+
+        try {
+            mSatelliteManagerWrapper
+                    .requestSatelliteAccessConfigurationForCurrentLocation(mExecutor, receiver);
+        } catch (SecurityException ex) {
+            String errorMessage = "requestSatelliteAccessConfigurationForCurrentLocation: "
+                    + ex.getMessage();
+            logd(errorMessage);
+            addLogMessage(errorMessage);
+        }
+    }
+
     private void addAttachRestrictionForCarrier(View view) {
         addLogMessage("addAttachRestrictionForCarrier");
         logd("addAttachRestrictionForCarrier");
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParserTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParserTest.java
index d577a63..72fb705 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParserTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessConfigurationParserTest.java
@@ -301,7 +301,10 @@
             for (int j = 0; j < satelliteInfoArray.length(); j++) {
                 JSONObject infoJson = satelliteInfoArray.getJSONObject(i);
                 assertNull(parseSatelliteId(infoJson));
-                assertNull(parseSatellitePosition(infoJson));
+                SatellitePosition satellitePosition = parseSatellitePosition(infoJson);
+                assertNotNull(satellitePosition);
+                assertTrue(Double.isNaN(satellitePosition.getLongitudeDegrees()));
+                assertTrue(Double.isNaN(satellitePosition.getAltitudeKm()));
                 assertTrue(parseSatelliteEarfcnRangeList(infoJson).isEmpty());
                 assertNotNull(parseSatelliteBandList(infoJson));
                 assertEquals(0, parseSatelliteBandList(infoJson).size());
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
index c8013d6..315184e 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -22,6 +22,7 @@
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
 import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ACCESS_BARRED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ERROR;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_DISABLED;
 import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_NOT_AVAILABLE;
@@ -44,6 +45,7 @@
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.GOOGLE_US_SAN_SAT_S2_FILE_NAME;
 import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
@@ -54,6 +56,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -62,6 +65,7 @@
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -98,10 +102,13 @@
 import android.telecom.TelecomManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.satellite.EarfcnRange;
 import android.telephony.satellite.ISatelliteCommunicationAllowedStateCallback;
 import android.telephony.satellite.SatelliteAccessConfiguration;
 import android.telephony.satellite.SatelliteInfo;
 import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatellitePosition;
+import android.telephony.satellite.SystemSelectionSpecifier;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.Log;
@@ -136,11 +143,14 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 /** Unit test for {@link SatelliteAccessController} */
 @RunWith(AndroidTestingRunner.class)
@@ -225,6 +235,7 @@
     @Mock
     private ConcurrentHashMap<IBinder, ISatelliteCommunicationAllowedStateCallback>
             mSatelliteCommunicationAllowedStateCallbackMap;
+    private SatelliteInfo mSatelliteInfo;
 
     private TestableLooper mTestableLooper;
     private Phone[] mPhones;
@@ -288,6 +299,22 @@
         }
     };
 
+    private int mQueriedSystemSelectionChannelUpdatedResultCode = SATELLITE_RESULT_SUCCESS;
+    private Semaphore mSystemSelectionChannelUpdatedSemaphore = new Semaphore(0);
+    private ResultReceiver mSystemSelectionChannelUpdatedReceiver = new ResultReceiver(null) {
+        @Override
+        protected void onReceiveResult(int resultCode, Bundle resultData) {
+            mQueriedSystemSelectionChannelUpdatedResultCode = resultCode;
+            try {
+                mSystemSelectionChannelUpdatedSemaphore.release();
+            } catch (Exception ex) {
+                fail("mSystemSelectionChannelUpdatedReceiver: Got exception in releasing "
+                        + "semaphore, ex="
+                        + ex);
+            }
+        }
+    };
+
     @Before
     public void setUp() throws Exception {
         super.setUp();
@@ -397,6 +424,13 @@
         mMockApplicationInfo.targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
         when(mMockPackageManager.getApplicationInfo(anyString(), anyInt()))
                 .thenReturn(mMockApplicationInfo);
+
+        mSatelliteInfo = new SatelliteInfo(
+                UUID.randomUUID(),
+                new SatellitePosition(10, 15),
+                new ArrayList<>(Arrays.asList(5, 30)),
+                new ArrayList<>(Arrays.asList(new EarfcnRange(0, 250))));
+
         mSatelliteAccessControllerUT = new TestSatelliteAccessController(mMockContext,
                 mMockFeatureFlags, mTestableLooper.getLooper(), mMockLocationManager,
                 mMockTelecomManager, mMockSatelliteOnDeviceAccessController, mMockSatS2File);
@@ -633,7 +667,7 @@
         Parcel satelliteAccessconfigParcel = Parcel.obtain();
 
         List<SatelliteInfo> satelliteInfoList = new ArrayList<>();
-        satelliteInfoList.add(mock(SatelliteInfo.class));
+        satelliteInfoList.add(mSatelliteInfo);
         satelliteAccessconfigParcel.writeTypedList(satelliteInfoList);
 
         List<Integer> tagIds = new ArrayList<>(List.of(1, 2));
@@ -1451,7 +1485,7 @@
 
         // These APIs are executed during loadRemoteConfigs
         verify(mMockSharedPreferences, times(1)).getStringSet(anyString(), any());
-        verify(mMockSharedPreferences, times(1)).getBoolean(anyString(), anyBoolean());
+        verify(mMockSharedPreferences, times(5)).getBoolean(anyString(), anyBoolean());
 
         // satelliteConfig is null
         SatelliteConfigParser spyConfigParser =
@@ -1530,7 +1564,7 @@
         // Captor and Verify if the mockReceiver and mocContext is registered well
         verify(mMockContext, times(2))
                 .registerReceiver(mLocationBroadcastReceiverCaptor.capture(),
-                mIntentFilterCaptor.capture());
+                        mIntentFilterCaptor.capture());
 
         // When the intent action is not MODE_CHANGED_ACTION,
         // verify if the location manager never invoke isLocationEnabled()
@@ -1710,6 +1744,314 @@
                 any(Consumer.class));
     }
 
+    @Test
+    public void testUpdateSystemSelectionChannels() {
+        // Set non-emergency case
+        when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+        when(mMockFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
+
+        // Invoke when regional config ID is not set.
+        mSatelliteAccessControllerUT.setRegionalConfigId(null);
+        mSatelliteAccessControllerUT.updateSystemSelectionChannels(
+                mSystemSelectionChannelUpdatedReceiver);
+        mTestableLooper.processAllMessages();
+        assertTrue(waitForRequestUpdateSystemSelectionChannelResult(
+                mSystemSelectionChannelUpdatedSemaphore, 1));
+        assertEquals(SATELLITE_RESULT_ACCESS_BARRED,
+                mQueriedSystemSelectionChannelUpdatedResultCode);
+
+        // Invoke when mSatelliteAccessConfigMap does not have data for given regional config ID
+        int satelliteRegionalConfigId = DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
+        mSatelliteAccessControllerUT.setRegionalConfigId(satelliteRegionalConfigId);
+        mSatelliteAccessControllerUT.resetSatelliteAccessConfigMap();
+        mSatelliteAccessControllerUT.updateSystemSelectionChannels(
+                mSystemSelectionChannelUpdatedReceiver);
+        mTestableLooper.processAllMessages();
+        assertTrue(waitForRequestUpdateSystemSelectionChannelResult(
+                mSystemSelectionChannelUpdatedSemaphore, 1));
+        assertEquals(SATELLITE_RESULT_ACCESS_BARRED,
+                mQueriedSystemSelectionChannelUpdatedResultCode);
+
+        // Invoke when mSatelliteAccessConfigMap does not have data and given data is old format.
+        satelliteRegionalConfigId = UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID;
+        mSatelliteAccessControllerUT.setRegionalConfigId(satelliteRegionalConfigId);
+        mSatelliteAccessControllerUT.resetSatelliteAccessConfigMap();
+        mSatelliteAccessControllerUT.updateSystemSelectionChannels(
+                mSystemSelectionChannelUpdatedReceiver);
+        mTestableLooper.processAllMessages();
+        assertTrue(waitForRequestUpdateSystemSelectionChannelResult(
+                mSystemSelectionChannelUpdatedSemaphore, 1));
+        assertEquals(SATELLITE_RESULT_ACCESS_BARRED,
+                mQueriedSystemSelectionChannelUpdatedResultCode);
+
+        satelliteRegionalConfigId = DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
+        // Return success when SatelliteController.updateSystemSelectionChannels was invoked
+        setupResponseForUpdateSystemSelectionChannels(SATELLITE_RESULT_SUCCESS);
+
+        // Invoke updateSystemSelectionChannels when there is corresponding satellite access config.
+        // Create satellite info 1
+        String seed1 = "test-seed-satellite1";
+        UUID uuid1 = UUID.nameUUIDFromBytes(seed1.getBytes());
+        SatellitePosition satellitePosition1 = new SatellitePosition(0, 35876);
+        int[] bands1 = {200, 201, 202};
+        EarfcnRange earfcnRange1 = new EarfcnRange(300, 301);
+        EarfcnRange earfcnRange2 = new EarfcnRange(310, 311);
+        List<EarfcnRange> earfcnRangeList1 = new ArrayList<>(
+                Arrays.asList(earfcnRange1, earfcnRange2));
+        SatelliteInfo satelliteInfo1 = new SatelliteInfo(uuid1, satellitePosition1, Arrays.stream(
+                bands1).boxed().collect(Collectors.toList()), earfcnRangeList1);
+        // Create satellite info 2
+        String seed2 = "test-seed-satellite2";
+        UUID uuid2 = UUID.nameUUIDFromBytes(seed2.getBytes());
+        SatellitePosition satellitePosition2 = new SatellitePosition(120, 35876);
+        int[] bands2 = {210, 211, 212};
+        EarfcnRange earfcnRange3 = new EarfcnRange(320, 321);
+        EarfcnRange earfcnRange4 = new EarfcnRange(330, 331);
+        List<EarfcnRange> earfcnRangeList2 = new ArrayList<>(
+                Arrays.asList(earfcnRange3, earfcnRange4));
+        SatelliteInfo satelliteInfo2 = new SatelliteInfo(uuid2, satellitePosition2, Arrays.stream(
+                bands2).boxed().collect(Collectors.toList()), earfcnRangeList2);
+        // Create satellite info 3
+        String seed3 = "test-seed-satellite3";
+        UUID uuid3 = UUID.nameUUIDFromBytes(seed3.getBytes());
+        SatellitePosition satellitePosition3 = new SatellitePosition(120, 35876);
+        int[] bands3 = {220, 221, 222};
+        EarfcnRange earfcnRange5 = new EarfcnRange(340, 341);
+        EarfcnRange earfcnRange6 = new EarfcnRange(350, 351);
+        List<EarfcnRange> earfcnRangeList3 = new ArrayList<>(
+                Arrays.asList(earfcnRange5, earfcnRange6));
+        SatelliteInfo satelliteInfo3 = new SatelliteInfo(uuid3, satellitePosition3, Arrays.stream(
+                bands3).boxed().collect(Collectors.toList()), earfcnRangeList3);
+
+        int[] tagIds = {1, 2, 3};
+        SatelliteAccessConfiguration satelliteAccessConfiguration =
+                new SatelliteAccessConfiguration(new ArrayList<>(
+                        Arrays.asList(satelliteInfo1, satelliteInfo2, satelliteInfo3)),
+                        Arrays.stream(tagIds).boxed().collect(Collectors.toList()));
+
+        // Add satellite access configuration to map
+        mSatelliteAccessControllerUT.setSatelliteAccessConfigMap(satelliteRegionalConfigId,
+                satelliteAccessConfiguration);
+
+        // Invoke updateSystemSelectionChannel
+        mSatelliteAccessControllerUT.updateSystemSelectionChannels(
+                mSystemSelectionChannelUpdatedReceiver);
+        mTestableLooper.processAllMessages();
+        assertTrue(waitForRequestUpdateSystemSelectionChannelResult(
+                mSystemSelectionChannelUpdatedSemaphore, 1));
+        assertEquals(SATELLITE_RESULT_SUCCESS,
+                mQueriedSystemSelectionChannelUpdatedResultCode);
+        ArgumentCaptor<List<SystemSelectionSpecifier>> systemSelectionSpecifierListCaptor =
+                ArgumentCaptor.forClass(List.class);
+        verify(mMockSatelliteController, times(1)).updateSystemSelectionChannels(
+                systemSelectionSpecifierListCaptor.capture(), any(ResultReceiver.class));
+        List<SystemSelectionSpecifier> capturedList = systemSelectionSpecifierListCaptor.getValue();
+        SystemSelectionSpecifier systemSelectionSpecifier = capturedList.getFirst();
+
+        // Verify the fields value of given systemSelectionSpecifier matched with expected.
+        int[] expectedBandsArray = IntStream.concat(
+                IntStream.concat(Arrays.stream(bands1), Arrays.stream(bands2)),
+                Arrays.stream(bands3)).toArray();
+        int[] actualBandsArray = systemSelectionSpecifier.getBands();
+        assertArrayEquals(expectedBandsArray, actualBandsArray);
+
+        int[] expectedEarfcnsArray = {300, 301, 310, 311, 320, 321, 330, 331, 340, 341, 350, 351};
+        int[] actualEarfcnsArray = systemSelectionSpecifier.getEarfcns();
+        assertArrayEquals(expectedEarfcnsArray, actualEarfcnsArray);
+
+        SatelliteInfo[] expectedSatelliteInfos = {satelliteInfo1, satelliteInfo2, satelliteInfo3};
+        assertArrayEquals(expectedSatelliteInfos,
+                systemSelectionSpecifier.getSatelliteInfos().toArray(new SatelliteInfo[0]));
+
+        int[] actualTagIdArray = systemSelectionSpecifier.getTagIds();
+        assertArrayEquals(tagIds, actualTagIdArray);
+
+        // Verify backward compatibility when there is valid data for default regional config ID
+        satelliteRegionalConfigId = UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID;
+        mSatelliteAccessControllerUT.setRegionalConfigId(satelliteRegionalConfigId);
+        mSatelliteAccessControllerUT.updateSystemSelectionChannels(
+                mSystemSelectionChannelUpdatedReceiver);
+        mTestableLooper.processAllMessages();
+
+        // updateSelectionChannelResult will be invoked with the data for default regional config ID
+        assertTrue(waitForRequestUpdateSystemSelectionChannelResult(
+                mSystemSelectionChannelUpdatedSemaphore, 1));
+        systemSelectionSpecifierListCaptor = ArgumentCaptor.forClass(List.class);
+        verify(mMockSatelliteController, times(2)).updateSystemSelectionChannels(
+                systemSelectionSpecifierListCaptor.capture(), any(ResultReceiver.class));
+        capturedList = systemSelectionSpecifierListCaptor.getValue();
+        systemSelectionSpecifier = capturedList.getFirst();
+
+        // Data will be same with default regional config ID
+
+        // Verify the fields value of given systemSelectionSpecifier matched with expected.
+        actualBandsArray = systemSelectionSpecifier.getBands();
+        assertArrayEquals(expectedBandsArray, actualBandsArray);
+
+        actualEarfcnsArray = systemSelectionSpecifier.getEarfcns();
+        assertArrayEquals(expectedEarfcnsArray, actualEarfcnsArray);
+
+        assertArrayEquals(expectedSatelliteInfos,
+                systemSelectionSpecifier.getSatelliteInfos().toArray(new SatelliteInfo[0]));
+
+        actualTagIdArray = systemSelectionSpecifier.getTagIds();
+        assertArrayEquals(tagIds, actualTagIdArray);
+
+        mSatelliteAccessControllerUT.resetSatelliteAccessConfigMap();
+    }
+
+    @Test
+    public void testUpdateSystemSelectionChannels_HandleInvalidInput() {
+        // Set non-emergency case
+        when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+        when(mMockFeatureFlags.carrierRoamingNbIotNtn()).thenReturn(true);
+
+        setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+        setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+        when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
+        int satelliteRegionalConfigId = DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
+        mSatelliteAccessControllerUT.setRegionalConfigId(satelliteRegionalConfigId);
+        // Set return success when SatelliteController.updateSystemSelectionChannels was invoked
+        setupResponseForUpdateSystemSelectionChannels(SATELLITE_RESULT_SUCCESS);
+
+        // Create satellite info in which satellite position is null.
+        String seed1 = "test-seed-satellite1";
+        UUID uuid1 = UUID.nameUUIDFromBytes(seed1.getBytes());
+        SatellitePosition satellitePosition1 = null;
+        List<Integer> bandList1 = new ArrayList<>(List.of(200, 201, 202));
+        EarfcnRange earfcnRange1 = new EarfcnRange(300, 301);
+        EarfcnRange earfcnRange2 = new EarfcnRange(310, 311);
+        List<EarfcnRange> earfcnRangeList1 = new ArrayList<>(
+                Arrays.asList(earfcnRange1, earfcnRange2));
+        SatelliteInfo satelliteInfo1 = new SatelliteInfo(uuid1, satellitePosition1, bandList1,
+                earfcnRangeList1);
+
+        // Create satellite info in which band list is empty
+        String seed2 = "test-seed-satellite2";
+        UUID uuid2 = UUID.nameUUIDFromBytes(seed2.getBytes());
+        SatellitePosition satellitePosition2 = new SatellitePosition(120, 35876);
+        List<Integer> bandList2 = new ArrayList<>();
+        EarfcnRange earfcnRange3 = new EarfcnRange(320, 321);
+        EarfcnRange earfcnRange4 = new EarfcnRange(330, 331);
+        List<EarfcnRange> earfcnRangeList2 = new ArrayList<>(
+                Arrays.asList(earfcnRange3, earfcnRange4));
+        SatelliteInfo satelliteInfo2 = new SatelliteInfo(uuid2, satellitePosition2, bandList2,
+                earfcnRangeList2);
+
+        // Create satellite info 3, every field is valid
+        String seed3 = "test-seed-satellite3";
+        UUID uuid3 = UUID.nameUUIDFromBytes(seed3.getBytes());
+        SatellitePosition satellitePosition3 = new SatellitePosition(120, 35876);
+        List<Integer> bandList3 = new ArrayList<>(List.of(220, 221, 222));
+        EarfcnRange earfcnRange5 = new EarfcnRange(340, 341);
+        EarfcnRange earfcnRange6 = new EarfcnRange(350, 351);
+        List<EarfcnRange> earfcnRangeList3 = new ArrayList<>(
+                Arrays.asList(earfcnRange5, earfcnRange6));
+        SatelliteInfo satelliteInfo3 = new SatelliteInfo(uuid3, satellitePosition3, bandList3,
+                earfcnRangeList3);
+        // Add empty tagId list
+        List<Integer> tagIdList = new ArrayList<>();
+
+        // Create satelliteAccessConfiguration with some of files of added Satellite info are empty.
+        SatelliteAccessConfiguration satelliteAccessConfiguration1 =
+                new SatelliteAccessConfiguration(new ArrayList<>(
+                        Arrays.asList(satelliteInfo1, satelliteInfo2, satelliteInfo3)), tagIdList);
+
+        // Add satellite access configuration to map
+        mSatelliteAccessControllerUT.setSatelliteAccessConfigMap(satelliteRegionalConfigId,
+                satelliteAccessConfiguration1);
+
+        // Invoke updateSystemSelectionChannel
+        mSatelliteAccessControllerUT.updateSystemSelectionChannels(
+                mSystemSelectionChannelUpdatedReceiver);
+        mTestableLooper.processAllMessages();
+        assertTrue(waitForRequestUpdateSystemSelectionChannelResult(
+                mSystemSelectionChannelUpdatedSemaphore, 1));
+        assertEquals(SATELLITE_RESULT_SUCCESS,
+                mQueriedSystemSelectionChannelUpdatedResultCode);
+        ArgumentCaptor<List<SystemSelectionSpecifier>> systemSelectionSpecifierListCaptor =
+                ArgumentCaptor.forClass(List.class);
+        verify(mMockSatelliteController, times(1)).updateSystemSelectionChannels(
+                systemSelectionSpecifierListCaptor.capture(), any(ResultReceiver.class));
+        List<SystemSelectionSpecifier> capturedList = systemSelectionSpecifierListCaptor.getValue();
+        SystemSelectionSpecifier systemSelectionSpecifier = capturedList.getFirst();
+
+        // Verify the fields value of given systemSelectionSpecifier matched with expected.
+        List<Integer> expectedBandList = new ArrayList<>(bandList1);
+        expectedBandList.addAll(bandList2);
+        expectedBandList.addAll(bandList3);
+
+        List<Integer> actualBandList = Arrays.stream(systemSelectionSpecifier.getBands()).boxed()
+                .collect(Collectors.toList());
+        assertEquals(expectedBandList, actualBandList);
+
+        List<Integer> expectedEarfcnList = new ArrayList<>(
+                List.of(300, 301, 310, 311, 320, 321, 330, 331, 340, 341, 350, 351));
+        List<Integer> actualEarfcnList = Arrays.stream(systemSelectionSpecifier.getEarfcns())
+                .boxed().collect(Collectors.toList());
+        assertEquals(expectedEarfcnList, actualEarfcnList);
+
+        assertEquals(satelliteInfo1, systemSelectionSpecifier.getSatelliteInfos().get(0));
+        assertEquals(satelliteInfo2, systemSelectionSpecifier.getSatelliteInfos().get(1));
+        assertEquals(satelliteInfo3, systemSelectionSpecifier.getSatelliteInfos().get(2));
+
+        List<Integer> actualTagIdList = Arrays.stream(systemSelectionSpecifier.getTagIds()).boxed()
+                .collect(Collectors.toList());
+        assertEquals(tagIdList, actualTagIdList);
+
+        // Create satelliteAccessConfiguration with empty list of SatelliteInfo.
+        SatelliteAccessConfiguration satelliteAccessConfiguration2 =
+                new SatelliteAccessConfiguration(new ArrayList<>(), tagIdList);
+        mSatelliteAccessControllerUT.setSatelliteAccessConfigMap(
+                DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, satelliteAccessConfiguration2);
+
+        // Invoke updateSystemSelectionChannel
+        mSatelliteAccessControllerUT.updateSystemSelectionChannels(
+                mSystemSelectionChannelUpdatedReceiver);
+        mTestableLooper.processAllMessages();
+        assertTrue(waitForRequestUpdateSystemSelectionChannelResult(
+                mSystemSelectionChannelUpdatedSemaphore, 1));
+        assertEquals(SATELLITE_RESULT_SUCCESS,
+                mQueriedSystemSelectionChannelUpdatedResultCode);
+        systemSelectionSpecifierListCaptor = ArgumentCaptor.forClass(List.class);
+        verify(mMockSatelliteController, times(2)).updateSystemSelectionChannels(
+                systemSelectionSpecifierListCaptor.capture(), any(ResultReceiver.class));
+        capturedList = systemSelectionSpecifierListCaptor.getValue();
+        systemSelectionSpecifier = capturedList.getFirst();
+
+        // Verify the fields value of given systemSelectionSpecifier matched with expected.
+        assertEquals(0, systemSelectionSpecifier.getBands().length);
+        assertEquals(0, systemSelectionSpecifier.getEarfcns().length);
+
+        SatelliteInfo[] expectedSatelliteInfoArray = new SatelliteInfo[0];
+        assertArrayEquals(expectedSatelliteInfoArray,
+                systemSelectionSpecifier.getSatelliteInfos().toArray(new SatelliteInfo[0]));
+
+        actualTagIdList = Arrays.stream(systemSelectionSpecifier.getTagIds()).boxed().collect(
+                Collectors.toList());
+        assertEquals(tagIdList, actualTagIdList);
+
+        mSatelliteAccessControllerUT.resetSatelliteAccessConfigMap();
+    }
+
+    @Test
+    public void testCheckSharedPreferenceException() {
+        doReturn(mMockSharedPreferencesEditor).when(mMockSharedPreferencesEditor)
+                .remove(anyString());
+        doThrow(new ClassCastException()).when(mMockSharedPreferences)
+                .getBoolean(anyString(), eq(false));
+
+        mSatelliteAccessControllerUT = new TestSatelliteAccessController(mMockContext,
+                mMockFeatureFlags, mTestableLooper.getLooper(), mMockLocationManager,
+                mMockTelecomManager, mMockSatelliteOnDeviceAccessController, mMockSatS2File);
+
+        verify(mMockSharedPreferencesEditor, times(4)).remove(anyString());
+    }
+
     private void sendSatelliteCommunicationAllowedEvent() {
         Pair<Integer, ResultReceiver> requestPair =
                 new Pair<>(DEFAULT_SUBSCRIPTION_ID,
@@ -1721,7 +2063,6 @@
         mTestableLooper.processAllMessages();
     }
 
-
     private void sendConfigUpdateChangedEvent(Context context) {
         Message msg = mSatelliteAccessControllerUT.obtainMessage(EVENT_CONFIG_DATA_UPDATED);
         msg.obj = new AsyncResult(context, SATELLITE_RESULT_SUCCESS, null);
@@ -1774,6 +2115,24 @@
         return true;
     }
 
+    private boolean waitForRequestUpdateSystemSelectionChannelResult(Semaphore semaphore,
+            int expectedNumberOfEvents) {
+        for (int i = 0; i < expectedNumberOfEvents; i++) {
+            try {
+                if (!semaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) {
+                    logd("Timeout to receive "
+                            + "updateSystemSelectionChannel()"
+                            + " callback");
+                    return false;
+                }
+            } catch (Exception ex) {
+                logd("updateSystemSelectionChannel: Got exception=" + ex);
+                return false;
+            }
+        }
+        return true;
+    }
+
     private void sendLocationRequestResult(Location location) {
         mLocationRequestConsumerCaptor.getValue().accept(location);
         mTestableLooper.processAllMessages();
@@ -1810,6 +2169,16 @@
         }).when(mMockSatelliteController).requestIsSatelliteProvisioned(any(ResultReceiver.class));
     }
 
+    private void setupResponseForUpdateSystemSelectionChannels(
+            @SatelliteManager.SatelliteResult int error) {
+        doAnswer(invocation -> {
+            ResultReceiver resultReceiver = invocation.getArgument(1);
+            resultReceiver.send(error, null);
+            return null;
+        }).when(mMockSatelliteController).updateSystemSelectionChannels(anyList(),
+                any(ResultReceiver.class));
+    }
+
     @SafeVarargs
     private static <E> List<E> listOf(E... values) {
         return Arrays.asList(values);
@@ -1925,5 +2294,25 @@
                 mRegionalConfigId = regionalConfigId;
             }
         }
+
+        public void setSatelliteAccessConfigMap(int regionalConfigId,
+                SatelliteAccessConfiguration satelliteAccessConfiguration) {
+            synchronized (mLock) {
+                if (mSatelliteAccessConfigMap == null) {
+                    mSatelliteAccessConfigMap = new HashMap<>();
+                }
+                mSatelliteAccessConfigMap.put(regionalConfigId, satelliteAccessConfiguration);
+            }
+        }
+
+        public void resetSatelliteAccessConfigMap() {
+            synchronized (mLock) {
+                if (mSatelliteAccessConfigMap == null) {
+                    mSatelliteAccessConfigMap = new HashMap<>();
+                } else {
+                    mSatelliteAccessConfigMap.clear();
+                }
+            }
+        }
     }
 }
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
index f41f861..a3b38df 100644
--- a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
@@ -16,6 +16,13 @@
 
 package com.android.phone.satellite.entitlement;
 
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_VOICE;
+
+import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_DATA_PLAN_METERED;
+import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_DATA_PLAN_UNMETERED;
 import static com.android.libraries.entitlement.ServiceEntitlementException.ERROR_HTTP_STATUS_NOT_SUCCESS;
 import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_DISABLED;
 import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_ENABLED;
@@ -28,6 +35,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyMap;
 import static org.mockito.ArgumentMatchers.anyVararg;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
@@ -91,7 +99,28 @@
     private static final int DEFAULT_QUERY_REFRESH_DAY = 7;
     private static final List<String> PLMN_ALLOWED_LIST = Arrays.asList("31026", "302820");
     private static final List<String> PLMN_BARRED_LIST = Arrays.asList("12345", "98765");
+    private static final Map<String, Integer> PLMN_DATA_PLAN_LIST = Map.of(
+            "31026", SATELLITE_DATA_PLAN_METERED,
+            "302820", SATELLITE_DATA_PLAN_UNMETERED);
     private static final List<String> EMPTY_PLMN_LIST = new ArrayList<>();
+    private static final Map<String, Integer> EMPTY_PLMN_DATA_PLAN_LIST = new HashMap<>();
+    private static final Map<String, List<Integer>> PLMN_ALLOWED_SERVICES_LIST = Map.of(
+            "31026", List.of(SERVICE_TYPE_DATA),
+            "302820", List.of(SERVICE_TYPE_DATA, SERVICE_TYPE_VOICE)
+    );
+    private static final Map<String, Integer> PLMN_DATA_SERVICE_POLICY_LIST = Map.of(
+            "31026", SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED,
+            "302820", SATELLITE_DATA_SUPPORT_ALL);
+    private static final Map<String, Integer> PLMN_VOICE_SERVICE_POLICY_LIST = Map.of(
+            "31026", SATELLITE_DATA_SUPPORT_ALL,
+            "302820", SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED
+    );
+    private static final Map<String, List<Integer>> EMPTY_PLMN_ALLOWED_SERVICES_LIST =
+            new HashMap<>();
+    private static final Map<String, Integer> EMPTY_PLMN_DATA_SERVICE_POLICY_LIST =
+            new HashMap<>();
+    private static final Map<String, Integer> EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST =
+            new HashMap<>();
     private static final int CMD_START_QUERY_ENTITLEMENT = 1;
     private static final int CMD_RETRY_QUERY_ENTITLEMENT = 2;
     private static final int CMD_SIM_REFRESH = 3;
@@ -173,7 +202,7 @@
 
         verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         mCarrierConfigBundle.putBoolean(
                 CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
@@ -184,7 +213,7 @@
 
         verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         setInternetConnected(true);
         // Verify don't start the query when last query refresh time is not expired.
@@ -193,7 +222,7 @@
 
         verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         setLastQueryTime(0L);
         // Verify don't start the query when retry count is reached max
@@ -206,7 +235,7 @@
 
         verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         replaceInstance(SatelliteEntitlementController.class, "mRetryCountPerSub",
                 mSatelliteEntitlementController, new HashMap<>());
@@ -220,7 +249,7 @@
 
         verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         replaceInstance(SatelliteEntitlementController.class, "mIsEntitlementInProgressPerSub",
                 mSatelliteEntitlementController, new HashMap<>());
@@ -228,12 +257,13 @@
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
     }
 
     @Test
@@ -246,7 +276,7 @@
         verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
         // Verify don't call the updateSatelliteEntitlementStatus.
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // Verify call the checkSatelliteEntitlementStatus with invalid response.
         setIsQueryAvailableTrue();
@@ -261,7 +291,10 @@
         // Verify call the updateSatelliteEntitlementStatus with satellite service is disabled
         // , empty PLMNAllowed and empty PLMNBarred.
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
-                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(EMPTY_PLMN_DATA_PLAN_LIST), eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST),
+                eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST), eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST),
+                any());
 
         // Verify call the checkSatelliteEntitlementStatus with the subscribed result.
         clearInvocationsForMock();
@@ -269,14 +302,17 @@
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
         // availablePLMNAllowedList and availablePLMNBarredList.
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
 
         // Change subId and verify call the updateSatelliteEntitlementStatus with satellite
         // service is enable, availablePLMNAllowedList and availablePLMNBarredList
@@ -287,43 +323,54 @@
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID_2), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
 
         // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
         // availablePLMNAllowedList and empty plmn barred list.
         clearInvocationsForMock();
         setIsQueryAvailableTrue();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                new ArrayList<>());
+                new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+                new HashMap<>());
         mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_DATA_PLAN_LIST),
+                eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST), eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST), any());
 
         // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
         // empty PLMNAllowedList and PLMNBarredList.
         clearInvocationsForMock();
         setIsQueryAvailableTrue();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, new ArrayList<>(),
-                new ArrayList<>());
+                new ArrayList<>(), new HashMap<>(), new HashMap<>(), new HashMap<>(),
+                new HashMap<>());
         mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_DATA_PLAN_LIST),
+                eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST), eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST), any());
 
         // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
         // empty PLMNAllowedList and availablePLMNBarredList.
         clearInvocationsForMock();
         setIsQueryAvailableTrue();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, new ArrayList<>(),
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(EMPTY_PLMN_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(EMPTY_PLMN_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -336,7 +383,8 @@
         setInternetConnected(true);
         setLastQueryTime(0L);
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
 
         networkCallback.onAvailable(mockNetwork);
         mTestableLooper.processAllMessages();
@@ -344,7 +392,9 @@
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         // Verify call the updateSatelliteEntitlementStatus with satellite service is available.
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -354,13 +404,16 @@
         setInternetConnected(true);
         setLastQueryTime(0L);
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         triggerCarrierConfigChanged();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         // Verify call the updateSatelliteEntitlementStatus with satellite service is available.
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -429,7 +482,10 @@
 
         // Verify only called onSatelliteEntitlementStatusUpdated once.
         verify(mSatelliteController, times(1)).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
-                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(EMPTY_PLMN_DATA_PLAN_LIST), eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST),
+                eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST), any());
 
         // Verify that the query is not restarted after reaching the maximum retry count even if
         // a start cmd is received.
@@ -525,7 +581,10 @@
 
         // Verify only called onSatelliteEntitlementStatusUpdated once.
         verify(mSatelliteController, times(1)).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
-                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(EMPTY_PLMN_DATA_PLAN_LIST), eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST),
+                eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST), eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST),
+                any());
     }
 
     @Test
@@ -540,7 +599,10 @@
         verify(mSatelliteEntitlementApi, times(1)).checkEntitlementStatus();
         assertNull(retryCountPerSub.get(SUB_ID));
         verify(mSatelliteController, times(1)).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
-                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(EMPTY_PLMN_DATA_PLAN_LIST), eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST),
+                eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -561,13 +623,16 @@
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
         mTestableLooper.processAllMessages();
         verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
         assertNull(retryCountPerSub.get(SUB_ID));
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -590,7 +655,7 @@
         assertNotNull(exponentialBackoffPerSub.get(SUB_ID));
         // Verify don't call the onSatelliteEntitlementStatusUpdated.
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // Verify the retry in progress.
         sendMessage(CMD_RETRY_QUERY_ENTITLEMENT, SUB_ID);
@@ -599,21 +664,24 @@
         assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
         // Verify don't call the onSatelliteEntitlementStatusUpdated.
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // Received the 200 response, Verify call the onSatelliteEntitlementStatusUpdated.
         setIsQueryAvailableTrue();
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
 
         sendMessage(CMD_RETRY_QUERY_ENTITLEMENT, SUB_ID);
         mTestableLooper.processAllMessages();
         verify(mSatelliteEntitlementApi, times(3)).checkEntitlementStatus();
         assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -625,14 +693,18 @@
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_DISABLED, EMPTY_PLMN_LIST,
-                EMPTY_PLMN_LIST);
+                EMPTY_PLMN_LIST, EMPTY_PLMN_DATA_PLAN_LIST, EMPTY_PLMN_ALLOWED_SERVICES_LIST,
+                EMPTY_PLMN_DATA_SERVICE_POLICY_LIST, EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST);
         sendMessage(CMD_START_QUERY_ENTITLEMENT, SUB_ID);
         mTestableLooper.processAllMessages();
 
         // Verify call the onSatelliteEntitlementStatusUpdated - entitlement status false
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
-                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(EMPTY_PLMN_DATA_PLAN_LIST), eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST),
+                eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST), eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST),
+                any());
 
         // Verify call the onSatelliteEntitlementStatusUpdated - entitlement status true
         mCarrierConfigBundle.putBoolean(
@@ -641,7 +713,10 @@
         mTestableLooper.processAllMessages();
 
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
-                eq(true), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(true), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(EMPTY_PLMN_DATA_PLAN_LIST), eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST),
+                eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST), eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST),
+                any());
 
         // KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL changed from Support(entitlement status
         // enabled) to not support.
@@ -650,14 +725,17 @@
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         sendMessage(CMD_START_QUERY_ENTITLEMENT, SUB_ID);
         mTestableLooper.processAllMessages();
 
         // Verify call the onSatelliteEntitlementStatusUpdated - entitlement status true.
         verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
-                eq(true), eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(true), eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST),
+                eq(PLMN_DATA_PLAN_LIST), eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
 
         // Verify not call the onSatelliteEntitlementStatusUpdated.
         clearInvocationsForMock();
@@ -667,7 +745,9 @@
         mTestableLooper.processAllMessages();
 
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                eq(true), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(true), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(PLMN_DATA_PLAN_LIST), eq(PLMN_ALLOWED_SERVICES_LIST),
+                eq(PLMN_DATA_SERVICE_POLICY_LIST), eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -680,13 +760,14 @@
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         sendMessage(CMD_START_QUERY_ENTITLEMENT, SUB_ID);
         mTestableLooper.processAllMessages();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // After move to the refresh time, verify the query started and success.
         setLastQueryTime(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1) - 1000);
@@ -695,7 +776,7 @@
 
         verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
         verify(mSatelliteController, times(2)).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
     }
 
     @Test
@@ -710,20 +791,23 @@
 
         verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // Verify the query start and success after internet connected.
         setInternetConnected(true);
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         sendMessage(CMD_START_QUERY_ENTITLEMENT, SUB_ID);
         mTestableLooper.processAllMessages();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -737,7 +821,7 @@
         mTestableLooper.processAllMessages();
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // Verify whether the second query has been triggered and whether
         // onSatelliteEntitlementStatusUpdated has been called after received the 500 error.
@@ -747,7 +831,10 @@
         mTestableLooper.processAllMessages();
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
-                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST), any());
+                eq(false), eq(EMPTY_PLMN_LIST), eq(EMPTY_PLMN_LIST),
+                eq(EMPTY_PLMN_DATA_PLAN_LIST), eq(EMPTY_PLMN_ALLOWED_SERVICES_LIST),
+                eq(EMPTY_PLMN_DATA_SERVICE_POLICY_LIST), eq(EMPTY_PLMN_VOICE_SERVICE_POLICY_LIST),
+                any());
     }
 
     @Test
@@ -761,7 +848,7 @@
         mTestableLooper.processAllMessages();
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // Verify whether the second query was triggered and onSatelliteEntitlementStatusUpdated
         // was not called after received a 503 error without valid retry-after header.
@@ -771,20 +858,23 @@
         mTestableLooper.processAllMessages();
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // Verify whether the third query was triggered and onSatelliteEntitlementStatusUpdated
         // was called after received a success case.
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         mTestableLooper.moveTimeForward(TimeUnit.MINUTES.toMillis(10));
         mTestableLooper.processAllMessages();
 
         verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
-                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+                eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), eq(PLMN_DATA_PLAN_LIST),
+                eq(PLMN_ALLOWED_SERVICES_LIST), eq(PLMN_DATA_SERVICE_POLICY_LIST),
+                eq(PLMN_VOICE_SERVICE_POLICY_LIST), any());
     }
 
     @Test
@@ -795,12 +885,13 @@
         doReturn(mSatelliteEntitlementResult).when(
                 mSatelliteEntitlementApi).checkEntitlementStatus();
         setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
-                PLMN_BARRED_LIST);
+                PLMN_BARRED_LIST, PLMN_DATA_PLAN_LIST, PLMN_ALLOWED_SERVICES_LIST,
+                PLMN_DATA_SERVICE_POLICY_LIST, PLMN_VOICE_SERVICE_POLICY_LIST);
         mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
 
         verify(mSatelliteEntitlementApi).checkEntitlementStatus();
         verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+                anyBoolean(), anyList(), anyList(), anyMap(), anyMap(), anyMap(), anyMap(), any());
 
         // SIM_REFRESH event occurred before expired the query refresh timer, verify the start
         // the query.
@@ -809,8 +900,9 @@
         mTestableLooper.processAllMessages();
 
         verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
-        verify(mSatelliteController, times(2)).onSatelliteEntitlementStatusUpdated(anyInt(),
-                anyBoolean(), anyList(), anyList(), any());
+        verify(mSatelliteController, times(2))
+                .onSatelliteEntitlementStatusUpdated(anyInt(), anyBoolean(), anyList(), anyList(),
+                        anyMap(), anyMap(), anyMap(), anyMap(), any());
     }
 
     private void triggerCarrierConfigChanged() {
@@ -868,10 +960,21 @@
     }
 
     private void setSatelliteEntitlementResult(int entitlementStatus,
-            List<String> plmnAllowedList, List<String> plmnBarredList) {
+            List<String> plmnAllowedList, List<String> plmnBarredList,
+            Map<String,Integer> plmnDataPlanMap,
+            Map<String,List<Integer>> plmnAllowedServicesMap,
+            Map<String,Integer> plmnDataServicePolicyMap,
+            Map<String,Integer> plmnVoiceServicePolicyMap) {
         doReturn(entitlementStatus).when(mSatelliteEntitlementResult).getEntitlementStatus();
         doReturn(plmnAllowedList).when(mSatelliteEntitlementResult).getAllowedPLMNList();
         doReturn(plmnBarredList).when(mSatelliteEntitlementResult).getBarredPLMNList();
+        doReturn(plmnDataPlanMap).when(mSatelliteEntitlementResult).getDataPlanInfoForPlmnList();
+        doReturn(plmnAllowedServicesMap).when(mSatelliteEntitlementResult)
+                .getAvailableServiceTypeInfoForPlmnList();
+        doReturn(plmnDataServicePolicyMap).when(mSatelliteEntitlementResult)
+                .getDataServicePolicyInfoForPlmnList();
+        doReturn(plmnVoiceServicePolicyMap).when(mSatelliteEntitlementResult)
+                .getVoiceServicePolicyInfoForPlmnList();
     }
 
     private void setLastQueryTime(Long lastQueryTime) throws Exception {
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
index 8e45a73..92dd997 100644
--- a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
@@ -16,6 +16,11 @@
 
 package com.android.phone.satellite.entitlement;
 
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL;
+import static android.telephony.CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_VOICE;
+
 import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_DISABLED;
 import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_ENABLED;
 import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE;
@@ -34,13 +39,17 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 @RunWith(AndroidJUnit4.class)
 public class SatelliteEntitlementResponseTest {
     private static final String TEST_OTHER_APP_ID = "ap201x";
+
     private static final List<SatelliteNetworkInfo> TEST_PLMN_DATA_PLAN_TYPE_LIST = Arrays.asList(
-            new SatelliteNetworkInfo("31026", "unmetered"),
-            new SatelliteNetworkInfo("302820", "metered"));
+            new SatelliteNetworkInfo("31026", "unmetered",
+                    Map.of("data","constrained")),
+            new SatelliteNetworkInfo("302820", "metered",
+                    Map.of("voice","unconstrained")));
     private static final List<String> TEST_PLMN_BARRED_LIST = Arrays.asList("31017", "302020");
     private static final String RESPONSE_WITHOUT_SATELLITE_APP_ID =
             "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
@@ -77,10 +86,14 @@
                 response.getPlmnAllowed().get(0).mPlmn);
         assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(0).mDataPlanType,
                 response.getPlmnAllowed().get(0).mDataPlanType);
+        assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(0).mAllowedServicesInfo,
+                response.getPlmnAllowed().get(0).mAllowedServicesInfo);
         assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(1).mPlmn,
                 response.getPlmnAllowed().get(1).mPlmn);
         assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(1).mDataPlanType,
                 response.getPlmnAllowed().get(1).mDataPlanType);
+        assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(1).mAllowedServicesInfo,
+                response.getPlmnAllowed().get(1).mAllowedServicesInfo);
         assertTrue(response.getPlmnBarredList().size() == 2);
         assertEquals(TEST_PLMN_BARRED_LIST, response.getPlmnBarredList());
 
@@ -207,15 +220,17 @@
 
     private String getPLMNListOrEmpty(int entitlementStatus) {
         return entitlementStatus == SATELLITE_ENTITLEMENT_STATUS_ENABLED ? ","
-                + "\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\"},"
-                + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\"}],"
+                + "\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\",\"AllowedServicesInfo\":[{\"AllowedServices\":{\"ServiceType\":\"data\",\"ServicePolicy\":\"constrained\"}}]},"
+                + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\",\"AllowedServicesInfo\":[{\"AllowedServices\":{\"ServiceType\":\"voice\",\"ServicePolicy\":\"unconstrained\"}}]}],"
                 + "\"PLMNBarred\":[{\"PLMN\":\"31017\"},"
                 + "{\"PLMN\":\"302020\"}]" : "";
     }
 
     private String getAllowedPlmns(String firstPlmn, String secondPlmn) {
-        return ",\"PLMNAllowed\":[{\"PLMN\":\"" + firstPlmn + "\",\"DataPlanType\":\"unmetered\"},"
-                + "{\"PLMN\":\"" + secondPlmn + "\",\"DataPlanType\":\"metered\"}]";
+        return ",\"PLMNAllowed\":[{\"PLMN\":\"" + firstPlmn +
+                "\",\"DataPlanType\":\"unmetered\",\"AllowedServicesInfo\":[{\"AllowedServices\":{\"ServiceType\":\"data\",\"ServicePolicy\":\"constrained\"}}]},"
+                + "{\"PLMN\":\"" + secondPlmn +
+                "\",\"DataPlanType\":\"metered\",\"AllowedServicesInfo\":[{\"AllowedServices\":{\"ServiceType\":\"voice\",\"ServicePolicy\":\"unconstrained\"}}]}]";
     }
 
     private String getBarredPlmns(String firstPlmn, String secondPlmn) {
@@ -237,8 +252,8 @@
                 + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
                 + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
                 + "\"EntitlementStatus\":\"" + SATELLITE_ENTITLEMENT_STATUS_ENABLED + "\""
-                + ",\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\"},"
-                + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\"}]"
+                + ",\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\",\"AllowedServicesInfo\":[{\"AllowedServices\":{\"ServiceType\":\"data\",\"ServicePolicy\":\"constrained\"}}]},"
+                + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\",\"AllowedServicesInfo\":[{\"AllowedServices\":{\"ServiceType\":\"voice\",\"ServicePolicy\":\"unconstrained\"}}]}]"
                 + getBarredPlmns(firstPlmn, secondPlmn)
                 + "}}";
     }